From 642f20dd1b068e23146b8ec96c5eac8b63c96b87 Mon Sep 17 00:00:00 2001
From: jianghaiyue <jianghaiyue@zkyt.com>
Date: 星期三, 05 十一月 2025 18:18:25 +0800
Subject: [PATCH] 优化更新
---
algo-zkd/src/main/java/com/algo/service/AStarPathPlanner.java | 198 +++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 181 insertions(+), 17 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 5fe5554..486c246 100644
--- a/algo-zkd/src/main/java/com/algo/service/AStarPathPlanner.java
+++ b/algo-zkd/src/main/java/com/algo/service/AStarPathPlanner.java
@@ -5,7 +5,10 @@
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.*;
/**
@@ -41,7 +44,7 @@
/**
* 鏈�澶ф悳绱㈡繁搴�
*/
- private final int maxSearchDepth = 15000;
+ private final int maxSearchDepth = 50000;
/**
* 璺濈缂撳瓨
@@ -70,13 +73,22 @@
*/
public AStarPathPlanner(Map<String, Map<String, Integer>> pathMapping) {
this.pathMapping = pathMapping;
- this.adjacencyList = new HashMap<>();
// 鍔犺浇鐜杩為�氭�ф暟鎹�
this.environmentConnectivity = JsonUtils.loadEnvironmentConnectivity("environment.json");
- // 鏋勫缓鐜鎰熺煡鐨勯偦鎺ヨ〃
- buildEnvironmentAwareAdjacencyList();
+ // 鍔犺浇閭绘帴琛�
+ 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();
@@ -88,6 +100,39 @@
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;
+ }
}
/**
@@ -113,7 +158,8 @@
if (fastPath != null) {
return fastPath;
}
- return planSpaceTimePath(startCode, endCode, constraints, null, null);
+ long defaultStartTime = System.currentTimeMillis();
+ return planSpaceTimePath(startCode, endCode, constraints, null, null, defaultStartTime);
}
@Override
@@ -129,12 +175,14 @@
* @param constraints 闈欐�佺害鏉熸潯浠�
* @param spaceTimeOccupancyMap 鏃剁┖鍗犵敤琛�
* @param physicalConfig CTU鐗╃悊閰嶇疆
+ * @param startTimeMs 璧峰鏃堕棿锛堟绉掞級
* @return 瑙勫垝鐨勮矾寰�
*/
public PlannedPath planSpaceTimePath(String startCode, String endCode,
List<double[]> constraints,
Map<String, String> spaceTimeOccupancyMap,
- CTUPhysicalConfig physicalConfig) {
+ CTUPhysicalConfig physicalConfig,
+ long startTimeMs) {
// 楠岃瘉杈撳叆
if (!isValidPathPoint(startCode) || !isValidPathPoint(endCode)) {
System.out.println("鏃犳晥鐨勮矾寰勭偣: " + startCode + " 鎴� " + endCode);
@@ -167,7 +215,7 @@
// 鏃剁┖A*绠楁硶瀹炵幇
PlannedPath result = spaceTimeAStarSearch(
startCode, endCode, startCoord, endCoord,
- constraints, spaceTimeOccupancyMap, physicalConfig
+ constraints, spaceTimeOccupancyMap, physicalConfig, startTimeMs
);
if (result != null) {
@@ -189,13 +237,15 @@
* @param constraints 绾︽潫鏉′欢
* @param occupancyMap 鏃剁┖鍗犵敤琛�
* @param physicalConfig 鐗╃悊閰嶇疆
+ * @param startTimeMs 璧峰鏃堕棿锛堟绉掞級
* @return 瑙勫垝鐨勮矾寰�
*/
private PlannedPath spaceTimeAStarSearch(String startCode, String endCode,
int[] startCoord, int[] endCoord,
List<double[]> constraints,
Map<String, String> occupancyMap,
- CTUPhysicalConfig physicalConfig) {
+ CTUPhysicalConfig physicalConfig,
+ long startTimeMs) {
// 浣跨敤浼樺厛闃熷垪瀹炵幇寮�鏀惧垪琛�
PriorityQueue<SpaceTimeAStarNode> openSet = new PriorityQueue<>(
@@ -205,8 +255,7 @@
Map<String, Double> gScores = new HashMap<>();
Map<String, SpaceTimeAStarNode> cameFrom = new HashMap<>();
- // 璧峰鏃堕棿
- long startTime = System.currentTimeMillis();
+ long startTime = startTimeMs;
// 鍒濆鍖栬捣濮嬭妭鐐�
SpaceTimeAStarNode startNode = new SpaceTimeAStarNode(
@@ -318,8 +367,9 @@
}
}
- // 鍑忓皯绛夊緟閫夐」
- if (Math.random() < 0.2) {
+ // 蹇呰鏃讹紙鏈夊啿绐侊級鐢熸垚绛夊緟鑺傜偣锛涘綋鍓嶈妭鐐圭殑鎵�鏈夐偦灞呭湪鐭湡鍐呴兘琚樆鎸″垯绛夊緟
+ boolean allNeighborsBlocked = checkIfAllNeighborsBlocked(current, constraintChecker, physicalConfig);
+ if (allNeighborsBlocked) {
long waitTime = timeResolution;
long waitUntilTime = current.timePoint + waitTime;
String waitKey = createSpaceTimeKey(current.code, waitUntilTime);
@@ -343,6 +393,52 @@
}
}
}
+ }
+
+ /**
+ * 妫�鏌ュ綋鍓嶈妭鐐圭殑閭诲眳鏄惁鍦ㄧ煭鏈熷唴閮借闃绘尅
+ */
+ private boolean checkIfAllNeighborsBlocked(SpaceTimeAStarNode current,
+ EnhancedConstraintChecker constraintChecker,
+ CTUPhysicalConfig physicalConfig) {
+ // 鑾峰彇褰撳墠鑺傜偣鐨勬墍鏈夌┖闂撮偦灞�
+ List<Map<String, String>> neighbors = getNeighbors(current.code);
+
+ if (neighbors.isEmpty()) {
+ return true;
+ }
+
+ // 妫�鏌ユ湭鏉ュ嚑涓椂闂寸墖鍐呯殑鍗犵敤鎯呭喌
+ int checkTimeSteps = 3;
+ boolean allBlocked = true;
+
+ for (int step = 1; step <= checkTimeSteps; step++) {
+ long checkTime = current.timePoint + (step * timeResolution);
+
+ // 妫�鏌ユ槸鍚︽湁鑷冲皯涓�涓偦灞呭湪褰撳墠鏃堕棿鐗囧彲鐢�
+ for (Map<String, String> neighbor : neighbors) {
+ String neighborCode = neighbor.get("code");
+ long arrivalTime = checkTime;
+
+ // 瀵归綈鍒版椂闂村垎杈ㄧ巼
+ arrivalTime = alignToTimeResolution(arrivalTime);
+
+ // 妫�鏌ヨ繖涓偦灞呭湪褰撳墠鏃堕棿鐗囨槸鍚﹀彲鐢�
+ if (constraintChecker.isValidMove(current.code, neighborCode,
+ current.timePoint, arrivalTime)) {
+ // 鑷冲皯鏈変竴涓偦灞呭彲鐢紝涓嶉渶瑕佺瓑寰�
+ allBlocked = false;
+ break;
+ }
+ }
+
+ // 濡傛灉鎵惧埌鍙敤閭诲眳锛屼笉闇�瑕佺瓑寰�
+ if (!allBlocked) {
+ break;
+ }
+ }
+
+ return allBlocked;
}
/**
@@ -517,17 +613,85 @@
codeList.add(pathCode);
}
+ codeList = optimizePathByRemovingBacktrack(codeList);
+
PlannedPath plannedPath = new PlannedPath("", "", codeList);
- // 浣跨敤缁熶竴鐨勬椂闂磋绠楀櫒璁$畻绮剧‘鏃堕棿
- long startTime = pathNodes.get(0).timePoint;
- CTUPhysicalConfig defaultConfig = createDefaultPhysicalConfig();
- timeCalculator.calculatePathTiming(plannedPath, startTime, defaultConfig, 0.0);
-
return plannedPath;
}
/**
+ * 浼樺寲璺緞锛氬幓闄ょ┖闂翠笂鐨勯噸澶嶇偣锛堥伩鍏嶆潵鍥炶蛋锛�
+ * 妫�娴嬪苟绉婚櫎 A->B->A 妯″紡鐨勬潵鍥炶蛋锛岄伩鍏嶄笉蹇呰鐨勭粫琛�
+ *
+ * @param codeList 鍘熷璺緞浠g爜鍒楄〃
+ * @return 浼樺寲鍚庣殑璺緞浠g爜鍒楄〃
+ */
+ private List<PathCode> optimizePathByRemovingBacktrack(List<PathCode> codeList) {
+ if (codeList == null || codeList.size() <= 2) {
+ return codeList;
+ }
+
+ List<PathCode> optimized = new ArrayList<>();
+ int i = 0;
+
+ while (i < codeList.size()) {
+ PathCode current = codeList.get(i);
+
+ // 妫�鏌ユ槸鍚︽槸鏉ュ洖璧版ā寮忥細A->B->A锛堣繛缁笁涓偣锛岀涓�涓拰绗笁涓浉鍚岋級
+ // 濡傛灉鍑虹幇鏉ュ洖璧帮紝璺宠繃B鍜岀浜屼釜A锛岀洿鎺ュ埌涓嬩竴涓笉鍚岀殑鐐�
+ if (i < codeList.size() - 2) {
+ PathCode next = codeList.get(i + 1);
+ PathCode nextNext = codeList.get(i + 2);
+
+ // 妫�娴嬫潵鍥炶蛋锛氬綋鍓嶄綅缃� == 涓嬩笅涓綅缃紝涓斾腑闂翠綅缃笉鍚�
+ if (current.getCode().equals(nextNext.getCode()) &&
+ !current.getCode().equals(next.getCode())) {
+ // 鏉ュ洖璧帮細璺宠繃B鍜岀浜屼釜A锛岀洿鎺ュ鐞嗕笅涓�涓笉鍚岀殑鐐�
+ // 鎵惧埌涓嬩竴涓笌褰撳墠鐐逛笉鍚岀殑浣嶇疆
+ int j = i + 2;
+ while (j < codeList.size() && codeList.get(j).getCode().equals(current.getCode())) {
+ j++;
+ }
+ // 濡傛灉鎵惧埌浜嗕笉鍚岀殑鐐癸紝鎴栬�呭埌杈炬湯灏撅紝璺宠繃鏉ュ洖璧扮殑閮ㄥ垎
+ if (j < codeList.size()) {
+ i = j; // 璺冲埌涓嬩竴涓笉鍚岀殑鐐�
+ continue;
+ } else {
+ // 濡傛灉鍚庨潰閮芥槸鐩稿悓鐐癸紝淇濈暀褰撳墠鐐癸紙鍙兘鏄洰鏍囩偣锛�
+ break;
+ }
+ }
+ }
+
+ // 姝e父娣诲姞褰撳墠鐐�
+ optimized.add(current);
+ i++;
+ }
+
+ // 纭繚鐩爣鐐硅鍖呭惈
+ if (!optimized.isEmpty() && !codeList.isEmpty()) {
+ PathCode lastOriginal = codeList.get(codeList.size() - 1);
+ PathCode lastOptimized = optimized.get(optimized.size() - 1);
+ if (!lastOriginal.getCode().equals(lastOptimized.getCode())) {
+ optimized.add(lastOriginal);
+ }
+ }
+
+ // 閲嶆柊璁$畻鏂瑰悜锛堝洜涓轰紭鍖栧悗璺宠繃浜嗕腑闂寸偣锛屾柟鍚戦渶瑕佹洿鏂帮級
+ for (int k = 0; k < optimized.size(); k++) {
+ PathCode code = optimized.get(k);
+ if (k < optimized.size() - 1) {
+ PathCode nextCode = optimized.get(k + 1);
+ String direction = calculateDirection(code.getCode(), nextCode.getCode());
+ code.setDirection(direction);
+ }
+ }
+
+ return optimized;
+ }
+
+ /**
* 鍒涘缓鏃剁┖閿�
*
* @param code 浣嶇疆浠g爜
--
Gitblit v1.9.1