From af5081bc0d0668d526a204076557a171097ddb8d Mon Sep 17 00:00:00 2001
From: zhang <zc857179121@qq.com>
Date: 星期四, 05 二月 2026 14:02:59 +0800
Subject: [PATCH] Merge branch 'refs/heads/rcs_master' into ctu_conveyor

---
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java |  392 +++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 246 insertions(+), 146 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 815c73f..495193d 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
@@ -4,13 +4,11 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.zy.acs.common.constant.RedisConstant;
-import com.zy.acs.common.domain.AgvAction;
-import com.zy.acs.common.domain.AgvActionItem;
-import com.zy.acs.common.domain.AgvProtocol;
-import com.zy.acs.common.domain.BaseResult;
+import com.zy.acs.common.domain.*;
 import com.zy.acs.common.domain.protocol.*;
 import com.zy.acs.common.domain.protocol.action.*;
 import com.zy.acs.common.enums.*;
+import com.zy.acs.common.utils.Base62;
 import com.zy.acs.common.utils.GsonUtils;
 import com.zy.acs.common.utils.RedisSupport;
 import com.zy.acs.common.utils.Utils;
@@ -25,7 +23,7 @@
 import com.zy.acs.manager.core.domain.TaskPosDto;
 import com.zy.acs.manager.core.integrate.conveyor.ConveyorStationService;
 import com.zy.acs.manager.core.service.astart.MapDataDispatcher;
-import com.zy.acs.manager.manager.controller.param.OpenBusSubmitParam;
+import com.zy.acs.manager.core.integrate.dto.OpenBusSubmitParam;
 import com.zy.acs.manager.manager.entity.*;
 import com.zy.acs.manager.manager.enums.*;
 import com.zy.acs.manager.manager.service.*;
@@ -90,7 +88,7 @@
     @Autowired
     private SegmentService segmentService;
     @Autowired
-    private TrafficService trafficService;
+    private LaneService laneService;
     @Autowired
     private AgvModelService agvModelService;
     @Autowired
@@ -106,11 +104,12 @@
     @Transactional
     public Bus generateBusAndTask(OpenBusSubmitParam busSubmitParam, String memo) {
         String errorMsg = busService.checkoutValid(busSubmitParam);
+        Boolean maintainLocSts = configService.getVal("maintainLocSts", Boolean.class);
         if (!Cools.isEmpty(errorMsg)) {
             throw new BusinessException(errorMsg);
         }
-        String batch = busSubmitParam.getBatch();
-        List<TaskDto> taskDtoList = busSubmitParam.getTaskList();
+        String batchNo = busSubmitParam.getBatchNo();
+        List<TaskDto> taskDtoList = busSubmitParam.getTasks();
         if (Cools.isEmpty(taskDtoList)) {
             throw new BusinessException("taskList can't be empty!");
         }
@@ -125,7 +124,7 @@
         Date now = new Date();
         Bus bus = new Bus();
         bus.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
-        bus.setBusNo(batch);
+        bus.setBusNo(batchNo);
         bus.setStartTime(now);
         bus.setBusSts(BusStsType.RECEIVE.val());
         bus.setMemo(memo);
@@ -149,35 +148,39 @@
             Sta destSta = null;
             switch (TaskTypeType.get(task.getTaskTypeEl())) {
                 case LOC_TO_LOC:
-                    oriLoc = locService.getById(task.getOriLoc());
-                    if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
-                        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$() + " failed to update");
-                    }
+                    if (maintainLocSts) {
+                        oriLoc = locService.getById(task.getOriLoc());
+                        if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
+                            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$() + " failed to update");
+                        }
 
-                    destLoc = locService.getById(task.getDestLoc());
-                    if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
-                        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$() + " failed to update");
+                        destLoc = locService.getById(task.getDestLoc());
+                        if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
+                            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$() + " 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$() + " is not in STOCK status");
-                    }
-                    oriLoc.setLocSts(LocStsType.PAKOUT.val());
-                    oriLoc.setUpdateTime(now);
-                    if (!locService.updateById(oriLoc)) {
-                        throw new BusinessException("oriLoc锛�" + task.getOriLoc$() + " failed to update");
+                    if (maintainLocSts) {
+                        oriLoc = locService.getById(task.getOriLoc());
+                        if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
+                            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$() + " failed to update");
+                        }
                     }
 
                     destSta = staService.getById(task.getDestSta());
@@ -191,14 +194,16 @@
                         throw new BusinessException("oriSta锛�" + task.getOriSta$() + " failed to reserve");
                     }
 
-                    destLoc = locService.getById(task.getDestLoc());
-                    if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
-                        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$() + " failed to update");
+                    if (maintainLocSts) {
+                        destLoc = locService.getById(task.getDestLoc());
+                        if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
+                            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$() + " failed to update");
+                        }
                     }
                     break;
                 case STA_TO_STA:
