From ff7f41f5d6c99bff4a1d85a5b3342eec5a8fee0c Mon Sep 17 00:00:00 2001 From: luxiaotao1123 <t1341870251@163.com> Date: 星期四, 07 十一月 2024 08:52:34 +0800 Subject: [PATCH] # --- zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java | 235 ++++++++++++++++++++++++++++++++++++++++------------------ 1 files changed, 160 insertions(+), 75 deletions(-) diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java index 434718d..89d03da 100644 --- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java +++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java @@ -3,9 +3,6 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.zy.acs.framework.common.Cools; -import com.zy.acs.framework.common.SnowflakeIdWorker; -import com.zy.acs.framework.exception.CoolException; import com.zy.acs.common.domain.AgvAction; import com.zy.acs.common.domain.AgvActionItem; import com.zy.acs.common.domain.AgvProtocol; @@ -14,10 +11,18 @@ import com.zy.acs.common.domain.protocol.AGV_70_UP; import com.zy.acs.common.domain.protocol.IMessageBody; import com.zy.acs.common.domain.protocol.action.*; -import com.zy.acs.common.enums.*; +import com.zy.acs.common.enums.AgvBackpackType; +import com.zy.acs.common.enums.AgvCompleteType; +import com.zy.acs.common.enums.AgvDirectionType; +import com.zy.acs.common.enums.AgvSpeedType; +import com.zy.acs.common.utils.RedisSupport; import com.zy.acs.common.utils.Utils; +import com.zy.acs.framework.common.Cools; +import com.zy.acs.framework.common.SnowflakeIdWorker; +import com.zy.acs.framework.exception.CoolException; import com.zy.acs.manager.common.domain.TaskDto; import com.zy.acs.manager.common.exception.BusinessException; +import com.zy.acs.manager.common.utils.CommonUtil; import com.zy.acs.manager.core.domain.AgvBackpackDto; import com.zy.acs.manager.core.domain.TaskPosDto; import com.zy.acs.manager.core.service.astart.MapDataDispatcher; @@ -45,6 +50,7 @@ @Component("mainService") public class MainService { + private final RedisSupport redis = RedisSupport.defaultRedisSupport; private static final int LOCK_TIMEOUT = 5; private final ReentrantLock lock = new ReentrantLock(Boolean.TRUE); @@ -67,6 +73,8 @@ @Autowired private ValidService validService; @Autowired + private AllocateService allocateService; + @Autowired private CodeService codeService; @Autowired private MapService mapService; @@ -88,8 +96,7 @@ private TrafficService trafficService; @Autowired private AgvModelService agvModelService; - @Autowired - private MissionAssignService missionAssignService; + @SuppressWarnings("all") @Transactional @@ -101,14 +108,14 @@ String batch = busSubmitParam.getBatch(); List<TaskDto> taskDtoList = busSubmitParam.getTaskList(); if (Cools.isEmpty(taskDtoList)) { - throw new BusinessException("taskDtoList 涓嶈兘涓虹┖"); + throw new BusinessException("taskList can't be empty!"); } // 浼樺厛绾ф帓搴� taskDtoList.sort((o1, o2) -> o2.getPriority() - o1.getPriority()); // 鏍¢獙 - List<Task> taskList = validService.validBusDto(taskDtoList); + List<Task> taskList = validService.validTaskDtoList(taskDtoList); // 淇濆瓨鎬荤嚎 Date now = new Date(); @@ -120,7 +127,7 @@ bus.setMemo(memo); if (!busService.save(bus)) { - throw new BusinessException("浠诲姟淇濆瓨澶辫触"); + throw new BusinessException("Internal Server Error!"); } // 淇濆瓨浠诲姟 @@ -128,7 +135,7 @@ task.setBusId(bus.getId()); task.setTaskSts(TaskStsType.INIT.val()); if (!taskService.save(task)) { - throw new BusinessException(task.getSeqNum() + "浠诲姟淇濆瓨澶辫触"); + throw new BusinessException("seqNum:" + task.getSeqNum() + " failed to save!"); } // 淇敼搴撲綅鐘舵�� @@ -140,44 +147,44 @@ case LOC_TO_LOC: oriLoc = locService.getById(task.getOriLoc()); if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) { - throw new BusinessException("oriLoc锛�" + task.getOriLoc$() + " 涓嶆槸鍦ㄥ簱鐘舵��"); + throw new BusinessException("oriLoc锛�" + task.getOriLoc$() + " is not in STOCK status"); } oriLoc.setLocSts(LocStsType.PAKOUT.val()); oriLoc.setUpdateTime(now); if (!locService.updateById(oriLoc)) { - throw new BusinessException("oriLoc锛�" + task.getOriLoc$() + " 淇敼搴撲綅鐘舵�佸け璐�"); + throw new BusinessException("oriLoc锛�" + task.getOriLoc$() + " failed to update"); } destLoc = locService.getById(task.getDestLoc()); if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) { - throw new BusinessException("destLoc锛�" + task.getDestLoc$() + " 涓嶆槸绌洪棽鐘舵��"); + throw new BusinessException("destLoc锛�" + task.getDestLoc$() + " is not in IDLE status"); } destLoc.setLocSts(LocStsType.PAKIN.val()); destLoc.setUpdateTime(now); if (!locService.updateById(destLoc)) { - throw new BusinessException("destLoc锛�" + task.getDestLoc$() + " 淇敼搴撲綅鐘舵�佸け璐�"); + throw new BusinessException("destLoc锛�" + task.getDestLoc$() + " failed to update"); } break; case LOC_TO_STA: oriLoc = locService.getById(task.getOriLoc()); if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) { - throw new BusinessException("oriLoc锛�" + task.getOriLoc$() + " 涓嶆槸鍦ㄥ簱鐘舵��"); + throw new BusinessException("oriLoc锛�" + task.getOriLoc$() + " is not in STOCK status"); } oriLoc.setLocSts(LocStsType.PAKOUT.val()); oriLoc.setUpdateTime(now); if (!locService.updateById(oriLoc)) { - throw new BusinessException("oriLoc锛�" + task.getOriLoc$() + " 淇敼搴撲綅鐘舵�佸け璐�"); + throw new BusinessException("oriLoc锛�" + task.getOriLoc$() + " failed to update"); } break; case STA_TO_LOC: destLoc = locService.getById(task.getDestLoc()); if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) { - throw new BusinessException("destLoc锛�" + task.getDestLoc$() + " 涓嶆槸绌洪棽鐘舵��"); + throw new BusinessException("destLoc锛�" + task.getDestLoc$() + " is not in IDLE status"); } destLoc.setLocSts(LocStsType.PAKIN.val()); destLoc.setUpdateTime(now); if (!locService.updateById(destLoc)) { - throw new BusinessException("destLoc锛�" + task.getDestLoc$() + " 淇敼搴撲綅鐘舵�佸け璐�"); + throw new BusinessException("destLoc锛�" + task.getDestLoc$() + " failed to update"); } break; case STA_TO_STA: @@ -194,7 +201,7 @@ * 浠诲姟鍒嗛厤缁欒溅杈� ( 杞﹁締姝ゆ椂鏄┖闂蹭笖闈欐鐨� ) */ @Transactional - public synchronized void infuseAgvForTask(Bus bus) { + public synchronized void allocateTask(Bus bus) { try { Date now = new Date(); List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>() @@ -207,39 +214,54 @@ bus.setBusSts(BusStsType.PROGRESS.val()); bus.setUpdateTime(now); if (!busService.updateById(bus)) { - log.error("Bus [{}] 鏇存柊澶辫触 锛侊紒锛�", bus.getUuid()); + log.error("Bus [{}] failed to Update 锛侊紒锛�", bus.getUuid()); } return; } - List<Long> taskIds = taskList.stream().map(Task::getId).distinct().collect(Collectors.toList()); - Map<String, List<Long>> taskAllot = new HashMap<>(); + List<Long> taskIds = taskList.stream().map(Task::getId).distinct().collect(Collectors.toList()); for (Task task : taskList) { - Agv agv = missionAssignService.execute(task, taskAllot, taskIds); + Agv agv = allocateService.execute(task); if (null == agv) { - log.warn("{}浠诲姟寮傚父锛屾棤娉曟绱㈢┖闂睞gv...", task.getSeqNum()); + log.warn("Task[{}] has an issue锛� because it failed to checkout agv which is idle...", task.getSeqNum()); continue; } - - task.setAgvId(agv.getId()); task.setTaskSts(TaskStsType.WAITING.val()); task.setIoTime(now); task.setUpdateTime(now); if (!taskService.updateById(task)) { - throw new BusinessException(task.getSeqNum() + "浠诲姟鏇存柊澶辫触"); - } - - if (taskAllot.containsKey(agv.getUuid())) { - taskAllot.get(agv.getUuid()).add(task.getId()); - } else { - taskAllot.put(agv.getUuid(), Utils.singletonList(task.getId())); + throw new BusinessException("seqNum: " + task.getSeqNum() + " failed to update"); } } -// bus.setUpdateTime(now); -// if (!busService.updateById(bus)) { -// throw new BusinessException(bus.getSeqNum() + "鎬荤嚎鏇存柊澶辫触"); + + // ------------------------------------------ + + +// +// Map<String, List<Long>> taskAllot = new HashMap<>(); +// for (Task task : taskList) { +// Agv agv = missionAssignService.execute(task, taskAllot, taskIds); +// if (null == agv) { +// log.warn("Task[{}] has an issue锛� because it failed to checkout agv which is idle...", task.getSeqNum()); +// continue; +// } +// +// +// task.setAgvId(agv.getId()); +// task.setTaskSts(TaskStsType.WAITING.val()); +// task.setIoTime(now); +// task.setUpdateTime(now); +// if (!taskService.updateById(task)) { +// throw new BusinessException("seqNum: " + task.getSeqNum() + " failed to update"); +// } +// +// if (taskAllot.containsKey(agv.getUuid())) { +// taskAllot.get(agv.getUuid()).add(task.getId()); +// } else { +// taskAllot.put(agv.getUuid(), Utils.singletonList(task.getId())); +// } // } } catch (Exception e) { log.error("mainService.infuseAgvForTask", e); @@ -251,38 +273,30 @@ * 瑙f瀽鍙栨斁璐ч泦鍚堜换鍔�,杩涜鏈�浼樼殑鎺掑垪缁勫悎椤哄簭 ( 杞﹁締姝ゆ椂鏄┖闂蹭笖闈欐鐨� ) */ @Transactional - public synchronized void mergeMajorTask(Long agvId, List<Task> taskList) { + public synchronized void buildMajorTask(Long agvId, List<Task> taskList) { if (Cools.isEmpty(taskList)) { return; } boolean lockAcquired = false; try { if (!(lockAcquired = this.lock.tryLock(LOCK_TIMEOUT, TimeUnit.SECONDS))) { throw new CoolException("generate [task] action fail, cause can not acquire lock ..."); } - Date now = new Date(); - final String sameGroupXy = configService.getVal( "sameGroupXy", String.class); + // valid ----------------------------------------------- Agv agv = agvService.getById(agvId); - if (!agvService.judgeEnable(agv.getId(), agvDetail -> agvDetail.getVol() > agv.getChargeLine())) { + if (!agvService.judgeEnable(agv.getId(), true)) { throw new CoolException("AGV[" + agv.getUuid() + "]褰撳墠涓嶅彲鐢�..."); } - if (!Cools.isEmpty(taskService.selectInSts(agvId, TaskStsType.ASSIGN, TaskStsType.PROGRESS))) { throw new CoolException("AGV[" + agv.getUuid() + "]鍒嗛厤浠诲姟澶辫触锛屽凡瀛樺湪鎵ц浠诲姟..."); } - AgvDetail agvDetail = agvDetailService.selectByAgvId(agvId); - assert agvDetail != null; - if (agvDetail.getPos() == 0) { - if (!agvDetail.getAgvStatus().equals(AgvStatusType.CHARGE)) { - throw new CoolException("AGV[" + agv.getUuid() + "]褰撳墠涓嶅湪瀹氫綅..."); - } - } - + // execute ---------------------------------------------------- + Date now = new Date(); // sort and sub taskList.sort(new Comparator<Task>() { @Override public int compare(Task o1, Task o2) { - return 0; + return o2.getPriority() - o1.getPriority(); } }); Integer backpack = agvService.getBackpack(agv); @@ -290,15 +304,18 @@ taskList = taskList.subList(0, backpack); } + AgvDetail agvDetail = agvDetailService.selectByAgvId(agvId); + List<AgvBackpackDto> backpackDtoList = new ArrayList<>(); + /** - * single agvId + * 鍚屽贩閬撳綊绫� + * same lane for every single agvId * - * key: y + TaskPosDto.PosType.ORI_LOC / ORI_STA / DEST_LOC / DEST_STA + * key: y(val) + TaskPosDto.PosType.ORI_LOC / ORI_STA / DEST_LOC / DEST_STA * val: new TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType) */ Map<String, List<TaskPosDto>> groups = new HashMap<>(); - - List<AgvBackpackDto> backpackDtoList = new ArrayList<>(); + final String sameGroupXy = configService.getVal( "sameGroupXy", String.class); int backpackLev = 0; for (Task task : taskList) { @@ -362,7 +379,31 @@ } /** - * List<TaskPosDto>: task list on the same channel + * 1.Map<String, List<TaskPosDto>> groups + * + * key: 1000 + ORI_LOC + * val: [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...] + * + * key: 3000 + ORI_LOC + * val: [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...] + * + * key: 2000 + ORI_LOC + * val: [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...] + * + * ...... + * + * 2.ArrayList<List<TaskPosDto>> list + * [ + * [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...], + * [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...], + * [TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType), TaskPosDto(taskId, new Double[]{code.getX(), code.getY()}, posType),...], + * ...... + * ] + */ + + /** + * 瀵规墍鏈夊贩閬撹繘琛屾湁搴忔帓搴忥紝鍏堟槸閽堝List涓轰竴涓崟浣嶏紝瀵逛粬浠繘琛孎irstWeight鎺掑簭锛岀浉褰撲簬琛�1鐨刱ey鐨勬暟鍊艰繘琛屾湁搴忔帓搴� + * List<TaskPosDto>: task list on the same lane * ArrayList<List<TaskPosDto>>: all the task list by one agv */ ArrayList<List<TaskPosDto>> list = new ArrayList<>(groups.values()); @@ -371,9 +412,53 @@ double o2CompVal = (o2.get(0).getFirstWeight(sameGroupXy) * 100) + o2.get(0).getPosType().compOffset; return (int) (o1CompVal - o2CompVal); }); - + // 閽堝Dto锛屾寜鐓econdWeight杩涜鎺掑簭 for (List<TaskPosDto> taskPosDtoList : list) { taskPosDtoList.sort((o1, o2) -> (int) (o1.getSecondWeight(sameGroupXy) * 100 - o2.getSecondWeight(sameGroupXy) * 100)); + } + + // re-order by agv current position + Code currCode = codeService.getById(agvDetail.getRecentCode()); + Double[] currPosition = new Double[] {currCode.getX(), currCode.getY()}; + + List<TaskPosDto> theFirstOne = list.get(0); + List<TaskPosDto> theLastOne = list.get(list.size() - 1); + + if (list.size() == 1) { + TaskPosDto head = theFirstOne.get(0); + TaskPosDto tail = theFirstOne.get(theFirstOne.size() - 1); + + int distanceByHead = CommonUtil.calcDistance(currPosition, head.getXy()); + int distanceByTail = CommonUtil.calcDistance(currPosition, tail.getXy()); + + if (distanceByTail < distanceByHead) { + Collections.reverse(theFirstOne); + } + + } else { + TaskPosDto headOfFirst = theFirstOne.get(0); + TaskPosDto tailOfFirst = theFirstOne.get(theFirstOne.size() - 1); + + TaskPosDto headOfLast = theLastOne.get(0); + TaskPosDto tailOfLast = theLastOne.get(theLastOne.size() - 1); + + int distanceByHeadOfFirst = CommonUtil.calcDistance(currPosition, headOfFirst.getXy()); + int distanceByTailOfFirst = CommonUtil.calcDistance(currPosition, tailOfFirst.getXy()); + + int distanceByHeadOfLast = CommonUtil.calcDistance(currPosition, headOfLast.getXy()); + int distanceByTailOfLast = CommonUtil.calcDistance(currPosition, tailOfLast.getXy()); + + if (Math.min(distanceByHeadOfLast, distanceByTailOfLast) < Math.min(distanceByHeadOfFirst, distanceByTailOfFirst)) { + Collections.reverse(list); + + if (distanceByTailOfLast < distanceByHeadOfLast) { + Collections.reverse(theLastOne); + } + } else { + if (distanceByTailOfFirst < distanceByHeadOfFirst) { + Collections.reverse(theFirstOne); + } + } } // generate travel @@ -465,15 +550,13 @@ switch (taskType) { case TO_CHARGE: case TO_STANDBY: - List<FuncSta> funcStaList = funcStaService.list(new LambdaQueryWrapper<FuncSta>() - .eq(FuncSta::getType, FuncStaType.query(taskType).toString()) - .eq(FuncSta::getAgvId, agv.getId()) - .eq(FuncSta::getState, FuncStaStateType.IDLE.toString()) - .eq(FuncSta::getStatus, StatusType.ENABLE.val) - ); - if (!Cools.isEmpty(funcStaList)) { - FuncSta funcSta = funcStaList.get(0); + List<FuncSta> idleFunStaList = funcStaService.findInIdleStatus(FuncStaType.query(taskType), agv.getId()); + if (!Cools.isEmpty(idleFunStaList)) { + FuncSta funcSta = funcStaService.checkoutClosestFunSta(agvDetail.getRecentCode(), idleFunStaList); endCode = codeService.getById(funcSta.getCode()); + } + if (null == endCode) { + log.warn("AGV[{}] failed to search destination锛宼here hadn't any idle funSta锛孴askTypeType锛歿}", agv.getUuid(), taskType.toString()); } break; case MOVE: @@ -484,7 +567,6 @@ } if (null == endCode) { - log.error("{}鍙疯溅杈嗗缓绔嬪姛鑳戒换鍔″け璐ワ紝鏃犳硶妫�绱㈠埌鐩爣瀹氫綅锛孴askTypeType锛歿}", agv.getUuid(), taskType.toString()); return false; } @@ -501,7 +583,7 @@ task.setIoTime(now); task.setStartTime(now); if (!taskService.save(task)) { - throw new BusinessException(task.getSeqNum() + "浠诲姟淇濆瓨澶辫触"); + throw new BusinessException(task.getSeqNum() + " failed to save"); } // generate travel @@ -513,7 +595,7 @@ travel.setTaskIds(JSON.toJSONString(Collections.singletonList(task.getId()))); travel.setState(TravelStateType.RUNNING.toString()); if (!travelService.save(travel)) { - throw new BusinessException("浠诲姟缁勪繚瀛樺け璐�"); + throw new BusinessException("travel failed to save"); } // generate segment @@ -552,7 +634,7 @@ next.setState(SegmentStateType.WAITING.toString()); } if (!segmentService.save(next)) { - throw new BusinessException("浠诲姟缁勪繚瀛樺け璐�"); + throw new BusinessException("segment failed to save"); } } @@ -564,7 +646,7 @@ destFuncSta.setState(FuncStaStateType.OCCUPIED.toString()); destFuncSta.setUpdateTime(now); if (!funcStaService.updateById(destFuncSta)) { - log.error("FuncSta [{}] 鏇存柊鐘舵�佸け璐� 锛侊紒锛�", destFuncSta.getName()); + log.error("FuncSta [{}] failed to update 锛侊紒锛�", destFuncSta.getName()); } break; case MOVE: @@ -572,6 +654,10 @@ default: break; } + +// if (taskType.equals(TaskTypeType.TO_STANDBY)) { +// redis.setObject(RedisConstant.AGV_TO_STANDBY_FLAG, agv.getUuid(), false); +// } return true; } catch (Exception e) { @@ -608,11 +694,6 @@ AgvDetail agvDetail = agvDetailService.selectByAgvId(agvId); assert agvDetail != null; - if (agvDetail.getPos() == 0) { - if (!agvDetail.getAgvStatus().equals(AgvStatusType.CHARGE)) { - throw new CoolException("AGV[" + agv.getUuid() + "]褰撳墠涓嶅湪瀹氫綅..."); - } - } List<Action> actionList = new ArrayList<>(); // start node @@ -999,6 +1080,7 @@ } for (Action action : actionList) { action.setActionSts(ActionStsType.ISSUED.val()); + action.setStartTime(now); action.setUpdateTime(now); if (!actionService.updateById(action)) { throw new BusinessException(action.getPriority() + " - " + action.getName() + "鍔ㄤ綔鏇存柊澶辫触"); @@ -1148,6 +1230,7 @@ if (null != action) { action.setActionSts(ActionStsType.FINISH.val()); + action.setEndTime(now); action.setUpdateTime(now); if (!actionService.updateById(action)) { log.error("Action [{}] 鏇存柊澶辫触 锛侊紒锛�", action.getPriority() + " - " + action.getName()); @@ -1180,6 +1263,7 @@ ); if (null != action) { action.setActionSts(ActionStsType.FINISH.val()); + action.setEndTime(now); action.setUpdateTime(now); if (!actionService.updateById(action)) { log.error("Action [{}] 鏇存柊澶辫触 锛侊紒锛�", action.getPriority() + " - " + action.getName()); @@ -1254,6 +1338,7 @@ ); for (Action action : actionList) { action.setActionSts(ActionStsType.FINISH.val()); + action.setEndTime(now); action.setUpdateTime(now); if (!actionService.updateById(action)) { log.error("Action [{}] 鏇存柊澶辫触 锛侊紒锛�", action.getPriority() + " - " + action.getName()); @@ -1270,7 +1355,7 @@ } // segment call back - trafficService.callback(segmentList); + segmentService.processNext(segmentList); log.info("Agv [{}] {}浣滀笟瀹屾瘯 ==========>> ", protocol.getAgvNo(), serialNo); -- Gitblit v1.9.1