Merge remote-tracking branch 'origin/jxgtwcs' into jxgtwcs
| | |
| | | width: 48, |
| | | }, |
| | | { |
| | | title: 'ID', |
| | | dataIndex: 'id', |
| | | valueType: 'text', |
| | | hidden: false, |
| | | width: 140, |
| | | filterDropdown: (props) => <TextFilter |
| | | name='uuid' |
| | | {...props} |
| | | actionRef={actionRef} |
| | | setSearchParam={setSearchParam} |
| | | />, |
| | | }, |
| | | { |
| | | title: '编号', |
| | | dataIndex: 'uuid', |
| | | valueType: 'text', |
| | |
| | | |
| | | // 入库 ===>> 入库站到堆垛机站,根据条码扫描生成入库工作档 |
| | | mainService.generateInboundWrk(); // 组托 |
| | | mainService.palletInbound();//入库-托盘进库 |
| | | |
| | | // 解析出库工作档 |
| | | mainService.analyzeOutBoundTask(); |
| | | // 解析入库工作档 |
| | |
| | | response = shuttleThread.updateLocation(command); |
| | | } |
| | | |
| | | // News.info("四向穿梭车命令下发,穿梭车号={},任务数据={}", device.getDeviceNo(), JSON.toJSON(command)); |
| | | News.info("四向穿梭车命令下发,穿梭车号={},任务数据={}", device.getDeviceNo(), JSON.toJSON(command)); |
| | | return response; |
| | | } |
| | | |
| | |
| | | package com.zy.asrs.wcs.core.domain.dto; |
| | | |
| | | import com.zy.asrs.wcs.core.BuildSupport; |
| | | import com.zy.asrs.wcs.rcs.entity.Device; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | //执行完成后是否释放穿梭车,默认不释放 1: 释放 0: 不释放 |
| | | private Integer releaseShuttle; |
| | | |
| | | private Device shuttleDevice; |
| | | |
| | | public static MotionDto build(BuildSupport<MotionDto> support) { |
| | | MotionDto dto = new MotionDto(); |
| | | |
| | |
| | | |
| | | private Integer staNo; |
| | | |
| | | private Integer deviceStaNo; |
| | | |
| | | private Integer barcode; |
| | | |
| | | private Integer backSta; |
| | |
| | | @ApiModelProperty(value= "拣料出库站点列表") |
| | | private String pickOutSta; |
| | | |
| | | /** |
| | | * 设备入库站点列表 |
| | | */ |
| | | @ApiModelProperty(value= "设备入库站点列表") |
| | | private String deviceInSta; |
| | | |
| | | /** |
| | | * 设备出库站点列表 |
| | | */ |
| | | @ApiModelProperty(value= "设备出库站点列表") |
| | | private String deviceOutSta; |
| | | |
| | | public BasConveyor() {} |
| | | |
| | | public BasConveyor(Long deviceId,Integer conveyorNo,Long updateBy,Long createBy,Date createTime,Date updateTime,String memo,Integer deleted,Long hostId,String inSta,String emptyInSta,String pickInSta,String outSta,String emptyOutSta,String pickOutSta) { |
| | |
| | | @ApiModelProperty(value= "所属机构") |
| | | private Long hostId; |
| | | |
| | | /** |
| | | * 移动路径 |
| | | */ |
| | | @ApiModelProperty(value= "移动路径") |
| | | private String movePath; |
| | | |
| | | public Motion() {} |
| | | |
| | | public Motion(String uuid,Integer taskNo,String serialNo,String title,Integer priority,Integer sync,Long motionCtg,Long motionSts,Long deviceCtg,String device,String origin,Integer oriDrt,String target,Integer tarDrt,String dockNo,Date ioTime,Date startTime,Date endTime,Date errTime,Long errCode,String errDesc,String temp,Integer status,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo,Integer deleted,Long hostId) { |
| | |
| | | |
| | | String shuttleLocNo = shuttleProtocol.getCurrentLocNo(); |
| | | |
| | | //获取距离目标位置最近的空闲可换层提升机 |
| | | LiftThread liftThread = liftDispatcher.searchIdleLift(shuttleLocNo, task.getHostId(), true); |
| | | //获取距离目标位置最近的可换层提升机(可能不空闲) |
| | | LiftThread liftThread = liftDispatcher.searchLift(shuttleLocNo, task.getHostId(), true); |
| | | if (liftThread == null) { |
| | | return motionList; |
| | | } |
| | |
| | | // 入库目标层有穿梭车 |
| | | if (Utils.getLev(shuttleLocNo) == Utils.getLev(task.getDestLoc())) { |
| | | |
| | | // 提升机载货移动 |
| | | motionList.addAll(kernelService.liftMoveGoods( |
| | | MotionDto.build((dto -> { |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLev(1);//光泰1层是输送线层 |
| | | dto.setStaNo(31004);//入库站点 |
| | | })) |
| | | , MotionDto.build((dto -> { |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLev(Utils.getLev(task.getDestLoc())); |
| | | dto.setStaNo(getStaByLev(Utils.getLev(task.getDestLoc()))); |
| | | dto.setDevpNo(basConveyorStaDest.getConveyorDeviceId().intValue()); |
| | | dto.setReleaseLift(1);//执行完成后释放提升机 |
| | | })) |
| | | )); |
| | | // // 提升机载货移动 |
| | | // motionList.addAll(kernelService.liftMoveGoods( |
| | | // MotionDto.build((dto -> { |
| | | // dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | // dto.setLev(1);//光泰1层是输送线层 |
| | | // dto.setStaNo(31004);//入库站点 |
| | | // })) |
| | | // , MotionDto.build((dto -> { |
| | | // dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | // dto.setLev(Utils.getLev(task.getDestLoc())); |
| | | // dto.setStaNo(getStaByLev(Utils.getLev(task.getDestLoc()))); |
| | | // dto.setDevpNo(basConveyorStaDest.getConveyorDeviceId().intValue()); |
| | | // dto.setReleaseLift(1);//执行完成后释放提升机 |
| | | // })) |
| | | // )); |
| | | |
| | | // 穿梭车走行至提升机库位待机位 |
| | | motionList.addAll(kernelService.shuttleMove( |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(standbyLocNoTo); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLocNo(destLoc); |
| | | // dto.setReleaseLift(2);//执行中释放提升机 |
| | |
| | | */ |
| | | } else { |
| | | |
| | | // 提升机载货移动 |
| | | motionList.addAll(kernelService.liftMoveGoods( |
| | | MotionDto.build((dto -> { |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLev(1);//光泰1层是输送线层 |
| | | dto.setStaNo(31004);//入库站点 |
| | | })) |
| | | , MotionDto.build((dto -> { |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLev(Utils.getLev(task.getDestLoc())); |
| | | dto.setStaNo(getStaByLev(Utils.getLev(task.getDestLoc()))); |
| | | dto.setDevpNo(basConveyorStaDest.getConveyorDeviceId().intValue()); |
| | | dto.setReleaseLift(1);//执行完成后释放提升机 |
| | | })) |
| | | )); |
| | | // // 提升机载货移动 |
| | | // motionList.addAll(kernelService.liftMoveGoods( |
| | | // MotionDto.build((dto -> { |
| | | // dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | // dto.setLev(1);//光泰1层是输送线层 |
| | | // dto.setStaNo(31004);//入库站点 |
| | | // })) |
| | | // , MotionDto.build((dto -> { |
| | | // dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | // dto.setLev(Utils.getLev(task.getDestLoc())); |
| | | // dto.setStaNo(getStaByLev(Utils.getLev(task.getDestLoc()))); |
| | | // dto.setDevpNo(basConveyorStaDest.getConveyorDeviceId().intValue()); |
| | | // dto.setReleaseLift(1);//执行完成后释放提升机 |
| | | // })) |
| | | // )); |
| | | |
| | | // 穿梭车走行至提升机库位待机位 |
| | | motionList.addAll(kernelService.shuttleMove( |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLocNo(standbyLocNoTo); |
| | | })), |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLocNo(liftLocNoTo); |
| | | })), |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(standbyLocNoFrom); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE_FROM_LIFT |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLocNo(destLoc); |
| | | })), |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(originLoc); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(lastPathStartLoc); |
| | | })), |
| | | MotionCtgType.SHUTTLE_TRANSPORT |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLocNo(standbyLocNoTo); |
| | | dto.setStaNo(getStaByLev(Utils.getLev(task.getOriginLoc())));//输送站 |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(standbyLocs); |
| | | dto.setSync(0);//异步执行 |
| | | dto.setReleaseShuttle(1);//执行完成后释放小车 |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLocNo(standbyLocNoTo); |
| | | })), |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLocNo(liftLocNoTo); |
| | | })), |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(standbyLocNoFrom); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE_FROM_LIFT |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(originLoc); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(lastPathStartLoc); |
| | | })), |
| | | MotionCtgType.SHUTTLE_TRANSPORT |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLocNo(standbyLocNoFrom); |
| | | dto.setStaNo(getStaByLev(Utils.getLev(task.getOriginLoc())));//输送站 |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(standbyLocs); |
| | | dto.setSync(0);//异步执行 |
| | | dto.setReleaseShuttle(1);//执行完成后释放小车 |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(chargeLocNo); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(standbyLocNoTo); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLiftNo(transferLiftDevice.getId().intValue()); |
| | | dto.setLocNo(liftLocNoTo); |
| | | })), |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(standbyLocNoFrom); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE_FROM_LIFT |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(chargeLocNo); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(locNo); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(locNo); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLiftNo(liftDevice.getId().intValue()); |
| | | dto.setLocNo(standbyLocNoTo); |
| | | })), |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLiftNo(liftDevice.getId().intValue()); |
| | | dto.setLocNo(liftLocNoTo); |
| | | })), |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(standbyLocNoFrom); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE_FROM_LIFT |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(shuttleDevice.getId().intValue()); |
| | | dto.setShuttleDevice(shuttleDevice); |
| | | dto.setLocNo(locNo); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(device.getId().intValue()); |
| | | dto.setShuttleDevice(device); |
| | | dto.setLocNo(targetLoc); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(device.getId().intValue()); |
| | | dto.setShuttleDevice(device); |
| | | dto.setLocNo(sourceLoc); |
| | | })), |
| | | MotionCtgType.SHUTTLE_MOVE |
| | |
| | | })), |
| | | MotionDto.build((dto -> { |
| | | dto.setShuttleNo(device.getId().intValue()); |
| | | dto.setShuttleDevice(device); |
| | | dto.setLocNo(targetLoc); |
| | | })), |
| | | MotionCtgType.SHUTTLE_TRANSPORT |
| | |
| | | package com.zy.asrs.wcs.core.kernel; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.zy.asrs.framework.exception.CoolException; |
| | | import com.zy.asrs.wcs.core.domain.dto.MotionDto; |
| | | import com.zy.asrs.wcs.core.model.NavigateNode; |
| | | import com.zy.asrs.wcs.core.model.enums.DeviceCtgType; |
| | | import com.zy.asrs.wcs.core.model.enums.MotionCtgType; |
| | | import com.zy.asrs.wcs.core.entity.Motion; |
| | | import com.zy.asrs.wcs.core.model.enums.NavigationMapType; |
| | | import com.zy.asrs.wcs.core.service.MotionService; |
| | | import com.zy.asrs.wcs.core.utils.LiftDispatcher; |
| | | import com.zy.asrs.wcs.core.utils.NavigateUtils; |
| | | import com.zy.asrs.wcs.core.utils.Utils; |
| | | import com.zy.asrs.wcs.rcs.News; |
| | | import com.zy.asrs.wcs.rcs.entity.Device; |
| | | import com.zy.asrs.wcs.rcs.service.DeviceService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | |
| | | private MotionService motionService; |
| | | @Autowired |
| | | private LiftDispatcher liftDispatcher; |
| | | @Autowired |
| | | private NavigateUtils navigateUtils; |
| | | @Autowired |
| | | private DeviceService deviceService; |
| | | |
| | | // agv ----------------------------------------------------------------------------- |
| | | @Deprecated |
| | |
| | | motion.setReleaseLift(target.getReleaseLift()); |
| | | } |
| | | |
| | | if (motion.getOrigin() != null && motion.getTarget() != null) { |
| | | List<NavigateNode> nodeList = navigateUtils.calc(motion.getOrigin(), motion.getTarget(), NavigationMapType.NONE_LOCK.id, Utils.getShuttlePoints(Integer.parseInt(target.getShuttleDevice().getDeviceNo()), Utils.getLev(motion.getTarget()))); |
| | | if (nodeList == null) { |
| | | throw new CoolException(motion.getOrigin() + " dash " + motion.getTarget() + " can't find navigate path!"); |
| | | } |
| | | motion.setMovePath(JSON.toJSONString(nodeList)); |
| | | } |
| | | |
| | | })); |
| | | |
| | | return motionList; |
| | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.zy.asrs.framework.common.Cools; |
| | | import com.zy.asrs.framework.common.SpringUtils; |
| | | import com.zy.asrs.framework.exception.CoolException; |
| | | import com.zy.asrs.wcs.common.ExecuteSupport; |
| | | import com.zy.asrs.wcs.core.action.LiftAction; |
| | |
| | | import com.zy.asrs.wcs.core.utils.*; |
| | | import com.zy.asrs.wcs.rcs.News; |
| | | import com.zy.asrs.wcs.rcs.cache.SlaveConnection; |
| | | import com.zy.asrs.wcs.rcs.constant.DeviceRedisConstant; |
| | | import com.zy.asrs.wcs.rcs.entity.Device; |
| | | import com.zy.asrs.wcs.rcs.model.enums.ShuttleProtocolStatusType; |
| | | import com.zy.asrs.wcs.rcs.model.enums.SlaveType; |
| | |
| | | import com.zy.asrs.wcs.rcs.thread.DevpThread; |
| | | import com.zy.asrs.wcs.rcs.thread.LiftThread; |
| | | import com.zy.asrs.wcs.rcs.thread.ShuttleThread; |
| | | import com.zy.asrs.wcs.system.entity.Dict; |
| | | import com.zy.asrs.wcs.system.service.DictService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | private BasConveyorStaService basConveyorStaService; |
| | | @Autowired |
| | | private ShuttleDispatcher shuttleDispatcher; |
| | | @Autowired |
| | | private NavigateUtils navigateUtils; |
| | | @Autowired |
| | | private DictService dictService; |
| | | |
| | | // 计算 |
| | | public Boolean accept(Motion motion) { |
| | |
| | | } |
| | | shuttleCommands = this.shuttleAssignCommand(motion.getOrigin(), motion.getTarget(), NavigationMapType.NORMAL.id, assignCommand, shuttleThread); |
| | | shuttleTaskModeType = ShuttleTaskModeType.SHUTTLE_MOVE; |
| | | |
| | | if (!checkSimilarityPath(motion, assignCommand)) { |
| | | return false; |
| | | } |
| | | |
| | | break; |
| | | case SHUTTLE_TRANSPORT://穿梭车载货行走 |
| | | // 如果已经在当前条码则过滤 |
| | |
| | | } |
| | | shuttleCommands = this.shuttleAssignCommand(motion.getOrigin(), motion.getTarget(), NavigationMapType.DFX.id, assignCommand, shuttleThread); |
| | | shuttleTaskModeType = ShuttleTaskModeType.TRANSPORT; |
| | | |
| | | if (!checkSimilarityPath(motion, assignCommand)) { |
| | | return false; |
| | | } |
| | | |
| | | if (motion.getReleaseLift() == 2) {//执行中释放提升机 |
| | | task.setLiftNo(0); |
| | |
| | | } |
| | | shuttleCommands = this.shuttleAssignCommand(motion.getOrigin(), motion.getTarget(), NavigationMapType.DFX.id, assignCommand, shuttleThread); |
| | | shuttleTaskModeType = ShuttleTaskModeType.TRANSPORT_TO_CONVEYOR; |
| | | |
| | | if (!checkSimilarityPath(motion, assignCommand)) { |
| | | return false; |
| | | } |
| | | |
| | | break; |
| | | case SHUTTLE_MOVE_LIFT_PALLET://穿梭车顶升并移动 |
| | | shuttleCommands = this.shuttleAssignCommand(motion.getOrigin(), motion.getTarget(), NavigationMapType.DFX.id, assignCommand, shuttleThread); |
| | | shuttleTaskModeType = ShuttleTaskModeType.MOVE_PALLET_LIFT; |
| | | |
| | | if (!checkSimilarityPath(motion, assignCommand)) { |
| | | return false; |
| | | } |
| | | |
| | | shuttleCommands.add(0, shuttleThread.getLiftCommand(motion.getTaskNo(), true)); |
| | | break; |
| | | case SHUTTLE_MOVE_DOWN_PALLET://穿梭车移动并托盘下降 |
| | | shuttleCommands = this.shuttleAssignCommand(motion.getOrigin(), motion.getTarget(), NavigationMapType.DFX.id, assignCommand, shuttleThread); |
| | | shuttleTaskModeType = ShuttleTaskModeType.MOVE_PALLET_DOWN; |
| | | |
| | | if (!checkSimilarityPath(motion, assignCommand)) { |
| | | return false; |
| | | } |
| | | |
| | | shuttleCommands.add(shuttleCommands.size(), shuttleThread.getLiftCommand(motion.getTaskNo(), false)); |
| | | break; |
| | | case SHUTTLE_MOVE_FROM_LIFT://出提升机 |
| | |
| | | //获取小车移动速度 |
| | | Integer runSpeed = Optional.ofNullable(basShuttleService.getOne(new LambdaQueryWrapper<BasShuttle>().eq(BasShuttle::getDeviceId, assignCommand.getDeviceId())).getRunSpeed()).orElse(1000); |
| | | Long hostId = shuttleThread.getDevice().getHostId(); |
| | | List<NavigateNode> nodeList = NavigateUtils.calc(startLocNo, endLocNo, mapType, Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), Utils.getLev(startLocNo))); |
| | | List<NavigateNode> nodeList = navigateUtils.calc(startLocNo, endLocNo, mapType, Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), Utils.getLev(startLocNo))); |
| | | if (nodeList == null) { |
| | | News.error("{} dash {} can't find navigate path!", startLocNo, endLocNo); |
| | | return null; |
| | |
| | | |
| | | List<ShuttleCommand> commands = new ArrayList<>(); |
| | | //获取分段路径 |
| | | ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(nodeList); |
| | | ArrayList<ArrayList<NavigateNode>> data = navigateUtils.getSectionPath(nodeList); |
| | | //将每一段路径分成command指令 |
| | | for (ArrayList<NavigateNode> nodes : data) { |
| | | //开始路径 |
| | |
| | | |
| | | //目标路径 |
| | | NavigateNode endPath = nodes.get(nodes.size() - 1); |
| | | Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离 |
| | | Integer allDistance = navigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离 |
| | | //通过xy坐标小车二维码 |
| | | String startCodeNum = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ(), hostId); |
| | | //通过xy坐标小车二维码 |
| | |
| | | //获取小车移动速度 |
| | | Integer runSpeed = Optional.ofNullable(basShuttleService.getOne(new LambdaQueryWrapper<BasShuttle>().eq(BasShuttle::getDeviceId, assignCommand.getDeviceId())).getRunSpeed()).orElse(1000); |
| | | Long hostId = shuttleThread.getDevice().getHostId(); |
| | | List<NavigateNode> nodeList = NavigateUtils.calc(startLocNo, endLocNo, mapType, Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), Utils.getLev(startLocNo))); |
| | | List<NavigateNode> nodeList = navigateUtils.calc(startLocNo, endLocNo, mapType, Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), Utils.getLev(startLocNo))); |
| | | if (nodeList == null) { |
| | | News.error("{} dash {} can't find navigate path!", startLocNo, endLocNo); |
| | | return null; |
| | |
| | | |
| | | List<ShuttleCommand> commands = new ArrayList<>(); |
| | | //获取分段路径 |
| | | ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(nodeList); |
| | | ArrayList<ArrayList<NavigateNode>> data = navigateUtils.getSectionPath(nodeList); |
| | | //将每一段路径分成command指令 |
| | | for (ArrayList<NavigateNode> nodes : data) { |
| | | //开始路径 |
| | |
| | | |
| | | //目标路径 |
| | | NavigateNode endPath = nodes.get(nodes.size() - 1); |
| | | Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离 |
| | | Integer allDistance = navigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离 |
| | | //通过xy坐标小车二维码 |
| | | String startCodeNum = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ(), hostId); |
| | | //通过xy坐标小车二维码 |
| | |
| | | return commands; |
| | | } |
| | | |
| | | private boolean checkSimilarityPath(Motion motion, ShuttleAssignCommand assignCommand) { |
| | | String movePath = motion.getMovePath(); |
| | | if (Cools.isEmpty(movePath)) { |
| | | return false; |
| | | } |
| | | |
| | | Double similarityRef = 0.9D; |
| | | Dict similarityRefDict = dictService.getOne(new LambdaQueryWrapper<Dict>() |
| | | .eq(Dict::getFlag, "similarityRef") |
| | | .eq(Dict::getStatus, 1)); |
| | | if (similarityRefDict != null) { |
| | | similarityRef = Double.parseDouble(similarityRefDict.getValue()); |
| | | } |
| | | |
| | | List<NavigateNode> originPath = JSON.parseArray(movePath, NavigateNode.class); |
| | | List<NavigateNode> finalPath = assignCommand.getNodes(); |
| | | |
| | | if (finalPath == null) { |
| | | return false; |
| | | } |
| | | |
| | | Double similarity = navigateUtils.similarityPath(originPath, finalPath); |
| | | if (similarity <= similarityRef) { |
| | | Object object = redisUtil.get(DeviceRedisConstant.SIMILARITY_TIMES + motion.getTaskNo()); |
| | | if (object == null) { |
| | | redisUtil.set(DeviceRedisConstant.SIMILARITY_TIMES + motion.getTaskNo(), System.currentTimeMillis(), 60 * 60 * 24); |
| | | }else { |
| | | long similarityTimeoutRef = 20L;//默认超时20s |
| | | Dict similarityTimeoutDict = dictService.getOne(new LambdaQueryWrapper<Dict>() |
| | | .eq(Dict::getFlag, "similarityTimeout") |
| | | .eq(Dict::getStatus, 1)); |
| | | if (similarityTimeoutDict != null) { |
| | | similarityTimeoutRef = Long.parseLong(similarityTimeoutDict.getValue()); |
| | | } |
| | | |
| | | long recordTime = Long.parseLong(object.toString()); |
| | | if (System.currentTimeMillis() - recordTime > (60 * similarityTimeoutRef)) { |
| | | //超时,直接放行 |
| | | return true; |
| | | } |
| | | } |
| | | News.error("{} dash {} path similarity mismatch!", motion.getOrigin(), motion.getTarget()); |
| | | return false; |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.asrs.wcs.core.model; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class PythonResult { |
| | | |
| | | private String start; |
| | | |
| | | private String target; |
| | | |
| | | private String path; |
| | | |
| | | private Double time; |
| | | |
| | | private Integer calcResult; |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.asrs.wcs.core.model; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class PythonSimilarityResult { |
| | | |
| | | private String firstPath; |
| | | |
| | | private String secondPath; |
| | | |
| | | private Double similarity; |
| | | |
| | | private Integer calcResult; |
| | | |
| | | } |
| | |
| | | NONE(-1, "无过滤"), |
| | | DFX(1, "过滤库位状态DFX"), // 带货走行 |
| | | NORMAL(2, "过滤库位状态X"), // 无货走行 |
| | | NONE_LOCK(3, "过滤库位状态X,且无路径锁"), |
| | | ; |
| | | |
| | | public Integer id; |
| | |
| | | import com.zy.asrs.framework.common.Cools; |
| | | import com.zy.asrs.framework.common.R; |
| | | import com.zy.asrs.framework.common.SnowflakeIdWorker; |
| | | import com.zy.asrs.framework.exception.CoolException; |
| | | import com.zy.asrs.wcs.core.action.LiftAction; |
| | | import com.zy.asrs.wcs.core.domain.dto.MatDto; |
| | | import com.zy.asrs.wcs.core.domain.dto.RedisMapDto; |
| | | import com.zy.asrs.wcs.core.domain.dto.StaDto; |
| | |
| | | import com.zy.asrs.wcs.core.entity.*; |
| | | import com.zy.asrs.wcs.core.kernel.AnalyzeService; |
| | | import com.zy.asrs.wcs.core.model.MapNode; |
| | | import com.zy.asrs.wcs.core.model.command.LiftAssignCommand; |
| | | import com.zy.asrs.wcs.core.model.command.LiftCommand; |
| | | import com.zy.asrs.wcs.core.model.enums.*; |
| | | import com.zy.asrs.wcs.core.service.*; |
| | | import com.zy.asrs.wcs.core.utils.OpenUtils; |
| | |
| | | import com.zy.asrs.wcs.rcs.model.command.LedCommand; |
| | | import com.zy.asrs.wcs.rcs.model.enums.ShuttleProtocolStatusType; |
| | | import com.zy.asrs.wcs.rcs.model.enums.SlaveType; |
| | | import com.zy.asrs.wcs.rcs.model.protocol.LiftProtocol; |
| | | import com.zy.asrs.wcs.rcs.model.protocol.ShuttleProtocol; |
| | | import com.zy.asrs.wcs.rcs.model.protocol.StaProtocol; |
| | | import com.zy.asrs.wcs.rcs.service.DeviceService; |
| | | import com.zy.asrs.wcs.rcs.thread.BarcodeThread; |
| | | import com.zy.asrs.wcs.rcs.thread.DevpThread; |
| | | import com.zy.asrs.wcs.rcs.thread.LedThread; |
| | | import com.zy.asrs.wcs.rcs.thread.ShuttleThread; |
| | | import com.zy.asrs.wcs.rcs.thread.*; |
| | | import com.zy.asrs.wcs.system.entity.Dict; |
| | | import com.zy.asrs.wcs.system.service.DictService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | private ShuttleChargeStaService shuttleChargeStaService; |
| | | @Autowired |
| | | private OpenUtils openUtils; |
| | | @Autowired |
| | | private LiftAction liftAction; |
| | | |
| | | /** |
| | | * 组托 |
| | |
| | | } |
| | | |
| | | /** |
| | | * 入库-托盘进库 |
| | | */ |
| | | public synchronized void palletInbound() { |
| | | try { |
| | | // 根据输送线plc遍历 |
| | | List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>() |
| | | .eq(Device::getDeviceType, DeviceCtgType.CONVEYOR.val()) |
| | | .eq(Device::getStatus, 1)); |
| | | for (Device devp : list) { |
| | | BasConveyor basConveyor = basConveyorService.getOne(new LambdaQueryWrapper<BasConveyor>().eq(BasConveyor::getDeviceId, devp.getId()).eq(BasConveyor::getHostId, devp.getHostId())); |
| | | // 遍历入库口 |
| | | for (StaDto inSta : JSON.parseArray(basConveyor.getInSta(), StaDto.class)) { |
| | | BasConveyorSta basConveyorSta = basConveyorStaService.selectBySiteNo(inSta.getDeviceStaNo().toString()); |
| | | if(basConveyorSta == null) { |
| | | continue; |
| | | } |
| | | |
| | | // 获取入库站信息 |
| | | DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, devp.getId().intValue()); |
| | | StaProtocol staProtocol = devpThread.getStation().get(inSta.getDeviceStaNo()); |
| | | if (staProtocol == null) { |
| | | continue; |
| | | } else { |
| | | staProtocol = staProtocol.clone(); |
| | | } |
| | | int workNo = staProtocol.getWorkNo().intValue(); |
| | | |
| | | // 判断是否满足入库条件 |
| | | if (staProtocol.isAutoing() |
| | | && staProtocol.isLoading() |
| | | && staProtocol.isInEnable() |
| | | && (workNo >= 0) |
| | | && staProtocol.isPakMk() |
| | | ) { |
| | | Object object = redisUtil.get(DeviceRedisConstant.LIFT_PALLET_INBOUND + workNo); |
| | | if (object != null) { |
| | | continue; |
| | | } |
| | | |
| | | Task task = taskService.getOne(new LambdaQueryWrapper<Task>() |
| | | .eq(Task::getDestSite, inSta.getDeviceStaNo()) |
| | | .in(Task::getTaskSts, TaskStsType.NEW_INBOUND.sts) |
| | | .eq(Task::getTaskNo, workNo)); |
| | | if (task != null) { |
| | | int lev = Utils.getLev(task.getDestLoc()); |
| | | Integer targetSite = null; |
| | | if (lev == 1) { |
| | | targetSite = 31006; |
| | | }else if (lev == 2) { |
| | | targetSite = 31007; |
| | | }else if (lev == 3) { |
| | | targetSite = 31008; |
| | | } |
| | | if(targetSite == null) { |
| | | throw new CoolException(lev + "层站点信息不存在"); |
| | | } |
| | | |
| | | StaProtocol staProtocol1 = devpThread.getStation().get(targetSite); |
| | | if (staProtocol1 == null) { |
| | | break; |
| | | } |
| | | if (!staProtocol1.isAutoing()) { |
| | | break; |
| | | } |
| | | if (staProtocol1.isLoading()) { |
| | | break; |
| | | } |
| | | if (staProtocol1.getWorkNo().intValue() != 0) { |
| | | break; |
| | | } |
| | | |
| | | LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, inSta.getLiftNo()); |
| | | if (liftThread == null) { |
| | | break; |
| | | } |
| | | |
| | | LiftProtocol liftProtocol = liftThread.getStatus(); |
| | | if (liftProtocol == null) { |
| | | break; |
| | | } |
| | | |
| | | if (!liftThread.isIdle()) { |
| | | break; |
| | | } |
| | | |
| | | if (motionService.count(new LambdaQueryWrapper<Motion>() |
| | | .eq(Motion::getDeviceCtg, DeviceCtgType.LIFT.val()) |
| | | .eq(Motion::getDevice, inSta.getLiftNo()) |
| | | .eq(Motion::getMotionSts, MotionStsType.EXECUTING.val())) > 0) { |
| | | break; |
| | | } |
| | | |
| | | //检测提升机是否有任务绑定 |
| | | boolean liftResult = Utils.checkLiftHasBinding(liftProtocol.getLiftNo(), String.valueOf(workNo)); |
| | | if (liftResult) { |
| | | //存在任务,禁止执行 |
| | | break; |
| | | } |
| | | |
| | | //每次执行提升机指令都绑定提升机 |
| | | task.setLiftNo(liftProtocol.getLiftNo()); |
| | | task.setUpdateTime(new Date()); |
| | | if (!taskService.updateById(task)) { |
| | | break; |
| | | } |
| | | |
| | | List<LiftCommand> command = liftThread.getPalletInOutCommand(workNo, 1, lev, inSta.getDeviceStaNo(), targetSite, LiftCommandModeType.PALLET_INOUT); |
| | | |
| | | LiftAssignCommand assignCommand = new LiftAssignCommand(); |
| | | assignCommand.setLiftNo(liftProtocol.getLiftNo()); |
| | | assignCommand.setTaskNo(workNo); |
| | | assignCommand.setDeviceTaskNo(liftThread.generateDeviceTaskNo(workNo, MotionCtgType.LIFT_WITH_GOODS)); |
| | | assignCommand.setCommands(command); |
| | | liftAction.assignWork(liftThread.getDevice(), assignCommand); |
| | | |
| | | redisUtil.set(DeviceRedisConstant.LIFT_PALLET_INBOUND + workNo, "send", 60 * 60 * 6); |
| | | break; |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 初始化实时地图 |
| | | */ |
| | | public synchronized void initRealtimeBasMap() { |
| | |
| | | |
| | | //将地图数据存入redis |
| | | redisUtil.set(DeviceRedisConstant.MAP + lev, JSON.toJSONString(map)); |
| | | redisUtil.set(DeviceRedisConstant.BASE_MAP + lev, JSON.toJSONString(map)); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | |
| | | |
| | | // 解析入库工作档 |
| | | public synchronized void analyzeInBoundTask() { |
| | | for (Task task : taskService.selectWaitAnalyzeInBoundTask()) { |
| | | BasConveyorSta basConveyorSta = basConveyorStaService.getOne(new LambdaQueryWrapper<BasConveyorSta>().eq(BasConveyorSta::getSiteNo, task.getDestSite())); |
| | | if (basConveyorSta == null) { |
| | | continue; |
| | | } |
| | | BasConveyor basConveyor = basConveyorService.getById(basConveyorSta.getConveyorId()); |
| | | if (basConveyor == null) { |
| | | continue; |
| | | } |
| | | // DeviceBarcode deviceBarcode = deviceBarcodeService.getById(basConveyorSta.getBarcodeId()); |
| | | // if (deviceBarcode == null) { |
| | | // continue; |
| | | // } |
| | | // BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, Integer.parseInt(deviceBarcode.getDeviceId())); |
| | | // if (barcodeThread == null) { |
| | | // continue; |
| | | // } |
| | | // if (!barcodeThread.getBarcode().equals(task.getZpallet())) { |
| | | // continue; |
| | | // } |
| | | if (Cools.isEmpty(basConveyorSta.getTaskNo())){ |
| | | continue; |
| | | } |
| | | if (!basConveyorSta.getTaskNo().toString().equals(task.getTaskNo())){ |
| | | continue; |
| | | } |
| | | DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, basConveyor.getDeviceId().intValue()); |
| | | if (devpThread == null) { |
| | | continue; |
| | | } |
| | | StaProtocol staProtocol = devpThread.getStation().get(basConveyorSta.getSiteNo()); |
| | | if (staProtocol == null) { |
| | | continue; |
| | | } |
| | | if (!(staProtocol.isAutoing() |
| | | && staProtocol.isLoading() |
| | | && staProtocol.isInEnable())) { |
| | | continue; |
| | | } |
| | | try { |
| | | // 根据输送线plc遍历 |
| | | List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>() |
| | | .eq(Device::getDeviceType, DeviceCtgType.CONVEYOR.val()) |
| | | .eq(Device::getStatus, 1)); |
| | | for (Device devp : list) { |
| | | BasConveyor basConveyor = basConveyorService.getOne(new LambdaQueryWrapper<BasConveyor>().eq(BasConveyor::getDeviceId, devp.getId()).eq(BasConveyor::getHostId, devp.getHostId())); |
| | | // 遍历入库口 |
| | | for (StaDto inSta : JSON.parseArray(basConveyor.getDeviceInSta(), StaDto.class)) { |
| | | BasConveyorSta basConveyorSta = basConveyorStaService.selectBySiteNo(inSta.getStaNo().toString()); |
| | | if(basConveyorSta == null) { |
| | | continue; |
| | | } |
| | | |
| | | //解析前判断内部目标值是否有物 有工作号 |
| | | StaProtocol staProtocolInside = devpThread.getStation().get(Utils.getStaByLev(Utils.getLev(task.getDestLoc()))); |
| | | if (staProtocolInside == null) { |
| | | continue; |
| | | } |
| | | if (staProtocolInside.isLoading() || staProtocolInside.getWorkNo() !=0) { |
| | | continue; |
| | | } |
| | | // 获取入库站信息 |
| | | DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, devp.getId().intValue()); |
| | | StaProtocol staProtocol = devpThread.getStation().get(inSta.getStaNo()); |
| | | if (staProtocol == null) { |
| | | continue; |
| | | } else { |
| | | staProtocol = staProtocol.clone(); |
| | | } |
| | | int workNo = staProtocol.getWorkNo().intValue(); |
| | | |
| | | if (Cools.isEmpty(task.getShuttleNo())) { |
| | | //分配小车 |
| | | //搜索空闲车 |
| | | ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task); |
| | | if (shuttleThread == null) { |
| | | News.info("{}任务未找到空闲穿梭车", task.getTaskNo()); |
| | | continue; |
| | | // 判断是否满足入库条件 |
| | | if (staProtocol.isAutoing() |
| | | && staProtocol.isInEnable() |
| | | && (workNo >= 0) |
| | | && staProtocol.isPakMk() |
| | | ) { |
| | | |
| | | Task task = taskService.getOne(new LambdaQueryWrapper<Task>() |
| | | .in(Task::getTaskSts, TaskStsType.NEW_INBOUND.sts) |
| | | .eq(Task::getTaskNo, workNo)); |
| | | if (task != null) { |
| | | if (!Cools.isEmpty(task.getLiftNo())) { |
| | | if (task.getLiftNo() > 0) { |
| | | task.setLiftNo(0); |
| | | task.setUpdateTime(new Date()); |
| | | if (!taskService.updateById(task)) { |
| | | News.info("{}任务更新释放提升机失败", task.getTaskNo()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (Cools.isEmpty(task.getShuttleNo())) { |
| | | //分配小车 |
| | | //搜索空闲车 |
| | | ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task); |
| | | if (shuttleThread == null) { |
| | | News.info("{}任务未找到空闲穿梭车", task.getTaskNo()); |
| | | continue; |
| | | } |
| | | |
| | | task.setShuttleNo(Integer.valueOf(shuttleThread.getDevice().getDeviceNo()));//保存穿梭车号 |
| | | task.setUpdateTime(new Date()); |
| | | if (!taskService.updateById(task)) { |
| | | News.info("{}任务更新穿梭车号失败", task.getTaskNo()); |
| | | } |
| | | continue; |
| | | } |
| | | |
| | | // generate motion list |
| | | List<Motion> motionList = analyzeService.generateMotion(task); |
| | | if (motionList.isEmpty()) { |
| | | continue; |
| | | } |
| | | motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), task.getHostId()); |
| | | |
| | | // 更新工作主档 |
| | | task.setTaskSts(TaskStsType.ANALYZE_INBOUND.sts); // 工作状态 |
| | | task.setUpdateTime(new Date()); |
| | | if (!taskService.updateById(task)) { |
| | | News.error("更新工作档失败!!! [工作号:{}]", task.getTaskNo()); |
| | | } |
| | | break; |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | task.setShuttleNo(Integer.valueOf(shuttleThread.getDevice().getDeviceNo()));//保存穿梭车号 |
| | | task.setUpdateTime(new Date()); |
| | | if (!taskService.updateById(task)) { |
| | | News.info("{}任务更新穿梭车号失败", task.getTaskNo()); |
| | | } |
| | | continue; |
| | | } |
| | | |
| | | // generate motion list |
| | | List<Motion> motionList = analyzeService.generateMotion(task); |
| | | if (motionList.isEmpty()) { |
| | | continue; |
| | | } |
| | | motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), task.getHostId()); |
| | | |
| | | // 更新工作主档 |
| | | task.setTaskSts(TaskStsType.ANALYZE_INBOUND.sts); // 工作状态 |
| | | task.setUpdateTime(new Date()); |
| | | if (!taskService.updateById(task)) { |
| | | News.error("更新工作档失败!!! [工作号:{}]", task.getTaskNo()); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | // for (Task task : taskService.selectWaitAnalyzeInBoundTask()) { |
| | | // BasConveyorSta basConveyorSta = basConveyorStaService.getOne(new LambdaQueryWrapper<BasConveyorSta>().eq(BasConveyorSta::getSiteNo, task.getDestSite())); |
| | | // if (basConveyorSta == null) { |
| | | // continue; |
| | | // } |
| | | // BasConveyor basConveyor = basConveyorService.getById(basConveyorSta.getConveyorId()); |
| | | // if (basConveyor == null) { |
| | | // continue; |
| | | // } |
| | | //// DeviceBarcode deviceBarcode = deviceBarcodeService.getById(basConveyorSta.getBarcodeId()); |
| | | //// if (deviceBarcode == null) { |
| | | //// continue; |
| | | //// } |
| | | //// BarcodeThread barcodeThread = (BarcodeThread) SlaveConnection.get(SlaveType.Barcode, Integer.parseInt(deviceBarcode.getDeviceId())); |
| | | //// if (barcodeThread == null) { |
| | | //// continue; |
| | | //// } |
| | | //// if (!barcodeThread.getBarcode().equals(task.getZpallet())) { |
| | | //// continue; |
| | | //// } |
| | | // if (Cools.isEmpty(basConveyorSta.getTaskNo())){ |
| | | // continue; |
| | | // } |
| | | // if (!basConveyorSta.getTaskNo().toString().equals(task.getTaskNo())){ |
| | | // continue; |
| | | // } |
| | | // DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Conveyor, basConveyor.getDeviceId().intValue()); |
| | | // if (devpThread == null) { |
| | | // continue; |
| | | // } |
| | | // StaProtocol staProtocol = devpThread.getStation().get(basConveyorSta.getSiteNo()); |
| | | // if (staProtocol == null) { |
| | | // continue; |
| | | // } |
| | | // if (!(staProtocol.isAutoing() |
| | | // && staProtocol.isLoading() |
| | | // && staProtocol.isInEnable())) { |
| | | // continue; |
| | | // } |
| | | // |
| | | // //解析前判断内部目标值是否有物 有工作号 |
| | | // StaProtocol staProtocolInside = devpThread.getStation().get(Utils.getStaByLev(Utils.getLev(task.getDestLoc()))); |
| | | // if (staProtocolInside == null) { |
| | | // continue; |
| | | // } |
| | | // if (staProtocolInside.isLoading() || staProtocolInside.getWorkNo() !=0) { |
| | | // continue; |
| | | // } |
| | | // |
| | | // if (Cools.isEmpty(task.getShuttleNo())) { |
| | | // //分配小车 |
| | | // //搜索空闲车 |
| | | // ShuttleThread shuttleThread = shuttleDispatcher.searchIdleShuttle(task); |
| | | // if (shuttleThread == null) { |
| | | // News.info("{}任务未找到空闲穿梭车", task.getTaskNo()); |
| | | // continue; |
| | | // } |
| | | // |
| | | // task.setShuttleNo(Integer.valueOf(shuttleThread.getDevice().getDeviceNo()));//保存穿梭车号 |
| | | // task.setUpdateTime(new Date()); |
| | | // if (!taskService.updateById(task)) { |
| | | // News.info("{}任务更新穿梭车号失败", task.getTaskNo()); |
| | | // } |
| | | // continue; |
| | | // } |
| | | // |
| | | // // generate motion list |
| | | // List<Motion> motionList = analyzeService.generateMotion(task); |
| | | // if (motionList.isEmpty()) { |
| | | // continue; |
| | | // } |
| | | // motionService.batchInsert(motionList, task.getUuid(), Integer.valueOf(task.getTaskNo()), task.getHostId()); |
| | | // |
| | | // // 更新工作主档 |
| | | // task.setTaskSts(TaskStsType.ANALYZE_INBOUND.sts); // 工作状态 |
| | | // task.setUpdateTime(new Date()); |
| | | // if (!taskService.updateById(task)) { |
| | | // News.error("更新工作档失败!!! [工作号:{}]", task.getTaskNo()); |
| | | // } |
| | | // } |
| | | } |
| | | |
| | | /** |
| | |
| | | import com.zy.asrs.common.utils.HttpHandler; |
| | | import com.zy.asrs.wcs.core.entity.*; |
| | | import com.zy.asrs.wcs.core.model.enums.LocStsType; |
| | | import com.zy.asrs.wcs.core.model.enums.MotionCtgType; |
| | | import com.zy.asrs.wcs.core.model.enums.TaskStsType; |
| | | import com.zy.asrs.wcs.core.service.*; |
| | | import com.zy.asrs.wcs.rcs.News; |
| | |
| | | .eq(Task::getStatus, 1) |
| | | .in(Task::getTaskSts, taskSts)); |
| | | for (Task task : tasks) { |
| | | Motion motion = motionService.getOne(new LambdaQueryWrapper<Motion>().eq(Motion::getMotionCtg, 9).eq(Motion::getTaskNo, task.getTaskNo())); |
| | | List<BasConveyorSta> conveyorStas = basConveyorStaService.list(new LambdaQueryWrapper<BasConveyorSta>().in(BasConveyorSta::getTaskNo, motion.getTemp())); |
| | | if (!conveyorStas.isEmpty()) { |
| | | continue; |
| | | Motion motion = motionService.getOne(new LambdaQueryWrapper<Motion>().eq(Motion::getMotionCtg, MotionCtgType.LIFT_WITH_GOODS.val()).eq(Motion::getTaskNo, task.getTaskNo())); |
| | | if (motion != null) { |
| | | List<BasConveyorSta> conveyorStas = basConveyorStaService.list(new LambdaQueryWrapper<BasConveyorSta>().in(BasConveyorSta::getTaskNo, motion.getTemp())); |
| | | if (!conveyorStas.isEmpty()) { |
| | | continue; |
| | | } |
| | | } |
| | | if (reportWms != null && reportWms.getValue().equals("true")) { |
| | | //获取WMS地址 |
| | |
| | | private BasLiftService basLiftService; |
| | | @Autowired |
| | | private ShuttleStandbyService shuttleStandbyService; |
| | | @Autowired |
| | | private NavigateUtils navigateUtils; |
| | | |
| | | /** |
| | | * 根据目标位置搜索提升机 |
| | | * transfer: 是否可换层 |
| | | */ |
| | | public LiftThread searchLift(String locNo, Long hostId, Boolean transfer) { |
| | | LiftThread recentLiftThread = null; |
| | | Integer finalDistance = Integer.MAX_VALUE; |
| | | List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>() |
| | | .eq(Device::getDeviceType, DeviceCtgType.LIFT.val()) |
| | | .eq(Device::getHostId, hostId) |
| | | .eq(Device::getStatus, 1)); |
| | | for (Device device : list) { |
| | | LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, device.getId().intValue()); |
| | | if (liftThread == null) { |
| | | continue; |
| | | } |
| | | |
| | | LiftProtocol liftProtocol = liftThread.getStatus(); |
| | | if (liftProtocol == null) { |
| | | continue; |
| | | } |
| | | |
| | | if (transfer) { |
| | | BasLift basLift = basLiftService.getOne(new LambdaQueryWrapper<BasLift>().eq(BasLift::getLiftNo, device.getDeviceNo()).eq(BasLift::getHostId, hostId)); |
| | | if (basLift == null) { |
| | | continue; |
| | | } |
| | | if (basLift.getTransfer() != 1) { |
| | | continue;//提升机被设置成不可换层 |
| | | } |
| | | } |
| | | |
| | | ShuttleStandby standby = shuttleStandbyService.getOne(new LambdaQueryWrapper<ShuttleStandby>() |
| | | .eq(ShuttleStandby::getDeviceId, device.getId()) |
| | | .eq(ShuttleStandby::getDeviceLev, Utils.getLev(locNo)) |
| | | .eq(ShuttleStandby::getStatus, 1)); |
| | | if (standby == null) { |
| | | continue; |
| | | } |
| | | |
| | | String liftLocNo = Utils.getLocNo(Utils.getRow(standby.getDeviceStandbyLoc()), Utils.getBay(standby.getDeviceStandbyLoc()), Utils.getLev(locNo)); |
| | | List<NavigateNode> nodeList = navigateUtils.calc(locNo, liftLocNo, NavigationMapType.NONE.id, null); |
| | | if (nodeList == null) { |
| | | continue; |
| | | } |
| | | Integer originPathAllDistance = navigateUtils.getOriginPathAllDistance(nodeList);//总距离 |
| | | if (originPathAllDistance < finalDistance) { |
| | | finalDistance = originPathAllDistance; |
| | | recentLiftThread = liftThread; |
| | | } |
| | | } |
| | | |
| | | return recentLiftThread; |
| | | } |
| | | |
| | | /** |
| | | * 根据目标位置搜索空闲提升机 |
| | |
| | | } |
| | | |
| | | String liftLocNo = Utils.getLocNo(Utils.getRow(standby.getDeviceStandbyLoc()), Utils.getBay(standby.getDeviceStandbyLoc()), Utils.getLev(locNo)); |
| | | List<NavigateNode> nodeList = NavigateUtils.calc(locNo, liftLocNo, NavigationMapType.NONE.id, null); |
| | | List<NavigateNode> nodeList = navigateUtils.calc(locNo, liftLocNo, NavigationMapType.NONE.id, null); |
| | | if (nodeList == null) { |
| | | continue; |
| | | } |
| | | Integer originPathAllDistance = NavigateUtils.getOriginPathAllDistance(nodeList);//总距离 |
| | | Integer originPathAllDistance = navigateUtils.getOriginPathAllDistance(nodeList);//总距离 |
| | | if (originPathAllDistance < finalDistance) { |
| | | finalDistance = originPathAllDistance; |
| | | recentLiftThread = liftThread; |
| | |
| | | private LocService locService; |
| | | @Autowired |
| | | private DictService dictService; |
| | | @Autowired |
| | | private NavigateMapData navigateMapData; |
| | | |
| | | private Integer lev;//地图楼层 |
| | | |
| | |
| | | * 尝试从redis获取数据 |
| | | */ |
| | | public int[][] getDataFromRedis(Integer mapType, List<int[]> whitePoints, List<int[]> shuttlePoints) { |
| | | String constantMap = DeviceRedisConstant.MAP; |
| | | if(mapType == NavigationMapType.NONE_LOCK.id){ |
| | | constantMap = DeviceRedisConstant.BASE_MAP; |
| | | } |
| | | |
| | | RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class); |
| | | Object o = redisUtil.get(DeviceRedisConstant.MAP + lev); |
| | | Object o = redisUtil.get(constantMap + lev); |
| | | if (o == null) { |
| | | return null; |
| | | } |
| | | |
| | | BasMapDto basMap = JSON.parseObject(o.toString(), BasMapDto.class); |
| | | return this.getDataFormString(basMap.getData(), mapType, whitePoints, shuttlePoints); |
| | | String mapData = basMap.getData(); |
| | | return this.getDataFormString(mapData, mapType, whitePoints, shuttlePoints); |
| | | } |
| | | |
| | | /** |
| | |
| | | ) { |
| | | mapNode.setValue(MapNodeType.DISABLE.id);//禁用节点 |
| | | } |
| | | } else if (mapType == NavigationMapType.NORMAL.id) { |
| | | } else if (mapType == NavigationMapType.NORMAL.id || mapType == NavigationMapType.NONE_LOCK.id) { |
| | | //过滤库位状态X |
| | | if (loc.getLocStsFlag().equals("X")) { |
| | | mapNode.setValue(MapNodeType.DISABLE.id);//禁用节点 |
| | |
| | | package com.zy.asrs.wcs.core.utils; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.zy.asrs.framework.common.SpringUtils; |
| | | import com.zy.asrs.framework.exception.CoolException; |
| | | import com.zy.asrs.wcs.core.model.NavigateNode; |
| | | import com.zy.asrs.wcs.core.model.PythonResult; |
| | | import com.zy.asrs.wcs.core.model.enums.MapNodeType; |
| | | import com.zy.asrs.wcs.system.entity.Dict; |
| | | import com.zy.asrs.wcs.system.service.DictService; |
| | | |
| | | import java.io.BufferedReader; |
| | | import java.io.IOException; |
| | | import java.io.InputStreamReader; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.PriorityQueue; |
| | |
| | | //Exist表用来存放已经出现过的结点。 |
| | | public ArrayList<NavigateNode> Exist = new ArrayList<NavigateNode>(); |
| | | |
| | | public NavigateNode astarSearch(NavigateNode start, NavigateNode end) { |
| | | //把第一个开始的结点加入到Open表中 |
| | | this.Open.add(start); |
| | | //把出现过的结点加入到Exist表中 |
| | | this.Exist.add(start); |
| | | //主循环 |
| | | while (Open.size() > 0) { |
| | | //取优先队列顶部元素并且把这个元素从Open表中删除 |
| | | NavigateNode current_node = Open.poll(); |
| | | //将这个结点加入到Close表中 |
| | | Close.add(current_node); |
| | | //对当前结点进行扩展,得到一个四周结点的数组 |
| | | ArrayList<NavigateNode> neighbour_node = extend_current_node(current_node); |
| | | //对这个结点遍历,看是否有目标结点出现 |
| | | for (NavigateNode node : neighbour_node) { |
| | | // G + H + E (对启发函数增加去拐点方案calcNodeExtraCost) |
| | | int gCost = calcNodeCost(current_node, node) * calcNodeExtraCost(current_node, node, end); |
| | | if (node.getX() == end.getX() && node.getY() == end.getY()) {//找到目标结点就返回 |
| | | //init_node操作把这个邻居结点的父节点设置为当前结点 |
| | | //并且计算出G, F, H等值 |
| | | node.setLastDistance(gCost); |
| | | node.init_node(current_node, end); |
| | | return node; |
| | | } |
| | | public String astarSearch(NavigateNode start, NavigateNode end, String pythonScriptPath) { |
| | | String maps = JSON.toJSONString(map); |
| | | String startStr = start.getX() + "-" + start.getY(); |
| | | String targetStr = end.getX() + "-" + end.getY(); |
| | | |
| | | //进行计算对G, F, H 等值 |
| | | node.setLastDistance(gCost); |
| | | node.init_node(current_node, end); |
| | | node.setH(calcNodeCost(node, end)); |
| | | node.setF(node.getG() + node.getH()); |
| | | |
| | | Open.add(node); |
| | | Exist.add(node); |
| | | //默认地图母轨方向x |
| | | String mapDirection = "x"; |
| | | DictService dictService = SpringUtils.getBean(DictService.class); |
| | | if (dictService != null) { |
| | | Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>() |
| | | .eq(Dict::getFlag, "direction_map") |
| | | .eq(Dict::getStatus, 1)); |
| | | if (dict != null) { |
| | | mapDirection = dict.getValue(); |
| | | } |
| | | } |
| | | //如果遍历完所有出现的结点都没有找到最终的结点,返回null |
| | | |
| | | ProcessBuilder processBuilder = new ProcessBuilder("python", pythonScriptPath, maps, startStr, targetStr, mapDirection); |
| | | processBuilder.redirectErrorStream(true); |
| | | |
| | | try { |
| | | Process process = processBuilder.start(); |
| | | |
| | | // 读取Python脚本的输出 |
| | | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); |
| | | String line; |
| | | StringBuilder builder = new StringBuilder(); |
| | | while ((line = reader.readLine()) != null) { |
| | | builder.append(line); |
| | | } |
| | | |
| | | // 等待Python脚本执行完成 |
| | | int exitCode = process.waitFor(); |
| | | if (exitCode != 0) { |
| | | System.out.println("Python script exited with error code: " + exitCode); |
| | | return null; |
| | | } |
| | | reader.close(); |
| | | |
| | | if (builder.length() <= 0) { |
| | | return null; |
| | | } |
| | | |
| | | PythonResult result = JSON.parseObject(builder.toString(), PythonResult.class); |
| | | if (result.getCalcResult() != 200) { |
| | | return null; |
| | | } |
| | | |
| | | String path = result.getPath(); |
| | | return path; |
| | | } catch (IOException | InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | // public NavigateNode astarSearch(NavigateNode start, NavigateNode end) { |
| | | // //把第一个开始的结点加入到Open表中 |
| | | // this.Open.add(start); |
| | | // //把出现过的结点加入到Exist表中 |
| | | // this.Exist.add(start); |
| | | // //主循环 |
| | | // while (Open.size() > 0) { |
| | | // //取优先队列顶部元素并且把这个元素从Open表中删除 |
| | | // NavigateNode current_node = Open.poll(); |
| | | // //将这个结点加入到Close表中 |
| | | // Close.add(current_node); |
| | | // //对当前结点进行扩展,得到一个四周结点的数组 |
| | | // ArrayList<NavigateNode> neighbour_node = extend_current_node(current_node); |
| | | // //对这个结点遍历,看是否有目标结点出现 |
| | | // for (NavigateNode node : neighbour_node) { |
| | | // // G + H + E (对启发函数增加去拐点方案calcNodeExtraCost) |
| | | // int gCost = calcNodeCost(current_node, node) * calcNodeExtraCost(current_node, node, end); |
| | | // if (node.getX() == end.getX() && node.getY() == end.getY()) {//找到目标结点就返回 |
| | | // //init_node操作把这个邻居结点的父节点设置为当前结点 |
| | | // //并且计算出G, F, H等值 |
| | | // node.setLastDistance(gCost); |
| | | // node.init_node(current_node, end); |
| | | // return node; |
| | | // } |
| | | // |
| | | // //进行计算对G, F, H 等值 |
| | | // node.setLastDistance(gCost); |
| | | // node.init_node(current_node, end); |
| | | // node.setH(calcNodeCost(node, end)); |
| | | // node.setF(node.getG() + node.getH()); |
| | | // |
| | | // Open.add(node); |
| | | // Exist.add(node); |
| | | // } |
| | | // } |
| | | // //如果遍历完所有出现的结点都没有找到最终的结点,返回null |
| | | // return null; |
| | | // } |
| | | |
| | | |
| | | public ArrayList<NavigateNode> extend_current_node(NavigateNode current_node) { |
| | | //默认地图母轨方向x |
| | |
| | | package com.zy.asrs.wcs.core.utils; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.zy.asrs.framework.common.SpringUtils; |
| | | import com.zy.asrs.wcs.core.model.MapNode; |
| | | import com.zy.asrs.wcs.core.model.NavigateNode; |
| | | import com.zy.asrs.wcs.core.model.PythonSimilarityResult; |
| | | import com.zy.asrs.wcs.core.model.enums.MapNodeType; |
| | | import com.zy.asrs.wcs.core.model.enums.NavigationMapType; |
| | | import com.zy.asrs.wcs.rcs.News; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.io.BufferedReader; |
| | | import java.io.InputStreamReader; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * A*算法使用工具 |
| | | */ |
| | | @Component |
| | | public class NavigateUtils { |
| | | |
| | | public static List<NavigateNode> calc(String startPoint, String endPoint, Integer mapType, List<int[]> shuttlePoints) { |
| | | @Value("${pythonCalcPath}") |
| | | private String pythonCalcPath; |
| | | |
| | | @Value("${pythonCalcSimilarity}") |
| | | private String pythonCalcSimilarity; |
| | | |
| | | public List<NavigateNode> calc(String startPoint, String endPoint, Integer mapType, List<int[]> shuttlePoints) { |
| | | //通过开始编号和结束编号获取对应的xy轴坐标 |
| | | int[] startArr = NavigatePositionConvert.positionToXY(startPoint);//开始节点 |
| | | int[] endArr = NavigatePositionConvert.positionToXY(endPoint);//结束节点 |
| | |
| | | NavigateSolution solution = new NavigateSolution(mapType, lev, whiteList, shuttlePoints); |
| | | //开始节点,不纳入禁用节点内计算 |
| | | |
| | | NavigateNode res_node = solution.astarSearch(start, end); |
| | | if (res_node == null) { |
| | | System.err.println("未找到路径"); |
| | | String pathStr = solution.astarSearch(start, end, pythonCalcPath); |
| | | if (pathStr == null) { |
| | | News.error("{} dash {} can't find navigate path!", startPoint, endPoint); |
| | | return null; |
| | | } |
| | | ArrayList<NavigateNode> list = new ArrayList<>(); |
| | | |
| | | //渲染 |
| | | List<NavigateNode> list = new ArrayList<>(); |
| | | |
| | | NavigateNode fatherNode = null;//当前循环上一节点,用于拐点计算 |
| | | while (res_node != null) { |
| | | res_node.setDirection(null); |
| | | res_node.setIsInflectionPoint(false); |
| | | res_node.setZ(lev);//设置层高 |
| | | JSONArray rows = JSON.parseArray(pathStr); |
| | | |
| | | for (int i = 0; i < rows.size(); i++) { |
| | | Object currentObj = rows.get(i); |
| | | |
| | | NavigateNode nextNode = null; |
| | | if ((i + 1) < rows.size()) { |
| | | Object object = rows.get(i + 1); |
| | | nextNode = pythonObjTransferNode(object, lev); |
| | | } |
| | | |
| | | NavigateNode node = pythonObjTransferNode(currentObj, lev); |
| | | |
| | | //寻找拐点 |
| | | HashMap<String, Object> result = searchInflectionPoint(res_node, fatherNode, res_node.getFather());//分别传入当前节点、父节点、下一节点 |
| | | HashMap<String, Object> result = searchInflectionPoint(node, fatherNode, nextNode);//分别传入当前节点、父节点、下一节点 |
| | | //判断当前节点是否为拐点 |
| | | if (Boolean.parseBoolean(result.get("result").toString())) { |
| | | //当前为拐点 |
| | | res_node.setIsInflectionPoint(true); |
| | | node.setIsInflectionPoint(true); |
| | | //拐点方向 |
| | | res_node.setDirection(result.get("direction").toString()); |
| | | node.setDirection(result.get("direction").toString()); |
| | | } |
| | | list.add(res_node); |
| | | |
| | | fatherNode = res_node;//把当前节点保存成一个父节点 |
| | | res_node = res_node.getFather();//迭代操作 |
| | | list.add(node); |
| | | |
| | | fatherNode = node;//把当前节点保存成一个父节点 |
| | | } |
| | | |
| | | Collections.reverse(list); |
| | | |
| | | //将每个节点里面的fatherNode至为null(方便后续计算时父节点过多导致显示的节点太多) |
| | | for (NavigateNode navigateNode : list) { |
| | |
| | | } |
| | | |
| | | //判断当前节点到下一个节点是否为拐点 |
| | | public static HashMap<String,Object> searchInflectionPoint(NavigateNode currentNode, NavigateNode fatherNode, NavigateNode nextNode) { |
| | | public HashMap<String,Object> searchInflectionPoint(NavigateNode currentNode, NavigateNode fatherNode, NavigateNode nextNode) { |
| | | HashMap<String, Object> map = new HashMap<>(); |
| | | map.put("result", false);//是否为拐点,true:拐点,false:直线 |
| | | // 第一个点或直线点 |
| | |
| | | /** |
| | | * 计算方向 |
| | | */ |
| | | public static String calcDirection(NavigateNode currentNode, NavigateNode fatherNode) { |
| | | public String calcDirection(NavigateNode currentNode, NavigateNode fatherNode) { |
| | | //拐点方向 |
| | | String direction = ""; |
| | | // 普通拐点 |
| | |
| | | * 加转弯节点 |
| | | * 获取分段路径,每当有一个拐点则进行一次分段,最终返回总分段数据 |
| | | */ |
| | | public static ArrayList<ArrayList<NavigateNode>> getSectionPath(List<NavigateNode> mapList) { |
| | | public ArrayList<ArrayList<NavigateNode>> getSectionPath(List<NavigateNode> mapList) { |
| | | ArrayList<ArrayList<NavigateNode>> list = new ArrayList<>(); |
| | | |
| | | ArrayList<NavigateNode> data = new ArrayList<>(); |
| | |
| | | } |
| | | |
| | | //获取从x点到下一点的行走距离 |
| | | public static Integer getXToNextDistance(NavigateNode xNode) { |
| | | public Integer getXToNextDistance(NavigateNode xNode) { |
| | | NavigateMapData mapData = SpringUtils.getBean(NavigateMapData.class); |
| | | mapData.setLev(xNode.getZ()); |
| | | List<List<MapNode>> lists = mapData.getJsonData(NavigationMapType.NONE.id, null, null); |
| | |
| | | /** |
| | | * 根据原始节点结果,计算总行走距离 |
| | | */ |
| | | public static Integer getOriginPathAllDistance(List<NavigateNode> path) { |
| | | ArrayList<ArrayList<NavigateNode>> sectionPath = NavigateUtils.getSectionPath(path); |
| | | public Integer getOriginPathAllDistance(List<NavigateNode> path) { |
| | | ArrayList<ArrayList<NavigateNode>> sectionPath = getSectionPath(path); |
| | | Integer allDistance = 0; |
| | | for (ArrayList<NavigateNode> navigateNodes : sectionPath) { |
| | | Integer distance = NavigateUtils.getCurrentPathAllDistance(navigateNodes); |
| | | Integer distance = getCurrentPathAllDistance(navigateNodes); |
| | | allDistance += distance; |
| | | } |
| | | return allDistance; |
| | |
| | | /** |
| | | * 获取当前路径总行走距离 |
| | | */ |
| | | public static Integer getCurrentPathAllDistance(List<NavigateNode> path) { |
| | | public Integer getCurrentPathAllDistance(List<NavigateNode> path) { |
| | | if (path.size() == 1) { |
| | | //路径只有一条数据,则直接返回行走距离 |
| | | return path.get(0).getMoveDistance(); |
| | |
| | | /** |
| | | * 获取中间点到目标点行走距离 |
| | | */ |
| | | public static Integer getMiddleToDistDistance(List<NavigateNode> path, NavigateNode middlePath) { |
| | | public Integer getMiddleToDistDistance(List<NavigateNode> path, NavigateNode middlePath) { |
| | | //最后一条节点不计算进行走距离 |
| | | NavigateNode lastPath = path.get(path.size() - 1); |
| | | //总距离 |
| | |
| | | /** |
| | | * 检测路径是否可用(可走) |
| | | */ |
| | | public static boolean checkPathIsAvailable(List<NavigateNode> path, Integer shuttleNo, Integer lev) { |
| | | public boolean checkPathIsAvailable(List<NavigateNode> path, Integer shuttleNo, Integer lev) { |
| | | NavigateSolution solution = new NavigateSolution(NavigationMapType.DFX.id, lev, null, Utils.getShuttlePoints(shuttleNo, lev));//获取无白名单地图(该地图包含小车坐标) |
| | | int[][] map = solution.map; |
| | | for (NavigateNode node : path) { |
| | |
| | | return true; |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | //计算路径 |
| | | List<NavigateNode> calc = calc("1000901", "1800201", NavigationMapType.NONE.id, null); |
| | | System.out.println(calc); |
| | | System.out.println("------------------------"); |
| | | // List<NavigateNode> calc = calc("0501401", "0201801", "out"); |
| | | //将路径分割成多段 |
| | | ArrayList<ArrayList<NavigateNode>> data = getSectionPath(calc); |
| | | for (ArrayList<NavigateNode> list : data) { |
| | | Integer currentPathAllDistance = getCurrentPathAllDistance(list);//计算当前路径总距离 |
| | | System.out.println(currentPathAllDistance); |
| | | System.out.println(list); |
| | | private NavigateNode pythonObjTransferNode(Object obj, Integer z) { |
| | | List<Integer> pathData = JSON.parseArray(obj.toString(), Integer.class); |
| | | Integer x = pathData.get(0); |
| | | Integer y = pathData.get(1); |
| | | |
| | | NavigateNode node = new NavigateNode(x, y); |
| | | node.setDirection(null); |
| | | node.setIsInflectionPoint(false); |
| | | node.setZ(z); |
| | | return node; |
| | | } |
| | | |
| | | public Double similarityPath(List<NavigateNode> firstPath, List<NavigateNode> secondPath) { |
| | | try { |
| | | List<int[]> first = new ArrayList<>(); |
| | | for (NavigateNode node : firstPath) { |
| | | first.add(new int[]{node.getX(), node.getY()}); |
| | | } |
| | | |
| | | List<int[]> second = new ArrayList<>(); |
| | | for (NavigateNode node : secondPath) { |
| | | second.add(new int[]{node.getX(), node.getY()}); |
| | | } |
| | | |
| | | ProcessBuilder processBuilder = new ProcessBuilder("python", pythonCalcSimilarity, JSON.toJSONString(first), JSON.toJSONString(second)); |
| | | processBuilder.redirectErrorStream(true); |
| | | |
| | | Process process = processBuilder.start(); |
| | | |
| | | // 读取Python脚本的输出 |
| | | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); |
| | | String line; |
| | | StringBuilder builder = new StringBuilder(); |
| | | while ((line = reader.readLine()) != null) { |
| | | builder.append(line); |
| | | } |
| | | |
| | | // 等待Python脚本执行完成 |
| | | int exitCode = process.waitFor(); |
| | | if (exitCode != 0) { |
| | | System.out.println("Python script exited with error code: " + exitCode); |
| | | return null; |
| | | } |
| | | reader.close(); |
| | | |
| | | if (builder.length() <= 0) { |
| | | return null; |
| | | } |
| | | |
| | | PythonSimilarityResult result = JSON.parseObject(builder.toString(), PythonSimilarityResult.class); |
| | | if (result.getCalcResult() != 200) { |
| | | return 0D; |
| | | } |
| | | |
| | | Double similarity = result.getSimilarity(); |
| | | return similarity; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return 0D; |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | // //计算路径 |
| | | // List<NavigateNode> calc = calc("1000901", "1800201", NavigationMapType.NONE.id, null); |
| | | // System.out.println(calc); |
| | | // System.out.println("------------------------"); |
| | | //// List<NavigateNode> calc = calc("0501401", "0201801", "out"); |
| | | // //将路径分割成多段 |
| | | // ArrayList<ArrayList<NavigateNode>> data = getSectionPath(calc); |
| | | // for (ArrayList<NavigateNode> list : data) { |
| | | // Integer currentPathAllDistance = getCurrentPathAllDistance(list);//计算当前路径总距离 |
| | | // System.out.println(currentPathAllDistance); |
| | | // System.out.println(list); |
| | | // } |
| | | |
| | | System.loadLibrary("example"); |
| | | |
| | | } |
| | | |
| | |
| | | private ShuttleStandbyService shuttleStandbyService; |
| | | @Autowired |
| | | private DictService dictService; |
| | | @Autowired |
| | | private NavigateUtils navigateUtils; |
| | | |
| | | public synchronized ShuttleThread searchIdleShuttle(Task task) { |
| | | String locNo = taskService.judgeInbound(task) ? task.getDestLoc() : task.getOriginLoc(); |
| | |
| | | //获取同层小车 |
| | | List<Device> currentLevDevices = new ArrayList<>(); |
| | | //获取跨层小车 |
| | | List<Device> diffLevDevices = new ArrayList<>(); |
| | | HashMap<Integer,List<Device>> diffLevDeviceMap = new HashMap<>(); |
| | | for (Device device : list) { |
| | | //获取四向穿梭车线程 |
| | | ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); |
| | |
| | | continue; |
| | | } |
| | | |
| | | if (Utils.getLev(shuttleProtocol.getCurrentLocNo()) == lev) { |
| | | int shuttleLev = Utils.getLev(shuttleProtocol.getCurrentLocNo()); |
| | | if (shuttleLev == lev) { |
| | | currentLevDevices.add(device); |
| | | }else { |
| | | diffLevDevices.add(device); |
| | | List<Device> devices = null; |
| | | if(diffLevDeviceMap.containsKey(shuttleLev)) { |
| | | devices = diffLevDeviceMap.get(shuttleLev); |
| | | }else { |
| | | devices = new ArrayList<>(); |
| | | } |
| | | devices.add(device); |
| | | diffLevDeviceMap.put(shuttleLev, devices); |
| | | } |
| | | } |
| | | //搜索同层 |
| | |
| | | |
| | | //同层没有搜索到合适小车,跨楼层搜索 |
| | | if(resThread == null) { |
| | | resThread = this.searchDiffLevShuttle(diffLevDevices, locNo, task); |
| | | resThread = this.searchDiffLevShuttle(diffLevDeviceMap, locNo, task); |
| | | } |
| | | |
| | | return resThread; |
| | |
| | | |
| | | // 同楼层直接计算到目标库位 |
| | | //当前穿梭车线程到当前车子所在楼层的目标库位距离 |
| | | List<NavigateNode> currentShuttlePath = NavigateUtils.calc( |
| | | List<NavigateNode> currentShuttlePath = navigateUtils.calc( |
| | | currentLocNo |
| | | , locNo |
| | | , NavigationMapType.NORMAL.id |
| | |
| | | continue; |
| | | } |
| | | |
| | | Integer currDistance = NavigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 |
| | | Integer currDistance = navigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 |
| | | |
| | | // 挂载任务权重 |
| | | List<Task> tasks = taskService.selectWorkingByShuttle(Integer.valueOf(device.getDeviceNo()), null); |
| | |
| | | return resThread; |
| | | } |
| | | |
| | | private synchronized ShuttleThread searchDiffLevShuttle(List<Device> devices, String locNo, Task task) { |
| | | private synchronized ShuttleThread searchDiffLevShuttle(HashMap<Integer,List<Device>> devicesMap, String locNo, Task task) { |
| | | ShuttleThread resThread = null; |
| | | Integer finalDistance = ShuttleDispatcher.INF; |
| | | |
| | | //检测目标楼层车数量是否小于允许的最大数量 |
| | | boolean checkDispatchMaxNum = checkDispatchMaxNum(Utils.getLev(locNo), task.getHostId()); |
| | | |
| | | for (Device device : devices) { |
| | | if (taskService.hasBusyOutboundByShuttle(Integer.parseInt(device.getDeviceNo()))) { |
| | | continue; |
| | | } |
| | | //获取四向穿梭车线程 |
| | | ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); |
| | | ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); |
| | | if (shuttleProtocol == null || shuttleProtocol.getShuttleNo() == null) { |
| | | continue; |
| | | } |
| | | for (Map.Entry<Integer, List<Device>> entry : devicesMap.entrySet()) { |
| | | Integer lev = entry.getKey(); |
| | | List<Device> devices = entry.getValue(); |
| | | for (Device device : devices) { |
| | | if (taskService.hasBusyOutboundByShuttle(Integer.parseInt(device.getDeviceNo()))) { |
| | | continue; |
| | | } |
| | | //获取四向穿梭车线程 |
| | | ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, device.getId().intValue()); |
| | | ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(); |
| | | if (shuttleProtocol == null || shuttleProtocol.getShuttleNo() == null) { |
| | | continue; |
| | | } |
| | | |
| | | if (!shuttleThread.isIdle()) { |
| | | continue; |
| | | } |
| | | if (!shuttleThread.isIdle()) { |
| | | continue; |
| | | } |
| | | |
| | | BasShuttle basShuttle = basShuttleService.getOne(new LambdaQueryWrapper<BasShuttle>() |
| | | .eq(BasShuttle::getShuttleNo, device.getDeviceNo()) |
| | | .eq(BasShuttle::getHostId, device.getHostId())); |
| | | if (basShuttle == null) { |
| | | continue;//小车基础数据不存在 |
| | | } |
| | | BasShuttle basShuttle = basShuttleService.getOne(new LambdaQueryWrapper<BasShuttle>() |
| | | .eq(BasShuttle::getShuttleNo, device.getDeviceNo()) |
| | | .eq(BasShuttle::getHostId, device.getHostId())); |
| | | if (basShuttle == null) { |
| | | continue;//小车基础数据不存在 |
| | | } |
| | | |
| | | if (!Cools.isEmpty(basShuttle.getDisableLev())) { |
| | | List<Integer> disableLev = JSON.parseArray(basShuttle.getDisableLev(), Integer.class); |
| | | //检查小车是否禁用该楼层 |
| | | if (disableLev.contains(Utils.getLev(locNo))) { |
| | | continue;//小车禁用该楼层跳过该车 |
| | | if (!Cools.isEmpty(basShuttle.getDisableLev())) { |
| | | List<Integer> disableLev = JSON.parseArray(basShuttle.getDisableLev(), Integer.class); |
| | | //检查小车是否禁用该楼层 |
| | | if (disableLev.contains(Utils.getLev(locNo))) { |
| | | continue;//小车禁用该楼层跳过该车 |
| | | } |
| | | } |
| | | |
| | | //检测是否存在充电任务 |
| | | Task taskCharge = taskService.selectChargeWorking(Integer.valueOf(device.getDeviceNo())); |
| | | if (taskCharge != null) { |
| | | continue; |
| | | } |
| | | |
| | | // 有没有被其他任务调度 |
| | | int currentLev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车当前层高 |
| | | String currentLocNo = shuttleProtocol.getCurrentLocNo();//小车当前库位号 |
| | | |
| | | if (!checkDispatchMaxNum) { |
| | | News.info("{}任务,{}层,已经达到当前楼层调度车辆最大值", task.getTaskNo(), Utils.getLev(locNo)); |
| | | continue; |
| | | } |
| | | |
| | | //获取距离小车位置最近的空闲可换层提升机 |
| | | LiftThread liftThread = liftDispatcher.searchIdleLift(currentLocNo, task.getHostId(), true); |
| | | if (liftThread == null) { |
| | | continue; |
| | | } |
| | | Device recentTransferLift = liftThread.getDevice(); |
| | | |
| | | //获取小车楼层提升机待机位 |
| | | ShuttleStandby shuttleStandby = shuttleStandbyService.getOne(new LambdaQueryWrapper<ShuttleStandby>() |
| | | .eq(ShuttleStandby::getDeviceId, recentTransferLift.getId()) |
| | | .eq(ShuttleStandby::getDeviceLev, currentLev) |
| | | .eq(ShuttleStandby::getStatus, 1)); |
| | | String targetLocNo = shuttleStandby.getDeviceLoc(); |
| | | |
| | | //当前穿梭车线程到当前车子所在楼层的提升机待机位距离 |
| | | List<NavigateNode> currentShuttlePath = navigateUtils.calc( |
| | | currentLocNo |
| | | , targetLocNo |
| | | , NavigationMapType.NORMAL.id |
| | | , Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), currentLev) |
| | | );//搜索空闲穿梭车,使用正常通道地图 |
| | | if (currentShuttlePath == null) { |
| | | continue; |
| | | } |
| | | |
| | | Integer currDistance = navigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 |
| | | |
| | | // 不同楼层权重 |
| | | if (currentLev != Utils.getLev(locNo)) { |
| | | currDistance += WEIGHT; |
| | | } |
| | | |
| | | // 挂载任务权重 |
| | | List<Task> tasks = taskService.selectWorkingByShuttle(Integer.valueOf(device.getDeviceNo()), null); |
| | | if (!Cools.isEmpty(tasks)) { |
| | | currDistance += tasks.size() * WEIGHT; |
| | | } |
| | | |
| | | if (currDistance < finalDistance) { |
| | | finalDistance = currDistance; |
| | | resThread = shuttleThread; |
| | | } |
| | | } |
| | | |
| | | //检测是否存在充电任务 |
| | | Task taskCharge = taskService.selectChargeWorking(Integer.valueOf(device.getDeviceNo())); |
| | | if (taskCharge != null) { |
| | | continue; |
| | | } |
| | | |
| | | // 有没有被其他任务调度 |
| | | int currentLev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车当前层高 |
| | | String currentLocNo = shuttleProtocol.getCurrentLocNo();//小车当前库位号 |
| | | |
| | | if (!checkDispatchMaxNum) { |
| | | News.info("{}任务,{}层,已经达到当前楼层调度车辆最大值", task.getTaskNo(), Utils.getLev(locNo)); |
| | | continue; |
| | | } |
| | | |
| | | //获取距离小车位置最近的空闲可换层提升机 |
| | | LiftThread liftThread = liftDispatcher.searchIdleLift(currentLocNo, task.getHostId(), true); |
| | | if (liftThread == null) { |
| | | continue; |
| | | } |
| | | Device recentTransferLift = liftThread.getDevice(); |
| | | |
| | | //获取小车楼层提升机待机位 |
| | | ShuttleStandby shuttleStandby = shuttleStandbyService.getOne(new LambdaQueryWrapper<ShuttleStandby>() |
| | | .eq(ShuttleStandby::getDeviceId, recentTransferLift.getId()) |
| | | .eq(ShuttleStandby::getDeviceLev, currentLev) |
| | | .eq(ShuttleStandby::getStatus, 1)); |
| | | String targetLocNo = shuttleStandby.getDeviceLoc(); |
| | | |
| | | //当前穿梭车线程到当前车子所在楼层的提升机待机位距离 |
| | | List<NavigateNode> currentShuttlePath = NavigateUtils.calc( |
| | | currentLocNo |
| | | , targetLocNo |
| | | , NavigationMapType.NORMAL.id |
| | | , Utils.getShuttlePoints(Integer.parseInt(shuttleThread.getDevice().getDeviceNo()), currentLev) |
| | | );//搜索空闲穿梭车,使用正常通道地图 |
| | | if (currentShuttlePath == null) { |
| | | continue; |
| | | } |
| | | |
| | | Integer currDistance = NavigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 |
| | | |
| | | // 不同楼层权重 |
| | | if (currentLev != Utils.getLev(locNo)) { |
| | | currDistance += WEIGHT; |
| | | } |
| | | |
| | | // 挂载任务权重 |
| | | List<Task> tasks = taskService.selectWorkingByShuttle(Integer.valueOf(device.getDeviceNo()), null); |
| | | if (!Cools.isEmpty(tasks)) { |
| | | currDistance += tasks.size() * WEIGHT; |
| | | } |
| | | |
| | | if (currDistance < finalDistance) { |
| | | finalDistance = currDistance; |
| | | resThread = shuttleThread; |
| | | if (resThread != null) { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | return resThread; |
| | | } |
| | | |
| | |
| | | String recentLoc = null; |
| | | for (String loc : locNos) { |
| | | //当前穿梭车到避让位计算 |
| | | List<NavigateNode> currentShuttlePath = NavigateUtils.calc( |
| | | List<NavigateNode> currentShuttlePath = navigateUtils.calc( |
| | | currentLocNo |
| | | , loc |
| | | , NavigationMapType.NORMAL.id |
| | |
| | | continue; |
| | | } |
| | | |
| | | Integer currDistance = NavigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 |
| | | Integer currDistance = navigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离 |
| | | if (currDistance < finalDistance) { |
| | | finalDistance = currDistance; |
| | | recentLoc = loc; |
| | |
| | | //分析出库路径待机库位 |
| | | public String analyzeOutPathWaitLoc(String startLoc, String targetLoc, Device shuttleDevice) { |
| | | //计算路径并分解成两段动作 |
| | | List<NavigateNode> nodeList = NavigateUtils.calc(startLoc, targetLoc, NavigationMapType.DFX.id, Utils.getShuttlePoints(Integer.parseInt(shuttleDevice.getDeviceNo()), Utils.getLev(startLoc))); |
| | | List<NavigateNode> nodeList = navigateUtils.calc(startLoc, targetLoc, NavigationMapType.DFX.id, Utils.getShuttlePoints(Integer.parseInt(shuttleDevice.getDeviceNo()), Utils.getLev(startLoc))); |
| | | if (nodeList == null) { |
| | | News.error("{} dash {} can't find navigate path!", startLoc, targetLoc); |
| | | return null; |
| | | } |
| | | //获取分段路径 |
| | | ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(nodeList); |
| | | ArrayList<ArrayList<NavigateNode>> data = navigateUtils.getSectionPath(nodeList); |
| | | if (data.size() <= 1) { |
| | | return startLoc;//两点之间只有一段路径,在起点位置等待 |
| | | } |
| | |
| | | |
| | | public static final String MAP = "realtimeBasMap_"; |
| | | |
| | | public static final String BASE_MAP = "BaseMap_"; |
| | | |
| | | public static final String LOCK_PATH = "mapLockPath_"; |
| | | |
| | | public static final String COMMAND_TMP = "command_tmp_"; |
| | | |
| | | public static final String SIMILARITY_TIMES = "similarity_times_"; |
| | | |
| | | public static final String LIFT_PALLET_INBOUND = "lift_pallet_inbound_"; |
| | | |
| | | } |
| | |
| | | public synchronized CommandResponse movePath(List<NavigateNode> nodes, Integer taskNo) { |
| | | CommandResponse response = new CommandResponse(false); |
| | | try { |
| | | NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class); |
| | | //默认地图母轨方向x |
| | | String mapDirection = "x"; |
| | | DictService dictService = SpringUtils.getBean(DictService.class); |
| | |
| | | |
| | | ArrayList<HashMap<String, Object>> modes = new ArrayList<>(); |
| | | //获取分段路径 |
| | | ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(nodes); |
| | | ArrayList<ArrayList<NavigateNode>> data = navigateUtils.getSectionPath(nodes); |
| | | for (int idx = 0; idx < data.size(); idx++) { |
| | | ArrayList<NavigateNode> sectionNodes = data.get(idx); |
| | | boolean isRemoveFooterNode = false;//是否剔除尾节点 |
| | |
| | | pwd: xltys1995 |
| | | |
| | | config: |
| | | token-key: KUHSMcYQ4lePt3r6bckz0P13cBJyoonYqInThvQlUnbsFCIcCcZZAbWZ6UNFztYNYPhGdy6eyb8WdIz8FU2Cz396TyTJk3NI2rtXMHBOehRb4WWJ4MdYVVg2oWPyqRQ2 |
| | | token-key: KUHSMcYQ4lePt3r6bckz0P13cBJyoonYqInThvQlUnbsFCIcCcZZAbWZ6UNFztYNYPhGdy6eyb8WdIz8FU2Cz396TyTJk3NI2rtXMHBOehRb4WWJ4MdYVVg2oWPyqRQ2 |
| | | |
| | | pythonCalcPath: D:\\path\\cpu.py |
| | | pythonCalcSimilarity: D:\\path\\similarity.py |
New file |
| | |
| | | import json |
| | | |
| | | import numpy as np |
| | | import time |
| | | import heapq |
| | | import sys |
| | | import ast |
| | | |
| | | startTime = time.perf_counter() |
| | | |
| | | # 创建一个简单的网格,0 为通行,1 为障碍 |
| | | # grid = np.array([ |
| | | # [0, 0, 0, 0, 0, 3, 0, 0, 3, 0], |
| | | # [0, 0, 0, 0, 0, 3, 0, 0, 3, 0], |
| | | # [1, 0, 0, 0, 0, 3, 0, 0, 3, 0], |
| | | # [0, 0, 0, 0, 0, 3, 0, 0, 3, 0], |
| | | # [0, 0, 1, 0, 0, 3, 0, 0, 3, 0], |
| | | # [0, 0, 0, 0, 0, 3, 0, 0, 3, 0], |
| | | # [0, 0, 0, 0, 1, 3, 0, 0, 3, 0], |
| | | # [0, 0, 0, 0, 0, 3, 0, 0, 3, 0], |
| | | # [0, 0, 0, 0, 0, 3, 0, 0, 3, 0], |
| | | # [0, 0, 0, 0, 0, 3, 0, 0, 3, 0], |
| | | # [0, 0, 0, 0, 0, 3, 1, 0, 3, 0], |
| | | # [0, 0, 0, 0, 0, 3, 0, 0, 3, 0], |
| | | # [0, 0, 0, 1, 0, 3, 0, 0, 3, 0], |
| | | # [0, 0, 0, 0, 0, 3, 0, 0, 3, 0] |
| | | # ]) |
| | | # grid = np.array([[-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, -1], [-1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1, -1, -1, -1, 3, 3, 3, 3, 3, 3, 3, -1], [-1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -1, 4, -1, 0, 0, 0, -1, 0, 0, 0, -1], [-1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -1, 4, -1, 0, 0, 0, -1, 0, 0, 0, -1], [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, -1], [-1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1], [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1], [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1], [-1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1], [-1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1], [-1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1, -1, -1, -1, -1, -1, -1, -1], [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 4, -1, -1, -1, -1], [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 4, 4, -1, -1, -1]]) |
| | | |
| | | # A* 算法实现 |
| | | def heuristic(a, b): |
| | | # 使用曼哈顿距离作为启发式估计 |
| | | return abs(a[0] - b[0]) + abs(a[1] - b[1]) |
| | | |
| | | def astar_search(grid, start, goal, mapDirection): |
| | | rows, cols = grid.shape |
| | | start = (start // cols, start % cols) |
| | | goal = (goal // cols, goal % cols) |
| | | |
| | | open_set = [] |
| | | heapq.heappush(open_set, (0, start)) |
| | | |
| | | came_from = {} |
| | | g_score = {start: 0} |
| | | f_score = {start: heuristic(start, goal)} |
| | | |
| | | while open_set: |
| | | current = heapq.heappop(open_set)[1] |
| | | |
| | | if current == goal: |
| | | return reconstruct_path(came_from, current) |
| | | |
| | | # 确定当前节点值 |
| | | current_value = grid[current[0], current[1]] |
| | | |
| | | neighbors = findNebor(current, current_value, mapDirection) |
| | | |
| | | for neighbor in neighbors: |
| | | # 检查邻居是否在网格内且通行 |
| | | if 0 <= neighbor[0] < rows and 0 <= neighbor[1] < cols: |
| | | if grid[neighbor] <= -1: |
| | | continue |
| | | |
| | | if grid[neighbor] in [66]: |
| | | continue |
| | | |
| | | tentative_g_score = g_score[current] + 1 |
| | | |
| | | if neighbor not in g_score or tentative_g_score < g_score[neighbor]: |
| | | came_from[neighbor] = current |
| | | g_score[neighbor] = tentative_g_score |
| | | f_score[neighbor] = tentative_g_score + heuristic(neighbor, goal) |
| | | |
| | | if neighbor not in [i[1] for i in open_set]: |
| | | heapq.heappush(open_set, (f_score[neighbor], neighbor)) |
| | | |
| | | return [] |
| | | |
| | | def reconstruct_path(came_from, current): |
| | | total_path = [current] |
| | | while current in came_from: |
| | | current = came_from[current] |
| | | total_path.append(current) |
| | | return total_path[::-1] # 反转路径 |
| | | |
| | | def findNebor(current,current_value, direction): |
| | | neighbors = [] |
| | | |
| | | if direction == "x": |
| | | if current_value == 3: |
| | | neighbors = [(current[0] + 1, current[1]), (current[0] - 1, current[1])] |
| | | |
| | | if current_value == 0 or current_value == 3 or current_value == 5 or current_value == 6 or current_value == 67: |
| | | neighbors.append((current[0], current[1] + 1)) |
| | | neighbors.append((current[0], current[1] - 1)) |
| | | else: |
| | | if current_value == 3: |
| | | neighbors = [(current[0], current[1] + 1), (current[0], current[1] - 1)] |
| | | |
| | | if current_value == 0 or current_value == 3 or current_value == 5 or current_value == 6 or current_value == 67: |
| | | neighbors.append((current[0] + 1, current[1])) |
| | | neighbors.append((current[0] - 1, current[1])) |
| | | return neighbors |
| | | |
| | | maps = sys.argv[1] |
| | | start_str = sys.argv[2] |
| | | goal_str = sys.argv[3] |
| | | mapDirection = sys.argv[4] |
| | | |
| | | maps = ast.literal_eval(maps) |
| | | grid = np.array(maps) |
| | | # print(type(maps)) |
| | | # print(start_str) |
| | | # print(goal_str) |
| | | |
| | | start_coords = (int(start_str.split('-')[0]), int(start_str.split('-')[1])) |
| | | goal_coords = (int(goal_str.split('-')[0]), int(goal_str.split('-')[1])) |
| | | |
| | | |
| | | # print(start_coords, goal_coords) |
| | | # # 定义起点和终点的坐标 |
| | | # start_coords = (1, 1) # 起点坐标 (行, 列) |
| | | # goal_coords = (11, 6) # 终点坐标 (行, 列) |
| | | |
| | | # 将坐标转换为一维索引 |
| | | start = start_coords[0] * grid.shape[1] + start_coords[1] |
| | | goal = goal_coords[0] * grid.shape[1] + goal_coords[1] |
| | | |
| | | try: |
| | | # 获取路径 |
| | | path_coordinates = astar_search(grid, start, goal, mapDirection) |
| | | except: |
| | | path_coordinates = [] |
| | | |
| | | end = time.perf_counter() |
| | | # print("最短路径坐标:", path_coordinates) |
| | | # print('程序运行时间为: %s Seconds' % (end - startTime)) |
| | | |
| | | calcResult = 200 |
| | | if(len(path_coordinates) == 0): |
| | | calcResult = 500 |
| | | |
| | | result = { |
| | | "start": start_str, |
| | | "target": goal_str, |
| | | "path": json.dumps(path_coordinates), |
| | | "time": (end - startTime), |
| | | "calcResult": calcResult |
| | | } |
| | | |
| | | print(result) |
New file |
| | |
| | | import json |
| | | import sys |
| | | |
| | | |
| | | def calculate_similarity(path1, path2): |
| | | # 将路径转换为集合 |
| | | set1 = set(path1) |
| | | set2 = set(path2) |
| | | |
| | | # 计算重叠节点 |
| | | overlap = len(set1.intersection(set2)) |
| | | |
| | | # 计算总节点 |
| | | total_nodes = len(set1.union(set2)) |
| | | |
| | | # 计算相似度 |
| | | similarity = overlap / total_nodes if total_nodes > 0 else 0 |
| | | |
| | | return similarity |
| | | |
| | | path_a_str = sys.argv[1] |
| | | path_b_str = sys.argv[2] |
| | | |
| | | path_a = json.loads(path_a_str) |
| | | path_a = [(int(x[0]), int(x[1])) for x in path_a] |
| | | |
| | | path_b = json.loads(path_b_str) |
| | | path_b = [(int(x[0]), int(x[1])) for x in path_b] |
| | | |
| | | # # 示例路径 |
| | | # path_a = [(1, 1), (1, 2), (1, 3), (1, 4), (2, 4), (3, 4), (4, 4), (5, 4), (6, 4), (7, 4), (8, 4), (9, 4), (10, 4), (10, 5), (10, 6), (11, 6)] |
| | | # path_b = [(1, 1), (1, 2), (1, 3), (1, 4), (2, 4), (3, 4), (4, 4), (5, 4), (6, 4), (7, 4), (8, 4), (9, 4), (10, 4), (10, 5), (10, 6), (11, 6)] |
| | | |
| | | |
| | | # 计算相似度 |
| | | similarity_score = calculate_similarity(path_a, path_b) |
| | | |
| | | calcResult = 200 |
| | | |
| | | result = { |
| | | "firstPath": json.dumps(path_a), |
| | | "secondPath": json.dumps(path_b), |
| | | "similarity": similarity_score, |
| | | "calcResult": calcResult |
| | | } |
| | | |
| | | print(result) |