@@ -251,33 +256,28 @@
                         , (task, agvNo, sta) -> {
                             Long agvId = agvService.getAgvId(agvNo);
 
-//                            List<Travel> travelList = travelService.list(new LambdaQueryWrapper<Travel>()
-//                                    .eq(Travel::getAgvId, agvId)
-//                                    .eq(Travel::getState, TravelStateType.RUNNING.toString())
-//                                    .orderByDesc(Travel::getCreateTime));
-//                            if (Cools.isEmpty(travelList)) {
-//                                throw new BusinessException("[Agv: " + agvNo + "]allocate inbound failed to find travel");
+                            Travel travel = travelService.findRunningTravel(agvId);
+                            if (null == travel) {
+                                throw new CoolException("[Agv:" + agvNo + "] allocate inbound failed: no roller waiting travel");
+                            }
+
+                            // curr segment
+                            Segment currSeg = segmentService.getCurrWaitingSeg(travel.getId(), agvId);
+//                            if (null == currSeg) {
+//                                currSeg = segmentService.getCurrRunningSeg(travel.getId(), agvId, null);
 //                            }
-//                            Travel travel = travelList.get(0);
-//
-//                            List<Segment> currSegments = segmentService.list(new LambdaQueryWrapper<Segment>()
-//                                    .eq(Segment::getAgvId, agvId)
-//                                    .eq(Segment::getTravelId, travel.getId())
-//                            );
-                            // load segment
-                            Segment currSeg = segmentService.getRollerWaiting(agvId, sta.getCode(), TaskPosDto.PosType.ORI_STA);
                             if (null == currSeg) {
-                                throw new BusinessException("[Agv:" + agvNo + "] allocate inbound failed: no roller waiting segment");
+                                throw new CoolException("[Agv:" + agvNo + "] allocate inbound failed: no waiting segment");
                             }
 
                             // get backpack lev
                             int backpackLev = 0;
-                            int backpack = agvService.getBackpack(agvId);
+                            int backpackCap = agvService.getBackpack(agvId);
                             List<Integer> usedBackpacks = segmentService.selectUsedBackpacks(currSeg.getTravelId(), agvId);
-                            if (usedBackpacks.size() >= backpack) {
+                            if (usedBackpacks.size() >= backpackCap) {
                                 throw new CoolException("[Agv:" + agvNo + "] allocate inbound segment failed: no idle backpack to use");
                             }
-                            for (int lev = 1; lev <= backpack; lev++) {
+                            for (int lev = 1; lev <= backpackCap; lev++) {
                                 if (!usedBackpacks.contains(lev)) {
                                     backpackLev = lev;
                                     break;
@@ -363,7 +363,6 @@
 
                             // DEST-only sort
                             destPosList.sort((a, b) -> {
-
                                 // 涓昏酱
                                 double aFirst = a.getFirstWeight(sameGroupXy);
                                 double bFirst = b.getFirstWeight(sameGroupXy);
@@ -381,11 +380,10 @@
 
                             // get placeSeg serial
                             int placeSegSerial;
-                            // query placeSeg idx
                             int idx = -1;
                             for (int i = 0; i < destPosList.size(); i++) {
-                                if (Objects.equals(destPosList.get(i).getCodeId(), newDto.getCodeId())
-                                        && Objects.equals(destPosList.get(i).getTaskId(), newDto.getTaskId())) {
+                                if (Objects.equals(destPosList.get(i).getTaskId(), newDto.getTaskId())
+                                 && Objects.equals(destPosList.get(i).getCodeId(), newDto.getCodeId())) {
                                     idx = i;
                                     break;
                                 }
@@ -492,7 +490,7 @@
         try {
             // valid -----------------------------------------------
             Agv agv = agvService.getById(agvId);
-            if (!agvService.judgeEnable(agv.getId(), false)) {
+            if (!agvService.judgeEnable(agv.getId())) {
                 return;
             }
             if (!Cools.isEmpty(taskService.selectInSts(agvId, TaskStsType.ASSIGN, TaskStsType.PROGRESS))) {
@@ -512,9 +510,9 @@
                     return o2.getPriority() - o1.getPriority();
                 }
             });
-            Integer backpack = agvService.getBackpack(agvId);
-            if (taskList.size() > backpack) {
-                taskList = taskList.subList(0, backpack);
+            Integer backpackCap = agvService.getBackpack(agvId);
+            if (taskList.size() > backpackCap) {
+                taskList = taskList.subList(0, backpackCap);
             }
 
             AgvDetail agvDetail = agvDetailService.selectByAgvId(agvId);
@@ -584,7 +582,7 @@
 
                 }
 
-                if (backpackLev > backpack) {
+                if (backpackLev > backpackCap) {
                     throw new BusinessException("瑙f瀽Task澶辫触,AGV鑳岀瘬宸叉弧......");
                 }
 
@@ -788,7 +786,8 @@
             task.setAgvId(agvId);
             task.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
             List<Task> lastTasks = taskService.list(new LambdaQueryWrapper<Task>().orderByDesc(Task::getId));
-            task.setSeqNum(Utils.generateSeqNum(Cools.isEmpty(lastTasks)?null:lastTasks.get(0).getSeqNum()));
+//            task.setSeqNum(Utils.generateSeqNum(Cools.isEmpty(lastTasks)?null:lastTasks.get(0).getSeqNum()));
+            task.setSeqNum(Base62.encode(snowflakeIdWorker.nextId()));
             task.setOriCode(agvDetail.getCode());
             task.setDestCode(endCode.getId());
             // lane
@@ -799,6 +798,7 @@
             task.setPriority(taskType.equals(TaskTypeType.TO_CHARGE)?2:1);
             task.setTaskSts(TaskStsType.ASSIGN.val());
             task.setTaskType(taskType.val());
+            task.setUplinkSts(TaskUplinkStateType.SKIPPED.toString());
             task.setIoTime(now);
             task.setStartTime(now);
             if (!taskService.save(task)) {
@@ -900,6 +900,8 @@
             long actionPrepareSts = ActionStsType.PREPARE.val();
 //            JSONObject storeDirection = configService.getVal("storeDirection", JSONObject.class);
             int angleOffsetVal = configService.getVal("mapAngleOffsetVal", Integer.class);
+//            Double defaultShelfDepth = configService.getVal("defaultShelfDepth", Double.class);
+//            defaultShelfDepth = Optional.ofNullable(defaultShelfDepth).orElse((double) 0);
             String agvNo = agvService.getAgvNo(agvId);
 //            if (!agvService.judgeEnable(agvId)) {
 //                throw new CoolException("AGV[" + agvNo + "]褰撳墠涓嶅彲鐢�...");
@@ -936,7 +938,6 @@
                 if (!lastCode.getData().equals(code.getData())) {
 
                     // 璧拌璺緞鑺傜偣
-//                    List<String> pathList = mapService.checkoutPath(agv.getUuid(), lastCode, code);
                     List<String> pathListPart = pathList.subList(pathList.indexOf(lastCode.getData()), pathList.indexOf(code.getData()) + 1);
 
                     for (int i = 0; i < pathListPart.size(); i++) {
@@ -945,59 +946,118 @@
                         String next = pathListPart.get(i);
 
                         Code nextCode = codeService.getCacheByData(next);
+                        // 杞﹀ご鏈濆墠鐨勪笅涓�涓璧版柟鍚�
                         Double nextDirection = mapService.calculateDirection(lastCode, nextCode, angleOffsetVal);
 
                         // 鍙嶅悜瑙�
                         final double oppLastDir = (lastDirection + 180) % 360;
-
-                        // 濡傛灉涓嬩竴涓柟鍚戞濂芥槸浣滀笟鏂瑰悜鐨勭浉鍙嶆柟鍚戯紝鍒欓噸缃笅涓�涓柟鍚戜负浣滀笟鏂瑰悜锛屾爣璁� reverse = true
+                        // 鏄惁鍊掗��琛岃蛋
                         boolean reverse = false;
-                        if (nextDirection.equals(oppWorkDir)) {
-                            nextDirection = workDirection;
-                            reverse = true;
-                        }
 
-                        // 鍒ゆ柇褰撳墠鑺傜偣鏄惁鍙互鏃嬭浆
-                        if (!lastCode.getCornerBool()) {
-                            // 濡傛灉鏄綔涓氭柟鍚戯紝浣嗘槸灏忚溅鍦ㄥ贩閬撳唴鏂瑰悜閿欒锛屽垯鍋滄
-                            if (reverse && !lastDirection.equals(nextDirection)) {
-                                throw new CoolException(agvNo + "鍙峰皬杞︽柟鍚戦敊璇紝璇锋帹鑷宠浆寮偣鎵嬪姩璋冩暣");
+                        // 宸烽亾閫昏緫
+                        if (!laneBuilder.isInitialized()) {
+                            throw new CoolException("lanes are not initialized");
+                        }
+                        LaneDto lastLaneDto = laneBuilder.search(lastCode.getData());
+                        LaneDto nextLaneDto = laneBuilder.search(nextCode.getData());
+                        // 杩涘叆宸烽亾瑙掑害
+                        Double lastLaneDir = laneService.getLaneDirection(lastLaneDto);
+                        Double nextLaneDir = laneService.getLaneDirection(nextLaneDto);
+
+                        // 宸烽亾寮哄埗杞集锛屼紭鍏堢骇 > workDirection
+                        if (null != nextLaneDir) {
+                            final double oppNextLaneDir = (nextLaneDir + 180) % 360;
+
+                            if (!lastDirection.equals(nextLaneDir)) {
+                                if (!lastCode.getCornerBool()) {
+                                    throw new CoolException(agvNo + "鍙峰皬杞﹁繘鍏ュ贩閬撻渶璋冩暣鏂瑰悜涓� " + nextLaneDir + "掳锛岃鎺ㄨ嚦杞集鐐规墜鍔ㄨ皟鏁�");
+                                }
+                                // turn
+                                actionList.add(new Action(
+                                        null,    // 缂栧彿s
+                                        task.getBusId(),    // 鎬荤嚎
+                                        task.getId(),    // 浠诲姟
+                                        null,    // 鍔ㄤ綔鍙�
+                                        null,    // 浼樺厛绾�
+                                        ActionTypeType.TurnCorner.desc,    // 鍚嶇О
+                                        (double) MapService.calcSpinDirection(lastCode, lastDirection, nextLaneDir).val,     // 灞炴�у��
+                                        lastCode.getData(),    // 鍦伴潰鐮�
+                                        String.valueOf(nextLaneDir),   // 鍔ㄤ綔鍙傛暟
+                                        ActionTypeType.TurnCorner.val(),    // 鍔ㄤ綔绫诲瀷
+                                        actionPrepareSts,    // 鍔ㄤ綔杩涘害
+                                        agvId,    // AGV
+                                        now    // 宸ヤ綔鏃堕棿
+                                ));
+                                lastDirection = nextLaneDir;
                             }
-                            // 濡傛灉涓嶆槸浣滀笟鏂瑰悜锛堝彟涓�缁勭浉鍙嶆柟鍚戯級锛屽垽鏂槸鍚︾浉鍙嶆柟鍚戯紝濡傛灉鍙嶆柟鍚戝垯鍊掗��琛岃蛋
-                            if (nextDirection.equals(oppLastDir)) {
-                                // 鍊掗��鏃讹紝鍥犱负agv鏂瑰悜娌″彉锛屾墍浠ヤ笅涓�涓柟鍚戣繕鏄痑gv鏂瑰悜锛屾晠nextDirection = lastDirection;
-                                nextDirection = lastDirection;
+
+                            if (nextDirection.equals(oppNextLaneDir)) {
                                 reverse = true;
                             }
-                            // 鎬荤粨锛�1.濡傛灉鏄綔涓氱粍锛堝樊180掳锛夋柟鍚戯紝閭d箞agv鏂瑰悜蹇呴』鏄綔涓氭柟鍚戯紝濡傛灉 reverse 鍒欒鏄庡�掗��锛岃繖鏃跺�檔extDirection鑲畾浼氱瓑浜庝綔涓氭柟鍚戯紙鍓嶉潰璧嬪�间簡锛夛紝濡傛灉涓嶇浉鍚岋紝鍒欐姤閿�
-                            //      2.濡傛灉涓嶆槸浣滀笟缁勬柟鍚戯紙鍙︿竴缁勭浉鍙嶆柟鍚戝樊180掳锛夛紝鍥犱负姝ゅ嚱鏁颁笉鑳芥棆杞紝鎵�浠ュ樊180掳鏃跺彧鑳藉�掗��锛屽�掗��鐨勬椂鍊欏洜涓篴gv涓嶄細鏃嬭浆锛屾墍浠extDirection瑕佸彉鎴恆gv鏂瑰悜
+                            nextDirection = nextLaneDir; // 闃叉 绗竴涓姩浣滀竴瀹氭槸 turn 鍑洪棶棰�
+                        } else if (null != lastLaneDir) { // turn 鐜舰鐩磋涓嶅簲璇ュ瓨鍦ㄤ簬lane涓�
+                            final double oppLastLaneDir = (lastLaneDir + 180) % 360;
+
+                            if (!lastDirection.equals(lastLaneDir)) {
+                                if (!lastCode.getCornerBool()) {
+                                    throw new CoolException(agvNo + "鍙峰皬杞︾寮�宸烽亾闇�璋冩暣鏂瑰悜涓� " + nextDirection + "掳锛岃鎺ㄨ嚦杞集鐐规墜鍔ㄨ皟鏁�");
+                                }
+                            }
+
+                            if (nextDirection.equals(oppLastLaneDir)) {
+                                reverse = true;
+                            }
+                            nextDirection = lastLaneDir; // 闃叉 绗竴涓姩浣滀竴瀹氭槸 turn 鍑洪棶棰�
                         } else {
-                            if (!lastDirection.equals(nextDirection)) {
-                                // 濡傛灉涓嬩竴涓柟鍚戜笌agv鏂瑰悜鐩稿弽锛屽垯鍊掗��琛岃蛋锛岄伩鍏嶈繘琛屾鏃犳剰涔夌殑杞集鍔ㄤ綔銆�
-                                // 浣嗘槸瑕佹敞鎰忥細濡傛灉agv鏂瑰悜涓庡伐浣滄柟鍚戞濂界浉鍙嶏紝鍒欓渶瑕佹棆杞嚦宸ヤ綔鏂瑰悜锛屼篃灏辨槸涓轰粈涔堣鍔�!workDirection.equals(oppLastDir)鍒ゆ柇
-                                if (nextDirection.equals(oppLastDir) && !workDirection.equals(oppLastDir)) {
+
+                            // 濡傛灉涓嬩竴涓柟鍚戞濂芥槸浣滀笟鏂瑰悜鐨勭浉鍙嶆柟鍚戯紝鍒欓噸缃笅涓�涓柟鍚戜负浣滀笟鏂瑰悜锛屾爣璁� reverse = true
+                            if (nextDirection.equals(oppWorkDir)) {
+                                nextDirection = workDirection;
+                                reverse = true;
+                            }
+
+                            // 鍒ゆ柇褰撳墠鑺傜偣鏄惁鍙互鏃嬭浆
+                            if (!lastCode.getCornerBool()) {
+                                // 濡傛灉鏄綔涓氭柟鍚戯紝浣嗘槸灏忚溅鍦ㄥ贩閬撳唴鏂瑰悜閿欒锛屽垯鍋滄
+                                if (reverse && !lastDirection.equals(nextDirection)) {
+                                    throw new CoolException(agvNo + "鍙峰皬杞︽柟鍚戦敊璇紝璇锋帹鑷宠浆寮偣鎵嬪姩璋冩暣");
+                                }
+                                // 濡傛灉涓嶆槸浣滀笟鏂瑰悜锛堝彟涓�缁勭浉鍙嶆柟鍚戯級锛屽垽鏂槸鍚︾浉鍙嶆柟鍚戯紝濡傛灉鍙嶆柟鍚戝垯鍊掗��琛岃蛋
+                                if (nextDirection.equals(oppLastDir)) {
                                     // 鍊掗��鏃讹紝鍥犱负agv鏂瑰悜娌″彉锛屾墍浠ヤ笅涓�涓柟鍚戣繕鏄痑gv鏂瑰悜锛屾晠nextDirection = lastDirection;
                                     nextDirection = lastDirection;
                                     reverse = true;
-                                } else {
-                                    // turn
-                                    actionList.add(new Action(
-                                            null,    // 缂栧彿s
-                                            task.getBusId(),    // 鎬荤嚎
-                                            task.getId(),    // 浠诲姟
-                                            null,    // 鍔ㄤ綔鍙�
-                                            null,    // 浼樺厛绾�
-                                            ActionTypeType.TurnCorner.desc,    // 鍚嶇О
-                                            (double) mapService.spinDirection(lastCode).val,     // 灞炴�у��
-                                            lastCode.getData(),    // 鍦伴潰鐮�
-                                            String.valueOf(nextDirection),   // 鍔ㄤ綔鍙傛暟
-                                            ActionTypeType.TurnCorner.val(),    // 鍔ㄤ綔绫诲瀷
-                                            actionPrepareSts,    // 鍔ㄤ綔杩涘害
-                                            agvId,    // AGV
-                                            now    // 宸ヤ綔鏃堕棿
-                                    ));
+                                }
+                                // 鎬荤粨锛�1.濡傛灉鏄綔涓氱粍锛堝樊180掳锛夋柟鍚戯紝閭d箞agv鏂瑰悜蹇呴』鏄綔涓氭柟鍚戯紝濡傛灉 reverse 鍒欒鏄庡�掗��锛岃繖鏃跺�檔extDirection鑲畾浼氱瓑浜庝綔涓氭柟鍚戯紙鍓嶉潰璧嬪�间簡锛夛紝濡傛灉涓嶇浉鍚岋紝鍒欐姤閿�
+                                //      2.濡傛灉涓嶆槸浣滀笟缁勬柟鍚戯紙鍙︿竴缁勭浉鍙嶆柟鍚戝樊180掳锛夛紝鍥犱负姝ゅ嚱鏁颁笉鑳芥棆杞紝鎵�浠ュ樊180掳鏃跺彧鑳藉�掗��锛屽�掗��鐨勬椂鍊欏洜涓篴gv涓嶄細鏃嬭浆锛屾墍浠extDirection瑕佸彉鎴恆gv鏂瑰悜
+                            } else {
+                                if (!lastDirection.equals(nextDirection)) {
+                                    // 濡傛灉涓嬩竴涓柟鍚戜笌agv鏂瑰悜鐩稿弽锛屽垯鍊掗��琛岃蛋锛岄伩鍏嶈繘琛屾鏃犳剰涔夌殑杞集鍔ㄤ綔銆�
+                                    // 浣嗘槸瑕佹敞鎰忥細濡傛灉agv鏂瑰悜涓庡伐浣滄柟鍚戞濂界浉鍙嶏紝鍒欓渶瑕佹棆杞嚦宸ヤ綔鏂瑰悜锛屼篃灏辨槸涓轰粈涔堣鍔�!workDirection.equals(oppLastDir)鍒ゆ柇
+                                    if (nextDirection.equals(oppLastDir) && !workDirection.equals(oppLastDir)) {
+                                        // 鍊掗��鏃讹紝鍥犱负agv鏂瑰悜娌″彉锛屾墍浠ヤ笅涓�涓柟鍚戣繕鏄痑gv鏂瑰悜锛屾晠nextDirection = lastDirection;
+                                        nextDirection = lastDirection;
+                                        reverse = true;
+                                    } else {
+                                        // turn
+                                        actionList.add(new Action(
+                                                null,    // 缂栧彿s
+                                                task.getBusId(),    // 鎬荤嚎
+                                                task.getId(),    // 浠诲姟
+                                                null,    // 鍔ㄤ綔鍙�
+                                                null,    // 浼樺厛绾�
+                                                ActionTypeType.TurnCorner.desc,    // 鍚嶇О
+                                                (double) MapService.calcSpinDirection(lastCode, lastDirection, nextDirection).val,     // 灞炴�у��
+                                                lastCode.getData(),    // 鍦伴潰鐮�
+                                                String.valueOf(nextDirection),   // 鍔ㄤ綔鍙傛暟
+                                                ActionTypeType.TurnCorner.val(),    // 鍔ㄤ綔绫诲瀷
+                                                actionPrepareSts,    // 鍔ㄤ綔杩涘害
+                                                agvId,    // AGV
+                                                now    // 宸ヤ綔鏃堕棿
+                                        ));
 
-                                    lastDirection = nextDirection;
+                                        lastDirection = nextDirection;
+                                    }
                                 }
                             }
                         }
@@ -1012,7 +1072,7 @@
                                     null,    // 鍔ㄤ綔鍙�
                                     null,    // 浼樺厛绾�
                                     ActionTypeType.TurnCorner.desc,    // 鍚嶇О
-                                    (double) mapService.spinDirection(lastCode).val,    // 灞炴�у��
+                                    (double) MapService.calcSpinDirection(lastCode, lastDirection, nextDirection).val,    // 灞炴�у��
                                     lastCode.getData(),    // 鍦伴潰鐮�
                                     String.valueOf(nextDirection),   // 鍔ㄤ綔鍙傛暟
                                     ActionTypeType.TurnCorner.val(),    // 鍔ㄤ綔绫诲瀷
@@ -1052,6 +1112,25 @@
                 // 鍒濆鏂瑰悜鍊艰ˉ涓�
                 if (first) {
                     if (Cools.isEmpty(actionList) || !actionList.get(0).getActionType().equals(ActionTypeType.TurnCorner.val())) {
+                        Double firstTurnDir = workDirection;
+
+                        // 宸烽亾閫昏緫
+                        if (!laneBuilder.isInitialized()) {
+                            throw new CoolException("lanes are not initialized");
+                        }
+                        LaneDto lastLaneDto = laneBuilder.search(lastCode.getData());
+                        // 杩涘叆宸烽亾瑙掑害
+                        Double lastLaneDir = laneService.getLaneDirection(lastLaneDto);
+                        if (lastLaneDir != null) {
+                            firstTurnDir = lastLaneDir;
+                        }
+
+                        if (!lastDirection.equals(firstTurnDir)) {
+                            if (!lastCode.getCornerBool()) {
+                                throw new CoolException(agvNo + "鍙峰皬杞︽柟鍚戦敊璇紝璇锋帹鑷宠浆寮偣鎵嬪姩璋冩暣");
+                            }
+                        }
+
                         // turn
                         actionList.add(new Action(
                                 null,    // 缂栧彿
@@ -1060,23 +1139,23 @@
                                 null,    // 鍔ㄤ綔鍙�
                                 null,    // 浼樺厛绾�
                                 ActionTypeType.TurnCorner.desc,    // 鍚嶇О
-                                (double) mapService.spinDirection(lastCode).val,    // 灞炴�у��
+                                (double) MapService.calcSpinDirection(lastCode, lastDirection, firstTurnDir).val,    // 灞炴�у��
                                 lastCode.getData(),    // 鍦伴潰鐮�
-                                String.valueOf(workDirection),   // 鍔ㄤ綔鍙傛暟
+                                String.valueOf(firstTurnDir),   // 鍔ㄤ綔鍙傛暟
                                 ActionTypeType.TurnCorner.val(),    // 鍔ㄤ綔绫诲瀷
                                 actionPrepareSts,    // 鍔ㄤ綔杩涘害
                                 agvId,    // AGV
                                 now    // 宸ヤ綔鏃堕棿
                         ));
 
-                        lastDirection = workDirection;
+                        lastDirection = firstTurnDir;
 
                     }
                     first = false;
                 }
 
                 // 浣滀笟鐐瑰姩浣�
-                AgvDirectionType agvDirectionType;
+                ActuatorDirectionType actuatorDirectionType;
                 Double staWorkDirection;
                 AgvBackpackType backpackType = AgvBackpackType.query(segment.getBackpack());
                 switch (Objects.requireNonNull(TaskPosDto.queryPosType(segment.getPosType()))) {
@@ -1089,7 +1168,8 @@
                         // 璐ф灦鍙栬揣
                         Loc oriLoc = locService.getById(task.getOriLoc());
                         // 璁$畻宸﹀彸鏂瑰悜
-                        agvDirectionType = mapService.calculateAgvWorkDirectionByShelf(oriLoc, lastCode);
+                        actuatorDirectionType = ActuatorDirectionType.fromVal(oriLoc.getCompDirect());
+//                        actuatorDirectionType = mapService.calculateAgvWorkDirectionByShelf(oriLoc, lastCode);
                         actionList.add(new Action(
                                 null,    // 缂栧彿
                                 task.getBusId(),    // 鎬荤嚎
@@ -1097,9 +1177,9 @@
                                 null,    // 鍔ㄤ綔鍙�
                                 null,    // 浼樺厛绾�
                                 ActionTypeType.ReadyTakeFromShelvesLoc.desc,    // 鍚嶇О
-                                (double) agvDirectionType.val,    // 灞炴�у��
+                                (double) actuatorDirectionType.val,    // 灞炴�у��
                                 lastCode.getData(),    // 鍦伴潰鐮�
-                                String.valueOf(oriLoc.getOffset()),   // 鍔ㄤ綔鍙傛暟
+                                JSON.toJSONString(new HeightDepthDto(oriLoc.getOffset())),   // 鍔ㄤ綔鍙傛暟
                                 ActionTypeType.ReadyTakeFromShelvesLoc.val(),    // 鍔ㄤ綔绫诲瀷
                                 actionPrepareSts,    // 鍔ㄤ綔杩涘害
                                 agvId,    // AGV
@@ -1152,7 +1232,8 @@
                         // 璐ф灦鏀捐揣
                         Loc destLoc = locService.getById(task.getDestLoc());
                         // 璁$畻宸﹀彸鏂瑰悜
-                        agvDirectionType = mapService.calculateAgvWorkDirectionByShelf(destLoc, lastCode);
+                        actuatorDirectionType = ActuatorDirectionType.fromVal(destLoc.getCompDirect());
+//                        actuatorDirectionType = mapService.calculateAgvWorkDirectionByShelf(destLoc, lastCode);
                         actionList.add(new Action(
                                 null,    // 缂栧彿
                                 task.getBusId(),    // 鎬荤嚎
@@ -1160,9 +1241,9 @@
                                 null,    // 鍔ㄤ綔鍙�
                                  null,    // 浼樺厛绾�
                                 ActionTypeType.ReadyReleaseToShelvesLoc.desc,    // 鍚嶇О
-                                (double) agvDirectionType.val,    // 灞炴�у��
+                                (double) actuatorDirectionType.val,    // 灞炴�у��
                                 lastCode.getData(),    // 鍦伴潰鐮�
-                                String.valueOf(destLoc.getOffset()),   // 鍔ㄤ綔鍙傛暟
+                                JSON.toJSONString(new HeightDepthDto(destLoc.getOffset())),   // 鍔ㄤ綔鍙傛暟
                                 ActionTypeType.ReadyReleaseToShelvesLoc.val(),    // 鍔ㄤ綔绫诲瀷
                                 actionPrepareSts,    // 鍔ㄤ綔杩涘害
                                 agvId,    // AGV
@@ -1186,7 +1267,7 @@
                                     null,    // 鍔ㄤ綔鍙�
                                     null,    // 浼樺厛绾�
                                     ActionTypeType.TurnCorner.desc,    // 鍚嶇О
-                                    (double) mapService.spinDirection(lastCode).val,   // 灞炴�у��
+                                    (double) MapService.calcSpinDirection(lastCode, lastDirection, oriStaWorkDirection).val,   // 灞炴�у��
                                     lastCode.getData(),    // 鍦伴潰鐮�
                                     String.valueOf(oriStaWorkDirection),   // 鍔ㄤ綔鍙傛暟
                                     ActionTypeType.TurnCorner.val(),    // 鍔ㄤ綔绫诲瀷
@@ -1197,7 +1278,8 @@
                             lastDirection = oriStaWorkDirection;
                         }
                         // 璁$畻璐у弶宸ヤ綔鏂瑰悜
-                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(oriStaWorkDirection, lastDirection);
+                        actuatorDirectionType = ActuatorDirectionType.fromVal(oriSta.getActDir());
+//                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(oriStaWorkDirection, lastDirection);
                         actionList.add(new Action(
                                 null,    // 缂栧彿
                                 task.getBusId(),    // 鎬荤嚎
@@ -1205,9 +1287,9 @@
                                 null,    // 鍔ㄤ綔鍙�
                                 null,    // 浼樺厛绾�
                                 ActionTypeType.ReadyTakeFromConveyorSta.desc,    // 鍚嶇О
-                                staWorkDirection,    // 灞炴�у��
+                                (double) actuatorDirectionType.val,    // 灞炴�у��
                                 lastCode.getData(),    // 鍦伴潰鐮�
-                                String.valueOf(oriSta.getOffset()),   // 鍔ㄤ綔鍙傛暟
+                                JSON.toJSONString(new HeightDepthDto(oriSta.getHeight(), Optional.ofNullable(oriSta.getDepth()).orElse((double) 0))),   // 鍔ㄤ綔鍙傛暟
                                 ActionTypeType.ReadyTakeFromConveyorSta.val(),    // 鍔ㄤ綔绫诲瀷
                                 actionPrepareSts,    // 鍔ㄤ綔杩涘害
                                 agvId,    // AGV
@@ -1250,7 +1332,7 @@
                                     null,    // 鍔ㄤ綔鍙�
                                     null,    // 浼樺厛绾�
                                     ActionTypeType.TurnCorner.desc,    // 鍚嶇О
-                                    (double) mapService.spinDirection(lastCode).val,    // 灞炴�у��
+                                    (double) MapService.calcSpinDirection(lastCode, lastDirection, destStaWorkDirection).val,    // 灞炴�у��
                                     lastCode.getData(),    // 鍦伴潰鐮�
                                     String.valueOf(destStaWorkDirection),   // 鍔ㄤ綔鍙傛暟
                                     ActionTypeType.TurnCorner.val(),    // 鍔ㄤ綔绫诲瀷
@@ -1280,7 +1362,8 @@
                             ));
                         }
                         // 璁$畻璐у弶宸ヤ綔鏂瑰悜
-                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(destStaWorkDirection, lastDirection);
+//                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(destStaWorkDirection, lastDirection);
+                        actuatorDirectionType = ActuatorDirectionType.fromVal(destSta.getActDir());
                         actionList.add(new Action(
                                 null,    // 缂栧彿
                                 task.getBusId(),    // 鎬荤嚎
@@ -1288,9 +1371,9 @@
                                 null,    // 鍔ㄤ綔鍙�
                                 null,    // 浼樺厛绾�
                                 ActionTypeType.ReadyReleaseToConveyorSta.desc,    // 鍚嶇О
-                                staWorkDirection,    // 灞炴�у��
+                                (double) actuatorDirectionType.val,    // 灞炴�у��
                                 lastCode.getData(),    // 鍦伴潰鐮�
-                                String.valueOf(destSta.getOffset()),   // 鍔ㄤ綔鍙傛暟
+                                JSON.toJSONString(new HeightDepthDto(destSta.getHeight(), Optional.ofNullable(destSta.getDepth()).orElse((double) 0))),   // 鍔ㄤ綔鍙傛暟
                                 ActionTypeType.ReadyReleaseToConveyorSta.val(),    // 鍔ㄤ綔绫诲瀷
                                 actionPrepareSts,    // 鍔ㄤ綔杩涘害
                                 agvId,    // AGV
@@ -1309,7 +1392,7 @@
                                     null,    // 鍔ㄤ綔鍙�
                                     null,    // 浼樺厛绾�
                                     ActionTypeType.TurnCorner.desc,    // 鍚嶇О
-                                    (double) mapService.spinDirection(lastCode).val,    // 灞炴�у��
+                                    (double) MapService.calcSpinDirection(lastCode, lastDirection, chargeDirection).val,    // 灞炴�у��
                                     lastCode.getData(),    // 鍦伴潰鐮�
                                     String.valueOf(chargeDirection),   // 鍔ㄤ綔鍙傛暟
                                     ActionTypeType.TurnCorner.val(),    // 鍔ㄤ綔绫诲瀷
@@ -1563,14 +1646,22 @@
                         agvAction.add(new AgvActionItem<>(ReadyTakeFromShelvesLoc.class)
                                 .setVal(action.getVal().intValue())
                                 .setQrCode(action.getCode())
-                                .bodySync(body -> body.setHeight((short) Double.parseDouble(action.getParams())))
+                                .bodySync((body) -> {
+                                    HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
+                                    body.setHeight(heightDepthDto.getHeight());
+                                    body.setDepth(heightDepthDto.getDepth());
+                                })
                         );
                         break;
                     case ReadyTakeFromConveyorSta:
                         agvAction.add(new AgvActionItem<>(ReadyTakeFromConveyorSta.class)
                                 .setVal(action.getVal().intValue())
                                 .setQrCode(action.getCode())
-                                .bodySync(body -> body.setHeight((short) Double.parseDouble(action.getParams())))
+                                .bodySync((body) -> {
+                                    HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
+                                    body.setHeight(heightDepthDto.getHeight());
+                                    body.setDepth(heightDepthDto.getDepth());
+                                })
                         );
                         break;
                     case ReadyTakeFromAgvSite:
@@ -1584,21 +1675,22 @@
                         agvAction.add(new AgvActionItem<>(ReadyReleaseToShelvesLoc.class)
                                 .setVal(action.getVal().intValue())
                                 .setQrCode(action.getCode())
-                                .bodySync(body -> body.setHeight((short) Double.parseDouble(action.getParams())))
-                        );
-                        break;
-                    case LoadPlatformLift:
-                        agvAction.add(new AgvActionItem<>(LoadPlatformLift.class)
-                                .setVal(action.getVal().intValue())
-                                .setQrCode(action.getCode())
-                                .bodySync(body -> body.setHeight((short) Double.parseDouble(action.getParams())))
+                                .bodySync((body) -> {
+                                    HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
+                                    body.setHeight(heightDepthDto.getHeight());
+                                    body.setDepth(heightDepthDto.getDepth());
+                                })
                         );
                         break;
                     case ReadyReleaseToConveyorSta:
                         agvAction.add(new AgvActionItem<>(ReadyReleaseToConveyorSta.class)
                                 .setVal(action.getVal().intValue())
                                 .setQrCode(action.getCode())
-                                .bodySync(body -> body.setHeight((short) Double.parseDouble(action.getParams())))
+                                .bodySync((body) -> {
+                                    HeightDepthDto heightDepthDto = JSON.parseObject(action.getParams(), HeightDepthDto.class);
+                                    body.setHeight(heightDepthDto.getHeight());
+                                    body.setDepth(heightDepthDto.getDepth());
+                                })
                         );
                         break;
                     case ReadyReleaseToAgvSite:
@@ -1606,6 +1698,13 @@
                                 .setVal(action.getVal().intValue())
                                 .setQrCode(action.getCode())
                                 .bodySync(body -> body.setDepth((short) Double.parseDouble(action.getParams())))
+                        );
+                        break;
+                    case LoadPlatformLift:
+                        agvAction.add(new AgvActionItem<>(LoadPlatformLift.class)
+                                .setVal(action.getVal().intValue())
+                                .setQrCode(action.getCode())
+                                .bodySync(body -> body.setHeight((short) Double.parseDouble(action.getParams())))
                         );
                         break;
                     case FinishPath:
@@ -1758,7 +1857,7 @@
                 Code code = codeService.getCacheByData(agv_06_up.getQrCode());
 
                 // query current segment
-                Segment currSeg = segmentService.getCurrRunningSeg(agv.getId(), code.getId());
+                Segment currSeg = segmentService.getCurrRunningSeg(null, agv.getId(), code.getId());
                 if (null == currSeg) {
                     log.error("failed to find curr segment [{}]", agv.getUuid());
                 } else {
@@ -1782,7 +1881,7 @@
                                 // load from sta
                                 sta = staService.getById(currTask.getOriSta());
                                 // reserve to be waiting
-                                if (!staReserveService.waitingStaReserve(sta, currTask, 1, StaReserveType.OUT)) {
+                                if (!staReserveService.waitingStaReserve(sta, currTask, currSeg, 1, StaReserveType.OUT)) {
                                     break;
                                 }
                                 // convey plc valid
@@ -1791,13 +1890,14 @@
                                     staReserveService.rollbackWaitingToReserved(sta, currTask, StaReserveType.OUT);
                                     break;
                                 }
+                                log.info("AGV [{}] load permitted at conveyor station [{}]", protocol.getAgvNo(), sta.getStaNo());
                                 success = true;
                                 break;
                             case DEST_STA:
                                 // place to sta
                                 sta = staService.getById(currTask.getDestSta());
                                 // reserve to be waiting
-                                if (!staReserveService.waitingStaReserve(sta, currTask, 1, StaReserveType.IN)) {
+                                if (!staReserveService.waitingStaReserve(sta, currTask, currSeg, 1, StaReserveType.IN)) {
                                     break;
                                 }
                                 // convey plc valid
@@ -1806,10 +1906,11 @@
                                     staReserveService.rollbackWaitingToReserved(sta, currTask, StaReserveType.IN);
                                     break;
                                 }
+                                log.info("AGV [{}] unload permitted at conveyor station [{}]", protocol.getAgvNo(), sta.getStaNo());
                                 success = true;
                                 break;
                             default:
-                                log.error("agv[{}] has wrong posType [{}], segment [{}]", protocol.getAgvNo(), posType.toString(), currSeg.getId());
+                                log.error("AGV [{}] has wrong posType [{}], segment [{}]", protocol.getAgvNo(), posType.toString(), currSeg.getId());
                                 break;
                         }
                     }
@@ -1823,7 +1924,6 @@
             agv_06_down.setSerialNo(agv_06_up.getSerialNo());
             agv_06_down.setActionCode(agv_06_up.getActionCode());
             agv_06_down.setResult(success ? 1 : 0);
-
             redis.push(RedisConstant.AGV_PATH_DOWN_FLAG, AgvProtocol.build(protocol.getAgvNo()).setMessageBody(agv_06_down));
         }
 

--
Gitblit v1.9.1