From c65a357fc8b907af755e1ef6a2c201e31eb71e94 Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期六, 07 二月 2026 13:50:38 +0800
Subject: [PATCH] #

---
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java |  183 ++++++++++++++++++++++++++++++++++++---------
 1 files changed, 146 insertions(+), 37 deletions(-)

diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java
index 9c975e1..d6ac66c 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java
@@ -1,8 +1,12 @@
 package com.zy.acs.manager.core.service;
 
-import com.zy.acs.common.enums.AgvDirectionType;
+import com.alibaba.fastjson.JSON;
+import com.zy.acs.common.enums.ActuatorDirectionType;
 import com.zy.acs.framework.common.Cools;
+import com.zy.acs.framework.exception.CoolException;
 import com.zy.acs.manager.core.constant.MapDataConstant;
+import com.zy.acs.manager.core.domain.DirectionDto;
+import com.zy.acs.manager.core.domain.LaneDto;
 import com.zy.acs.manager.core.domain.SortCodeDto;
 import com.zy.acs.manager.core.domain.UnlockPathTask;
 import com.zy.acs.manager.core.service.astart.*;
@@ -14,9 +18,8 @@
 import com.zy.acs.manager.manager.entity.Segment;
 import com.zy.acs.manager.manager.entity.Sta;
 import com.zy.acs.manager.manager.enums.CodeSpinType;
-import com.zy.acs.manager.manager.service.ActionService;
 import com.zy.acs.manager.manager.service.CodeService;
-import com.zy.acs.manager.system.service.ConfigService;
+import com.zy.acs.manager.manager.service.LaneService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -36,6 +39,7 @@
 @Component("mapService")
 public class MapService {
 
+    private static final double EPS = 1e-7;
     private final static int[][] DIRECTIONS = {{0,1},{0,-1},{-1,0},{1,0}};
 
     @Value("${floyd.enable}")
@@ -49,9 +53,9 @@
     @Autowired
     private AStarNavigateService aStarNavigateService;
     @Autowired
-    private ConfigService configService;
+    private LaneService laneService;
     @Autowired
-    private ActionService actionService;
+    private LaneBuilder laneBuilder;
     @Autowired
     private LinkedBlockingQueue<UnlockPathTask> unlockTaskQueue;
 
@@ -155,27 +159,39 @@
         return angle;
     }
 
