| | |
| | | } |
| | | } |
| | | |
| | | // 减少等待选项 |
| | | 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); |
| | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 检查当前节点的邻居是否在短期内都被阻挡 |
| | | */ |
| | | 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; |
| | | } |
| | | |
| | | /** |
| | |
| | | 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 原始路径代码列表 |
| | | * @return 优化后的路径代码列表 |
| | | */ |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 正常添加当前点 |
| | | 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 位置代码 |