From 1d520bffcd63cb8389c9cdf719c3cf7e7c4af567 Mon Sep 17 00:00:00 2001
From: jianghaiyue <jianghaiyue@zkyt.com>
Date: 星期四, 30 十月 2025 10:20:28 +0800
Subject: [PATCH] 优化更新
---
algo-zkd/src/main/java/com/algo/service/AStarPathPlanner.java | 255 +++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 226 insertions(+), 29 deletions(-)
diff --git a/algo-zkd/src/main/java/com/algo/service/AStarPathPlanner.java b/algo-zkd/src/main/java/com/algo/service/AStarPathPlanner.java
index 4ae0129..cdc4431 100644
--- a/algo-zkd/src/main/java/com/algo/service/AStarPathPlanner.java
+++ b/algo-zkd/src/main/java/com/algo/service/AStarPathPlanner.java
@@ -4,12 +4,15 @@
import com.algo.model.PathCode;
import com.algo.model.PlannedPath;
import com.algo.util.JsonUtils;
+import com.algo.util.PathTimeCalculator;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.File;
import java.util.*;
/**
* A*璺緞瑙勫垝鍣ㄥ疄鐜�
- * 浣跨敤3D A*绠楁硶杩涜CTU鏃剁┖璺緞瑙勫垝锛屾敮鎸佺墿鐞嗙害鏉�
*/
public class AStarPathPlanner implements PathPlanner {
@@ -22,6 +25,11 @@
* 閭绘帴琛�
*/
private final Map<String, List<Map<String, String>>> adjacencyList;
+
+ /**
+ * 鐜杩為�氭�ф暟鎹�
+ */
+ private final JsonUtils.EnvironmentConnectivity environmentConnectivity;
/**
* 鏃堕棿绮惧害锛堟绉掞級
@@ -39,7 +47,7 @@
private final int maxSearchDepth = 15000;
/**
- * 璺濈缂撳瓨 - 浼樺寲锛氱紦瀛樿窛绂昏绠楃粨鏋�
+ * 璺濈缂撳瓨
*/
private final Map<String, Double> distanceCache = new HashMap<>();
@@ -47,6 +55,16 @@
* 蹇�熻矾寰勭紦瀛�
*/
private final Map<String, List<String>> fastPathCache = new HashMap<>();
+
+ /**
+ * 瀹為檯鍧愭爣鏄犲皠
+ */
+ private Map<String, double[]> realCoordinateMapping;
+
+ /**
+ * 璺緞鏃堕棿璁$畻鍣�
+ */
+ private PathTimeCalculator timeCalculator;
/**
* 鏋勯�犲嚱鏁�
@@ -55,15 +73,82 @@
*/
public AStarPathPlanner(Map<String, Map<String, Integer>> pathMapping) {
this.pathMapping = pathMapping;
- this.adjacencyList = new HashMap<>();
- // 鐩存帴鏋勫缓閭绘帴琛�
- buildAdjacencyList();
+ // 鍔犺浇鐜杩為�氭�ф暟鎹�
+ this.environmentConnectivity = JsonUtils.loadEnvironmentConnectivity("environment.json");
+
+ // 鍔犺浇閭绘帴琛�
+ Map<String, List<Map<String, String>>> loadedAdjacency = loadAdjacencyListFromJson("adjacency.json");
+
+ if (loadedAdjacency != null && !loadedAdjacency.isEmpty()) {
+ // 鎴愬姛鍔犺浇棰勭敓鎴愮殑閭绘帴琛�
+ this.adjacencyList = loadedAdjacency;
+ System.out.println("浠� adjacency.json 鍔犺浇閭绘帴琛�: " + adjacencyList.size() + " 涓妭鐐�");
+ } else {
+ this.adjacencyList = new HashMap<>();
+ buildEnvironmentAwareAdjacencyList();
+ System.out.println("浣跨敤缃戞牸鐩搁偦鎬ф瀯寤洪偦鎺ヨ〃: " + adjacencyList.size() + " 涓妭鐐�");
+ }
+
+ // 鍔犺浇瀹為檯鍧愭爣鏄犲皠
+ loadRealCoordinateMapping();
+
+ // 鍒濆鍖栨椂闂磋绠楀櫒
+ this.timeCalculator = new PathTimeCalculator(pathMapping, realCoordinateMapping);
// 棰勮绠楀父鐢ㄨ窛绂�
precomputeCommonDistances();
System.out.println("A*璺緞瑙勫垝鍣ㄥ垵濮嬪寲瀹屾垚锛岄偦鎺ヨ〃鍖呭惈 " + adjacencyList.size() + " 涓妭鐐�");
+ }
+
+ /**
+ * 浠� JSON 鏂囦欢鍔犺浇棰勭敓鎴愮殑閭绘帴琛�
+ */
+ private Map<String, List<Map<String, String>>> loadAdjacencyListFromJson(String filePath) {
+ try {
+ File file = new File(filePath);
+
+ if (!file.exists()) {
+ System.out.println("璺緞閭绘帴琛ㄦ枃浠朵笉瀛樺湪: " + filePath + "锛屼娇鐢ㄩ粯璁ゆ瀯寤烘柟娉�");
+ return null;
+ }
+
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ TypeReference<Map<String, List<Map<String, String>>>> typeRef =
+ new TypeReference<Map<String, List<Map<String, String>>>>() {};
+
+ Map<String, List<Map<String, String>>> adjacency = objectMapper.readValue(file, typeRef);
+
+ if (adjacency == null || adjacency.isEmpty()) {
+ System.out.println("閭绘帴琛ㄦ枃浠朵负绌�: " + filePath);
+ return null;
+ }
+
+ return adjacency;
+
+ } catch (Exception e) {
+ System.err.println("鍔犺浇閭绘帴琛ㄥけ璐�: " + e.getMessage());
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * 鍔犺浇瀹為檯鍧愭爣鏄犲皠
+ */
+ private void loadRealCoordinateMapping() {
+ try {
+ this.realCoordinateMapping = JsonUtils.loadRealCoordinateMapping("man_code.json");
+ if (realCoordinateMapping == null || realCoordinateMapping.isEmpty()) {
+ System.out.println("鏈兘鍔犺浇瀹為檯鍧愭爣鏄犲皠锛屼娇鐢ㄧ綉鏍煎潗鏍�");
+ this.realCoordinateMapping = new HashMap<>();
+ }
+ } catch (Exception e) {
+ System.err.println("鍔犺浇瀹為檯鍧愭爣鏄犲皠澶辫触: " + e.getMessage());
+ this.realCoordinateMapping = new HashMap<>();
+ }
}
@Override
@@ -278,7 +363,7 @@
}
}
- // 鍑忓皯绛夊緟閫夐」 - 鍙湪蹇呰鏃剁瓑寰咃紙20%姒傜巼锛�
+ // 鍑忓皯绛夊緟閫夐」
if (Math.random() < 0.2) {
long waitTime = timeResolution;
long waitUntilTime = current.timePoint + waitTime;
@@ -308,27 +393,61 @@
/**
* 鏃剁┖鍚彂寮忓嚱鏁�
*
- * @param coord1 褰撳墠鍧愭爣
- * @param coord2 鐩爣鍧愭爣
+ * @param coord1 褰撳墠鍧愭爣锛堢綉鏍硷級
+ * @param coord2 鐩爣鍧愭爣锛堢綉鏍硷級
* @param currentTime 褰撳墠鏃堕棿
* @param physicalConfig 鐗╃悊閰嶇疆
* @return 鍚彂寮忓��
*/
private double spaceTimeHeuristic(int[] coord1, int[] coord2, long currentTime, CTUPhysicalConfig physicalConfig) {
- // 绌洪棿璺濈
+ String pathId1 = findPathIdByCoordinate(coord1);
+ String pathId2 = findPathIdByCoordinate(coord2);
+
+ if (pathId1 != null && pathId2 != null) {
+ double[] realCoord1 = JsonUtils.getRealCoordinate(pathId1, realCoordinateMapping);
+ double[] realCoord2 = JsonUtils.getRealCoordinate(pathId2, realCoordinateMapping);
+
+ if (realCoord1 != null && realCoord2 != null) {
+ // 浣跨敤瀹為檯璺濈璁$畻
+ double realDistance = CTUPhysicalConfig.calculateRealDistance(realCoord1, realCoord2);
+
+ // 鏃堕棿鎴愭湰浼拌锛堝亣璁惧钩鍧囬�熷害锛�
+ double timeEstimate = realDistance / physicalConfig.getNormalSpeed();
+
+ // 鑰冭檻杞悜鎴愭湰
+ double turnPenalty = realDistance > 0.5 ? physicalConfig.getTurnTime90() / 2.0 : 0;
+
+ return timeEstimate + turnPenalty;
+ }
+ }
+
+ // 鍓嶆柟妗堬細浣跨敤缃戞牸鍧愭爣
double spatialDistance = Math.abs(coord1[0] - coord2[0]) + Math.abs(coord1[1] - coord2[1]);
-
- // 鏃堕棿鎴愭湰浼拌
double timeEstimate = spatialDistance * physicalConfig.getStandardPointDistance() / physicalConfig.getNormalSpeed();
-
- // 鑰冭檻杞悜鎴愭湰
double turnPenalty = spatialDistance > 1 ? physicalConfig.getTurnTime90() : 0;
return timeEstimate + turnPenalty;
}
+
+ /**
+ * 鏍规嵁缃戞牸鍧愭爣鏌ユ壘璺緞ID
+ */
+ private String findPathIdByCoordinate(int[] coord) {
+ if (coord == null) return null;
+
+ for (Map.Entry<String, Map<String, Integer>> entry : pathMapping.entrySet()) {
+ Map<String, Integer> coordMap = entry.getValue();
+ if (coordMap != null &&
+ coord[0] == coordMap.getOrDefault("x", -1) &&
+ coord[1] == coordMap.getOrDefault("y", -1)) {
+ return entry.getKey();
+ }
+ }
+ return null;
+ }
/**
- * 璁$畻绉诲姩鏃堕棿
+ * 璁$畻绮剧‘鐨勭Щ鍔ㄦ椂闂达紝鍩轰簬瀹為檯鍧愭爣鍜岀墿鐞嗗弬鏁�
*
* @param fromCode 璧峰浠g爜
* @param toCode 鐩爣浠g爜
@@ -337,14 +456,70 @@
* @return 绉诲姩鏃堕棿锛堟绉掞級
*/
private long calculateTravelTime(String fromCode, String toCode, String direction, CTUPhysicalConfig physicalConfig) {
- // 鍩烘湰绉诲姩鏃堕棿
+ // 鑾峰彇瀹為檯鍧愭爣
+ double[] fromCoord = JsonUtils.getRealCoordinate(fromCode, realCoordinateMapping);
+ double[] toCoord = JsonUtils.getRealCoordinate(toCode, realCoordinateMapping);
+
+ if (fromCoord == null || toCoord == null) {
+ // fallback鍒扮綉鏍煎潗鏍囪绠�
+ return calculateFallbackTravelTime(fromCode, toCode, physicalConfig);
+ }
+
+ // 璁$畻瀹為檯璺濈锛堢背锛�
+ double realDistance = CTUPhysicalConfig.calculateRealDistance(fromCoord, toCoord);
+
+ if (realDistance == 0.0) {
+ return 100; // 鏈�灏忔椂闂�100ms
+ }
+
+ // 鍋囪璧峰鍜岀粨鏉熼�熷害锛堝彲浠ユ牴鎹笂涓嬫枃杩涗竴姝ヤ紭鍖栵級
+ double startSpeed = 0.0; // 鍋囪浠庨潤姝㈠紑濮�
+ double endSpeed = 0.0; // 鍋囪缁撴潫鏃跺仠姝�
+ double targetSpeed = physicalConfig.getNormalSpeed();
+
+ // 璁$畻绮剧‘鐨勭Щ鍔ㄦ椂闂�
+ double movementTime = physicalConfig.calculatePreciseMovementTime(
+ realDistance, startSpeed, endSpeed, targetSpeed
+ );
+
+ // 璁$畻杞悜鏃堕棿
+ double turnTime = calculateTurnTime(fromCode, toCode, physicalConfig);
+
+ return Math.max(100, (long) ((movementTime + turnTime) * 1000));
+ }
+
+ /**
+ * 璁$畻杞悜鏃堕棿
+ */
+ private double calculateTurnTime(String fromCode, String toCode, CTUPhysicalConfig physicalConfig) {
+
+ double[] fromCoord = JsonUtils.getRealCoordinate(fromCode, realCoordinateMapping);
+ double[] toCoord = JsonUtils.getRealCoordinate(toCode, realCoordinateMapping);
+
+ if (fromCoord == null || toCoord == null) {
+ return physicalConfig.getTurnTime90() / 4.0; // 骞冲潎杞悜鏃堕棿
+ }
+
+ // 璁$畻鏂瑰悜鍙樺寲
+ double dx = toCoord[0] - fromCoord[0];
+ double dy = toCoord[1] - fromCoord[1];
+
+ // 鐩寸嚎杩愬姩鏃犻渶杞悜
+ if (Math.abs(dx) < 1.0 && Math.abs(dy) < 1.0) {
+ return 0.0;
+ }
+
+ return physicalConfig.getTurnTime90() / 2.0;
+ }
+
+ /**
+ * 澶囩敤鏃堕棿璁$畻鏂规硶锛堝綋鏃犳硶鑾峰彇瀹為檯鍧愭爣鏃朵娇鐢級
+ */
+ private long calculateFallbackTravelTime(String fromCode, String toCode, CTUPhysicalConfig physicalConfig) {
double distance = physicalConfig.getStandardPointDistance();
double speed = physicalConfig.getNormalSpeed();
long moveTime = (long) ((distance / speed) * 1000);
-
- // 杞悜鏃堕棿
- long turnTime = (long) (physicalConfig.getTurnTime90() * 1000 / 4); // 鍋囪骞冲潎杞悜鏃堕棿
-
+ long turnTime = (long) (physicalConfig.getTurnTime90() * 1000 / 4);
return moveTime + turnTime;
}
@@ -384,14 +559,17 @@
}
PathCode pathCode = new PathCode(node.code, direction);
-
- // 娣诲姞鏃堕棿淇℃伅
- // pathCode.setArrivalTime(node.timePoint);
-
codeList.add(pathCode);
}
- return new PlannedPath("", "", codeList);
+ PlannedPath plannedPath = new PlannedPath("", "", codeList);
+
+ // 浣跨敤缁熶竴鐨勬椂闂磋绠楀櫒璁$畻绮剧‘鏃堕棿
+ long startTime = pathNodes.get(0).timePoint;
+ CTUPhysicalConfig defaultConfig = createDefaultPhysicalConfig();
+ timeCalculator.calculatePathTiming(plannedPath, startTime, defaultConfig, 0.0);
+
+ return plannedPath;
}
/**
@@ -472,6 +650,15 @@
@Override
public double calculateDistance(String startCode, String endCode) {
+ // 浼樺厛浣跨敤瀹為檯鍧愭爣
+ double[] startRealCoord = JsonUtils.getRealCoordinate(startCode, realCoordinateMapping);
+ double[] endRealCoord = JsonUtils.getRealCoordinate(endCode, realCoordinateMapping);
+
+ if (startRealCoord != null && endRealCoord != null) {
+ return CTUPhysicalConfig.calculateRealDistance(startRealCoord, endRealCoord);
+ }
+
+ // 鍓嶆柟妗堬細浣跨敤缃戞牸鍧愭爣
int[] startCoord = JsonUtils.getCoordinate(startCode, pathMapping);
int[] endCoord = JsonUtils.getCoordinate(endCode, pathMapping);
@@ -493,9 +680,9 @@
}
/**
- * 鏋勫缓閭绘帴琛�
+ * 鏋勫缓鐜鎰熺煡鐨勯偦鎺ヨ〃
*/
- private void buildAdjacencyList() {
+ private void buildEnvironmentAwareAdjacencyList() {
// 鍒涘缓鍧愭爣鍒扮紪鍙风殑涓存椂鏄犲皠
Map<String, String> tempCoordToCode = new HashMap<>();
for (Map.Entry<String, Map<String, Integer>> entry : pathMapping.entrySet()) {
@@ -523,6 +710,12 @@
int x = coordMap.get("x");
int y = coordMap.get("y");
+ // 鐜鎰熺煡锛氭鏌ュ綋鍓嶈妭鐐规槸鍚﹀彲閫氳
+ if (!environmentConnectivity.isTraversable(x, y)) {
+ adjacencyList.put(code, new ArrayList<>()); // 涓嶅彲閫氳鐨勮妭鐐规病鏈夐偦灞�
+ continue;
+ }
+
List<Map<String, String>> neighbors = new ArrayList<>();
// 妫�鏌ュ洓涓柟鍚戠殑閭诲眳
@@ -532,7 +725,9 @@
String coordKey = newX + "," + newY;
String neighborCode = tempCoordToCode.get(coordKey);
- if (neighborCode != null) {
+
+ // 鐜鎰熺煡锛氬彧鏈夊綋閭诲眳鑺傜偣涔熷彲閫氳鏃舵墠娣诲姞杩炴帴
+ if (neighborCode != null && environmentConnectivity.isTraversable(newX, newY)) {
Map<String, String> neighbor = new HashMap<>();
neighbor.put("code", neighborCode);
neighbor.put("direction", directionAngles[i]);
@@ -542,6 +737,8 @@
adjacencyList.put(code, neighbors);
}
+
+ System.out.println("鐜鎰熺煡閭绘帴琛ㄦ瀯寤哄畬鎴愶紝杩囨护浜嗕笉鍙�氳鐨勮繛鎺�");
}
/**
@@ -673,7 +870,7 @@
}
/**
- * 蹇�熻矾寰勮鍒� - 鍏堝皾璇曠畝鍖栫┖闂磋矾寰勮鍒�
+ * 蹇�熻矾寰勮鍒�
* 瀵逛簬杩戣窛绂昏矾寰勶紝鐩存帴杩斿洖缁撴灉閬垮厤澶嶆潅鐨勬椂绌鸿绠�
*/
private PlannedPath tryFastPathPlanning(String startCode, String endCode, List<double[]> constraints) {
@@ -722,7 +919,7 @@
openSet.offer(startNode);
gScores.put(startCode, 0.0);
- // 绠�鍖栫殑绾︽潫妫�鏌ュ櫒
+ // 绾︽潫妫�鏌ュ櫒
FastConstraintChecker constraintChecker = new FastConstraintChecker(constraints);
int searchDepth = 0;
--
Gitblit v1.9.1