-    // 鍧愭爣璐ф灦闃堝�� todo:luxiaotao
-    public AgvDirectionType calculateAgvWorkDirectionByShelf(Loc loc, Code code) {
+    // 鍧愭爣璐ф灦闃堝��
+    public ActuatorDirectionType calculateAgvWorkDirectionByShelf(Loc loc, Code code) {
         Integer compDirect = loc.getCompDirect();
-        AgvDirectionType agvDirectionType = null;
-        if (compDirect == 0) {
-            agvDirectionType = AgvDirectionType.RIGHT;
-        }
-        if (compDirect == 1) {
-            agvDirectionType = AgvDirectionType.LEFT;
-        }
-        return agvDirectionType;
+        return ActuatorDirectionType.fromVal(compDirect);
     }
 
-    public Double getStaAngle(Sta sta, Double workDirection) {
-        if (null == sta) {
-            return null;
+    public Double getStaAngle(Sta sta) {
+        if (null == sta.getCode()) {
+            throw new CoolException(sta.getStaNo() + "鍙锋帴椹崇珯鏈缃湴鐮侊紒");
         }
-        if (Cools.isEmpty(sta.getAngle())) {
-            return workDirection;
+        Code code = codeService.getCacheById(sta.getCode());
+        if (code.getCornerBool()) {
+            if (!Cools.isEmpty(sta.getAngle())) {
+                return Double.parseDouble(sta.getAngle());
+            } else {
+                throw new CoolException(sta.getStaNo() + "鍙锋帴椹崇珯鏈缃溅浣撲綔涓氳搴︼紒");
+            }
+        } else {
+            LaneDto laneDto = laneBuilder.search(code.getData());
+            Double laneDir = laneService.getLaneDirection(laneDto);
+
+            if (!Cools.isEmpty(laneDir)) {
+                if (!Cools.isEmpty(sta.getAngle()) && !laneDir.equals(Double.parseDouble(sta.getAngle()))) {
+                    throw new CoolException(sta.getStaNo() + "鍙锋帴椹崇珯杞︿綋浣滀笟瑙掑害涓庡贩閬撹繘鍏ヨ搴︿笉涓�鑷达紒");
+                }
+                return laneDir;
+            } else {
+                if (!Cools.isEmpty(sta.getAngle())) {
+                    return Double.parseDouble(sta.getAngle());
+                }
+                throw new CoolException("鏈缃�" + sta.getStaNo() + "鍙锋帴椹崇珯鎵�澶勫贩閬撶殑杩涘叆瑙掑害");
+            }
         }
-        return Double.parseDouble(sta.getAngle());
     }
 
     public Double calculateAgvWorkDirectionByStation(Double staWorkDirection, Double lastDirection) {
@@ -186,22 +202,6 @@
         double deltaX = x2 - x1;
         double deltaY = y2 - y1;
         return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
-    }
-
-    public DirectionType calcDirectionType(int[] originIdx, int[] oppositeIdx) {
-        if (oppositeIdx[0] < originIdx[0] && oppositeIdx[1] == originIdx[1]) {
-            return DirectionType.TOP;
-        }
-        if (oppositeIdx[0] > originIdx[0] && oppositeIdx[1] == originIdx[1]) {
-            return DirectionType.BOTTOM;
-        }
-        if (oppositeIdx[0] == originIdx[0] && oppositeIdx[1] > originIdx[1]) {
-            return DirectionType.RIGHT;
-        }
-        if (oppositeIdx[0] == originIdx[0] && oppositeIdx[1] < originIdx[1]) {
-            return DirectionType.LEFT;
-        }
-        return DirectionType.NONE;
     }
 
     public void lockPath(Integer lev, List<String> pathList, String agvNo) {
@@ -438,6 +438,115 @@
         return CodeSpinType.of(code.getSpin());
     }
 
+    public static void main(String[] args) {
+        CodeSpinType codeSpinType = calcSpinDirection(null, 260.0, 10.0);
+        List<DirectionDto> directionDtoList = DirectionDto.initCodeDirections();
+        System.out.println(JSON.toJSONString(directionDtoList));
+        System.out.println(codeSpinType.toString());
+    }
+
+    public static CodeSpinType calcSpinDirection(Code code, Double currDir, Double nextDir) {
+        if (Cools.isEmpty(code, currDir, nextDir)) {
+            return CodeSpinType.NA;
+        }
+        List<Double> disableAngleList = new ArrayList<>();
+        List<DirectionDto> directionDtoList;
+        if (!Cools.isEmpty(code.getDirRule())) {
+            directionDtoList = JSON.parseArray(code.getDirRule(), DirectionDto.class);
+        } else {
+            directionDtoList = DirectionDto.initCodeDirections();
+        }
+        for (DirectionDto dto : directionDtoList) {
+            if (null != dto.getEnabled() && !dto.getEnabled()) {
+                disableAngleList.add(dto.getAngle());
+            }
+        }
+
+        if (Cools.isEmpty(disableAngleList)) {
+            return CodeSpinType.NA;
+        }
+
+        double curr = norm360(currDir);
+        double next = norm360(nextDir);
+
+        // 濡傛灉鍑犱箮鐩哥瓑锛岃涓轰笉闇�瑕佹棆杞�
+        if (almostEqual(curr, next)) {
+            return CodeSpinType.NA;
+        }
+
+        double cwDelta = cwDelta(curr, next);
+        double ccwDelta = 360.0 - cwDelta;
+
+        boolean cwBlocked = false;
+        boolean ccwBlocked = false;
+
+        for (Double disableAngle : disableAngleList) {
+            if (disableAngle == null) continue;
+            double disable = norm360(disableAngle);
+
+            if (isOnArcCW(curr, next, disable)) {
+                cwBlocked = true;
+            }
+            if (isOnArcCCW(curr, next, disable)) {
+                ccwBlocked = true;
+            }
+        }
+
+        if (cwBlocked && !ccwBlocked) {
+            return CodeSpinType.CCW;
+        }
+        if (!cwBlocked && ccwBlocked) {
+            return CodeSpinType.CW;
+        }
+
+        return CodeSpinType.NA;
+    }
+
+    private static double norm360(double a) {
+        double x = a % 360.0;
+        if (x < 0) x += 360.0;
+        // 360 褰掍竴鍖栦负 0
+        if (almostEqual(x, 360.0)) return 0.0;
+        return x;
+    }
+
+    private static boolean almostEqual(double a, double b) {
+        return Math.abs(a - b) <= EPS;
+    }
+
+    /**
+     * 椤烘椂閽堣窛绂伙細浠� start 鍒� end锛屾部 CW 鏂瑰悜璧板灏戝害锛岃寖鍥� (0, 360]锛岃繖閲屼笉浼氳繑鍥� 0锛堥櫎闈炰綘 curr==next 宸叉彁鍓嶅鐞嗭級
+     */
+    private static double cwDelta(double start, double end) {
+        double d = end - start;
+        if (d < 0) d += 360.0;
+        if (almostEqual(d, 0.0)) return 0.0;
+        return d;
+    }
+
+    /**
+     * 鍒ゆ柇 angle 鏄惁钀藉湪浠� start -> end 鐨勯『鏃堕拡寮ф涓婏紙涓嶅惈绔偣锛夈��
+     * 鍗筹細娌� CW 浠� start 璧� cwDelta(start,end) 鐨勮矾寰勪笂鏄惁鈥滅粡杩団�漚ngle銆�
+     */
+    private static boolean isOnArcCW(double start, double end, double angle) {
+        double total = cwDelta(start, end);
+        // 寮ч暱涓� 0 琛ㄧず鏃犳棆杞紙宸叉彁鍓嶅鐞嗭級锛岃繖閲岀洿鎺� false
+        if (almostEqual(total, 0.0)) return false;
+
+        double a = cwDelta(start, angle);
+        // 涓嶅寘鍚鐐癸細a 鍦� (0, total) 涔嬮棿鎵嶇畻缁忚繃
+        return a > EPS && a < total - EPS;
+    }
+
+    /**
+     * 鍒ゆ柇 angle 鏄惁钀藉湪浠� start -> end 鐨勯�嗘椂閽堝姬娈典笂锛堜笉鍚鐐癸級銆�
+     * 閫嗘椂閽堢瓑浠蜂簬锛氶『鏃堕拡浠� end -> start 鐨勫姬娈点��
+     */
+    private static boolean isOnArcCCW(double start, double end, double angle) {
+        // 閫嗘椂閽� start->end == 椤烘椂閽� end->start
+        return isOnArcCW(end, start, angle);
+    }
+
     /**
      * That vehicle is walking if the dynamic node count > 1
      */

--
Gitblit v1.9.1