From ebd2f4397a92c6a5096de1b86d59154363344720 Mon Sep 17 00:00:00 2001 From: vincentlu <t1341870251@gmail.com> Date: 星期二, 13 五月 2025 08:48:15 +0800 Subject: [PATCH] # --- zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/astart/AStarNavigateService.java | 192 +++++++++++++++++++++++++++++------------------ 1 files changed, 117 insertions(+), 75 deletions(-) diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/astart/AStarNavigateService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/astart/AStarNavigateService.java index 9e9e982..a7ea660 100644 --- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/astart/AStarNavigateService.java +++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/astart/AStarNavigateService.java @@ -1,12 +1,10 @@ package com.zy.acs.manager.core.service.astart; -import com.zy.acs.common.constant.RedisConstant; -import com.zy.acs.common.utils.GsonUtils; import com.zy.acs.common.utils.RedisSupport; import com.zy.acs.framework.common.Cools; import com.zy.acs.manager.common.utils.MapDataUtils; -import com.zy.acs.manager.core.domain.Lane; import com.zy.acs.manager.core.service.LaneService; +import com.zy.acs.manager.core.service.astart.domain.AStarNavigateNode; import com.zy.acs.manager.core.service.astart.domain.DynamicNode; import com.zy.acs.manager.core.utils.RouteGenerator; import com.zy.acs.manager.manager.entity.Segment; @@ -17,7 +15,6 @@ import org.springframework.stereotype.Service; import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; /** * Created by vincent on 6/12/2024 @@ -32,6 +29,9 @@ public static final int WEIGHT_CALC_FACTOR = 1; + // right left up down + private final static int[][] DIRECTIONS = {{0,1},{0,-1},{-1,0},{1,0}}; + @Autowired private MapDataDispatcher mapDataDispatcher; @Autowired @@ -41,15 +41,22 @@ @Autowired private ConfigService configService; - public synchronized NavigateNode execute(String agvNo, NavigateNode start, NavigateNode end + public synchronized AStarNavigateNode execute(String agvNo, AStarNavigateNode start, AStarNavigateNode end , Boolean lock, List<String> blackList, Segment segment) { if (start.getX() == end.getX() && start.getY() == end.getY()) { return end; } Integer maxAgvCountInLane = configService.getVal("maxAgvCountInLane", Integer.class); - PriorityQueue<NavigateNode> openQueue = new PriorityQueue<>(); - Set<NavigateNode> existNodes = new HashSet<>(); + PriorityQueue<AStarNavigateNode> openQueue = new PriorityQueue<>(); + Set<AStarNavigateNode> existNodes = new HashSet<>(); + Map<String, Integer> bestGMap = new HashMap<>(); + + start.setG(0); + start.setH(calcNodeCost(start, end)); + start.setF(start.getG() + start.getH()); + String startKey = start.getX() + "_" + start.getY(); + bestGMap.put(startKey, start.getG()); openQueue.add(start); existNodes.add(start); @@ -58,12 +65,24 @@ String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(null); DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(null); String[][] waveMatrix = mapDataDispatcher.getWaveMatrix(null); + + long getNeighborNodesTime = 0; + int getNeighborNodesCount = 0; + while (!openQueue.isEmpty()) { // 鍙栦紭鍏堥槦鍒楅《閮ㄥ厓绱犲苟涓旀妸杩欎釜鍏冪礌浠嶰pen琛ㄤ腑鍒犻櫎锛屽彇F鍊兼渶灏忕殑鑺傜偣 - NavigateNode currentNode = openQueue.poll(); + AStarNavigateNode currentNode = openQueue.poll(); - List<NavigateNode> neighbourNodes = this.getNeighborNodes(currentNode, mapMatrix, existNodes); - for (NavigateNode node : neighbourNodes) { + // 缁堢偣 + if (currentNode.getX() == end.getX() && currentNode.getY() == end.getY()) { +// System.out.println("getNeighborNodes spend time: " + getNeighborNodesTime +", count: " + getNeighborNodesCount); + return currentNode; + } + long currentTime = System.currentTimeMillis(); + List<AStarNavigateNode> neighbourNodes = this.getNeighborNodes(currentNode, mapMatrix, existNodes); + getNeighborNodesTime += System.currentTimeMillis() - currentTime; + getNeighborNodesCount ++; + for (AStarNavigateNode node : neighbourNodes) { node.setCodeData(codeMatrix[node.getX()][node.getY()]); boolean isEndNode = node.getX() == end.getX() && node.getY() == end.getY(); @@ -88,6 +107,9 @@ assert !vehicle.equals(DynamicNodeType.BLOCK.val); if (!vehicle.equals(DynamicNodeType.ACCESS.val)) { if (!vehicle.equals(agvNo)) { + if (lock) { + continue; + } // 濡傛灉瀛樺湪杞﹁締锛屽垯澧炲姞鏉冮噸 2 鎴栬�� 3锛屽洜涓烘嫄鐐逛細澧炲姞鏉冮噸 1 // vehicle宸茬粡涓哄綋鍓峴egment鍋氳繃浜嗛伩璁╋紝涓旈伩璁╀换鍔″凡瀹屾垚锛屽垯鏉冮噸鍊煎鍔� @@ -98,10 +120,6 @@ weight += (WEIGHT_CALC_FACTOR * 2); } } - - if (lock) { - continue; - } } } @@ -111,7 +129,6 @@ if (!waveNode.equals(WaveNodeType.ENABLE.val)) { List<String> waveNodeList = MapDataUtils.parseWaveNode(waveNode); List<String> otherWaveList = MapDataUtils.hasOtherWave(waveNodeList, agvNo); - if (!Cools.isEmpty(otherWaveList)) { if (lock) { @@ -121,91 +138,102 @@ } // 鍗曞贩閬撹溅杈嗗杞芥暟閲� - Lane lane = laneService.search(node.getCodeData()); - if (null != lane) { + List<int[]> laneCodeIdxList = laneService.getLaneCodeIdxList(node.getCodeData()); + if (!Cools.isEmpty(laneCodeIdxList)) { Set<String> lanVehicleSet = new HashSet<>(); - List<String> laneCodes = lane.getCodes(); - for (String laneCodeData : laneCodes) { - int[] laneCodeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(null, laneCodeData); - // scan dynamicMatrix or WaveMatrix - DynamicNode laneDynamicNode = dynamicMatrix[laneCodeMatrixIdx[0]][laneCodeMatrixIdx[1]]; + for (int[] codeMatrixIdx : laneCodeIdxList) { + DynamicNode laneDynamicNode = dynamicMatrix[codeMatrixIdx[0]][codeMatrixIdx[1]]; String laneVehicle = laneDynamicNode.getVehicle(); assert !laneVehicle.equals(DynamicNodeType.BLOCK.val); if (!laneVehicle.equals(DynamicNodeType.ACCESS.val)) { if (!laneVehicle.equals(agvNo)) { lanVehicleSet.add(laneVehicle); -// redis.setObject(RedisConstant.AGV_TO_STANDBY_FLAG, laneVehicle, true, 30); } } } - if (lanVehicleSet.size() + 1 > maxAgvCountInLane) { continue; } } - - //鎵惧埌鐩爣缁撶偣灏辫繑鍥� - if (isEndNode) { - //骞朵笖璁$畻鍑篏锛� F锛� H绛夊�� - node.initNode(currentNode, end); - return node; - } - - // G + H + T (瀵瑰惎鍙戝嚱鏁板鍔犲幓鎷愮偣鏂规calcNodeTurnCost) - int gCost = calcNodeCost(currentNode, node); - if (OPEN_TURN_COST_WEIGHT) { - gCost += calcNodeTurnCost(currentNode, node, end); + if (this.isTurning(currentNode, node)) { + weight += WEIGHT_CALC_FACTOR; + node.setTurnCount(currentNode.getTurnCount() + 1); + } else { + // 鏂瑰悜娌″彉 + node.setTurnCount(currentNode.getTurnCount()); + } } //杩涜璁$畻瀵� G, F, H 绛夊�� node.setWeight(weight); - node.setLastDistance(gCost); + node.setLastDistance(calcNodeCost(currentNode, node)); node.initNode(currentNode, end); node.setH(calcNodeCost(node, end)); node.setF(node.getG() + node.getH()); - openQueue.add(node); - existNodes.add(node); + String key = node.getX() + "_" + node.getY(); + Integer recordedG = bestGMap.get(key); + if (recordedG == null || node.getG() <= recordedG) { + bestGMap.put(key, node.getG()); + + openQueue.add(node); + } + +// openQueue.add(node); +// existNodes.add(node); } } - //濡傛灉閬嶅巻瀹屾墍鏈夊嚭鐜扮殑缁撶偣閮芥病鏈夋壘鍒版渶缁堢殑缁撶偣锛岃繑鍥瀗ull +// System.out.println("getNeighborNodes spend time: " + getNeighborNodesTime +", count: " + getNeighborNodesCount); return null; } // 鑾峰彇鍥涘懆鑺傜偣 - private List<NavigateNode> getNeighborNodes(NavigateNode currentNode, int[][] mapMatrix, Set<NavigateNode> existNodes) { + private List<AStarNavigateNode> getNeighborNodes(AStarNavigateNode currentNode, int[][] mapMatrix, Set<AStarNavigateNode> existNodes) { int x = currentNode.getX(); int y = currentNode.getY(); + AStarNavigateNode parent = currentNode.getParent(); - List<NavigateNode> neighbourNodes = new CopyOnWriteArrayList<>(); +// List<AStarNavigateNode> neighbourNodes = new CopyOnWriteArrayList<>(); + List<AStarNavigateNode> neighbourNodes = new ArrayList<>(); - List<NavigateNode> possibleNodes = Arrays.asList( - new NavigateNode(x, y + 1), // right - new NavigateNode(x, y - 1), // left - new NavigateNode(x - 1, y), // up - new NavigateNode(x + 1, y) // down - ); + List<AStarNavigateNode> possibleNodes = new ArrayList<>(); + for (int[] d: DIRECTIONS) { + int nx = x + d[0]; + int ny = y + d[1]; + // 濡傛灉鐖惰妭鐐逛笉涓虹┖锛屽苟涓� (nx,ny) 绛変簬鐖惰妭鐐瑰潗鏍囷紝鍒欒烦杩� + if (parent != null && nx == parent.getX() && ny == parent.getY()) { + continue; + } + possibleNodes.add(new AStarNavigateNode(nx, ny)); + } - possibleNodes.parallelStream() - .map(extendNode -> extendNeighborNodes(currentNode, extendNode, mapMatrix, existNodes, null, null)) - .filter(Objects::nonNull) - .forEach(neighbourNodes::add); +// possibleNodes.parallelStream() +// .map(extendNode -> extendNeighborNodes(currentNode, extendNode, mapMatrix, existNodes, null, null)) +// .filter(Objects::nonNull) +// .forEach(neighbourNodes::add); + + for (AStarNavigateNode pn : possibleNodes) { + AStarNavigateNode next = extendNeighborNodes(currentNode, pn, mapMatrix, existNodes, null, null); + if (next != null) { + neighbourNodes.add(next); + } + } return neighbourNodes; } - private NavigateNode extendNeighborNodes(NavigateNode currentNode, NavigateNode extendNode, int[][] mapMatrix, Set<NavigateNode> existNodes, Integer dx, Integer dy) { - NavigateNode nextNode; + private AStarNavigateNode extendNeighborNodes(AStarNavigateNode currentNode, AStarNavigateNode extendNode, int[][] mapMatrix, Set<AStarNavigateNode> existNodes, Integer dx, Integer dy) { + AStarNavigateNode nextNode; if (null == dx || null == dy) { dx = extendNode.getX() - currentNode.getX(); dy = extendNode.getY() - currentNode.getY(); nextNode = extendNode; } else { - nextNode = new NavigateNode(extendNode.getX() + dx, extendNode.getY() + dy); + nextNode = new AStarNavigateNode(extendNode.getX() + dx, extendNode.getY() + dy); } int x = nextNode.getX(); @@ -223,9 +251,9 @@ assert mapMatrix[x][y] == MapNodeType.ENABLE.val; - if (existNodes.contains(nextNode)) { - return null; - } +// if (existNodes.contains(nextNode)) { +// return null; +// } // 鍒ゆ柇閫氳繃鎬� String routeCdaKey = RouteGenerator.generateRouteCdaKey(new int[]{currentNode.getX(), currentNode.getY()}, new int[]{nextNode.getX(), nextNode.getY()}); @@ -239,27 +267,41 @@ //------------------A*鍚彂鍑芥暟------------------// //璁$畻閫氳繃鐜板湪鐨勭粨鐐圭殑浣嶇疆鍜屾渶缁堢粨鐐圭殑浣嶇疆璁$畻H鍊�(鏇煎搱椤挎硶锛氬潗鏍囧垎鍒彇宸�肩浉鍔�) - private int calcNodeCost(NavigateNode node1, NavigateNode node2) { + private int calcNodeCost(AStarNavigateNode node1, AStarNavigateNode node2) { return Math.abs(node2.getX() - node1.getX()) + Math.abs(node2.getY() - node1.getY()); } - //鍘婚櫎鎷愮偣绠楁硶锛岀粰鐩寸嚎澧炲姞浼樺厛绾� - private int calcNodeTurnCost(NavigateNode currNode, NavigateNode nextNode, NavigateNode endNode) { - // 绗竴涓偣鎴栫洿绾跨偣 - if (currNode.getParent() == null - || nextNode.getX() == currNode.getParent().getX() - || nextNode.getY() == currNode.getParent().getY() - ) { - return 0; + // 杞集鍒ゆ柇锛氬彧鍏佽鈥滃瀭鐩存垨姘村钩鈥濊繍鍔� + private boolean isTurning(AStarNavigateNode currNode, AStarNavigateNode nextNode) { + // 绗竴涓偣 + if (currNode.getParent() == null) { + return false; } - - // 鎷愬悜缁堢偣鐨勭偣 - if (nextNode.getX() == endNode.getX() || nextNode.getY() == endNode.getY()) { - return 1; - } - - // 鏅�氭嫄鐐� - return 1; + AStarNavigateNode parent = currNode.getParent(); + // 濡傛灉涓嬩竴鐐癸紙nextNode锛変笌 parent 鍦ㄥ悓涓�琛屾垨鍚屼竴鍒� => 娌℃湁杞集 + // 娉ㄦ剰锛岃繖瀹為檯涓婄瓑鍚屼簬鈥�(curr->next) 鐨勬柟鍚� == (parent->curr) 鐨勬柟鍚戔�濄�� + boolean sameRowOrCol = + (nextNode.getX() == parent.getX()) + || (nextNode.getY() == parent.getY()); + return !sameRowOrCol; } + // 杞集鍒ゆ柇锛氬鏋滆繖涓や釜鍚戦噺鐩稿悓锛堜緥濡傞兘绛変簬 (0,1)锛夛紝璇存槑鏂瑰悜鐩稿悓锛涘惁鍒欒鏄庤浆寮�� +// private boolean isTurning(AStarNavigateNode currNode, AStarNavigateNode nextNode) { +// // 濡傛灉 currNode 娌℃湁鐖惰妭鐐癸紝璇存槑鏄捣鐐癸紝涓嶇畻杞集 +// if (currNode.getParent() == null) { +// return false; +// } +// // 鍙栧嚭鍧愭爣 +// AStarNavigateNode parent = currNode.getParent(); +// int px = currNode.getX() - parent.getX(); // parent -> curr 鐨剎鍋忕Щ +// int py = currNode.getY() - parent.getY(); // parent -> curr 鐨剏鍋忕Щ +// +// int nx = nextNode.getX() - currNode.getX(); // curr -> next 鐨剎鍋忕Щ +// int ny = nextNode.getY() - currNode.getY(); // curr -> next 鐨剏鍋忕Щ +// +// // 濡傛灉 (px, py) 涓� (nx, ny) 涓嶄竴鏍凤紝灏辫鏄庤浆寮� +// return (px != nx) || (py != ny); +// } + } -- Gitblit v1.9.1