jianghaiyue
3 天以前 7dd762215b373851ed313b46bad08cc973816665
algo-zkd/src/main/java/com/algo/service/CollisionResolver.java
@@ -1,10 +1,12 @@
package com.algo.service;
import com.algo.model.AGVStatus;
import com.algo.model.Conflict;
import com.algo.model.ExecutingTask;
import com.algo.model.PathCode;
import com.algo.model.PlannedPath;
import com.algo.model.CTUPhysicalConfig;
import com.algo.util.JsonUtils;
import com.algo.util.PathTimeCalculator;
import java.util.*;
@@ -24,6 +26,16 @@
     * 路径时间计算器
     */
    private PathTimeCalculator timeCalculator;
    /**
     * 路径规划器
     */
    private PathPlanner pathPlanner;
    /**
     * 路径映射表(用于坐标转换)
     */
    private Map<String, Map<String, Integer>> pathMapping;
    /**
     * 构造函数
@@ -40,6 +52,20 @@
    public void setTimeCalculator(PathTimeCalculator timeCalculator) {
        this.timeCalculator = timeCalculator;
    }
    /**
     * 设置路径规划器
     */
    public void setPathPlanner(PathPlanner pathPlanner) {
        this.pathPlanner = pathPlanner;
    }
    /**
     * 设置路径映射表
     */
    public void setPathMapping(Map<String, Map<String, Integer>> pathMapping) {
        this.pathMapping = pathMapping;
    }
    /**
     * 解决路径冲突
@@ -47,11 +73,17 @@
     * @param plannedPaths   规划路径列表
     * @param conflicts      冲突列表
     * @param executingTasks 执行中任务列表
     * @param agvStatusList  AGV状态列表(用于判断剩余路径)
     * @return 解决冲突后的路径列表
     */
    /**
     * 解决路径冲突
     */
    public List<PlannedPath> resolveConflicts(List<PlannedPath> plannedPaths,
                                              List<Conflict> conflicts,
                                              List<ExecutingTask> executingTasks) {
                                              List<ExecutingTask> executingTasks,
                                              List<AGVStatus> agvStatusList,
                                              long unifiedTimestamp) {
        if (conflicts == null || conflicts.isEmpty()) {
            return plannedPaths;
        }
@@ -63,6 +95,28 @@
        for (PlannedPath path : plannedPaths) {
            pathsMap.put(path.getAgvId(), path);
        }
        // 构建AGV状态字典
        Map<String, AGVStatus> agvStatusMap = new HashMap<>();
        if (agvStatusList != null) {
            for (AGVStatus agv : agvStatusList) {
                if (agv.getAgvId() != null) {
                    agvStatusMap.put(agv.getAgvId(), agv);
                }
            }
        }
        // 构建所有已规划路径的占用位置集合(用于查找等待位置时避开)
        Set<String> allOccupiedPositions = new HashSet<>();
        for (PlannedPath path : plannedPaths) {
            if (path.getCodeList() != null) {
                for (PathCode code : path.getCodeList()) {
                    if (code.getCode() != null) {
                        allOccupiedPositions.add(code.getCode());
                    }
                }
            }
        }
        // 按时间步排序处理冲突
        List<Conflict> sortedConflicts = new ArrayList<>(conflicts);
@@ -70,7 +124,9 @@
        // 逐个解决冲突
        for (Conflict conflict : sortedConflicts) {
            resolveSingleConflict(pathsMap, conflict, executingTasks);
            // 对于每个冲突,计算两车路径重合的位置
            Set<String> overlappingPositions = findOverlappingPositions(pathsMap, conflict);
            resolveSingleConflict(pathsMap, conflict, executingTasks, agvStatusMap, overlappingPositions, unifiedTimestamp);
        }
        List<PlannedPath> resolvedPaths = new ArrayList<>(pathsMap.values());
@@ -81,17 +137,30 @@
        return resolvedPaths;
    }
    /**
     * 解决路径冲突
     *
     * @param plannedPaths   规划路径列表
     * @param conflicts      冲突列表
     * @param executingTasks 执行中任务列表
     * @return 解决冲突后的路径列表
     */
    public List<PlannedPath> resolveConflicts(List<PlannedPath> plannedPaths,
                                              List<Conflict> conflicts,
                                              List<ExecutingTask> executingTasks) {
        return resolveConflicts(plannedPaths, conflicts, executingTasks, null, System.currentTimeMillis() / 1000);
    }
    /**
     * 解决单个冲突
     *
     * @param pathsMap       路径映射
     * @param conflict       冲突
     * @param executingTasks 执行中任务列表
     */
    private void resolveSingleConflict(Map<String, PlannedPath> pathsMap,
                                       Conflict conflict,
                                       List<ExecutingTask> executingTasks) {
                                       List<ExecutingTask> executingTasks,
                                       Map<String, AGVStatus> agvStatusMap,
                                       Set<String> overlappingPositions,
                                       long unifiedTimestamp) {
        String conflictType = conflict.getType();
        switch (conflictType) {
@@ -103,6 +172,9 @@
                break;
            case "follow":
                resolveFollowingConflict(pathsMap, conflict, executingTasks);
                break;
            case "time_gap_insufficient":
                resolveTimeGapConflict(pathsMap, conflict, executingTasks, agvStatusMap, overlappingPositions, unifiedTimestamp);
                break;
            default:
                System.out.println("未知冲突类型: " + conflictType);
@@ -177,8 +249,8 @@
     * @param executingTasks 执行中任务列表
     */
    private void resolveFollowingConflict(Map<String, PlannedPath> pathsMap,
                                          Conflict conflict,
                                          List<ExecutingTask> executingTasks) {
                                         Conflict conflict,
                                         List<ExecutingTask> executingTasks) {
        String agv1 = conflict.getAgv1();
        String agv2 = conflict.getAgv2();
        int timeStep = conflict.getTimeStep();
@@ -200,7 +272,577 @@
    }
    /**
     * 评估AGV优先级 - 优化版本,只保留必要字段
     * 找到两车路径重合的位置
     */
    private Set<String> findOverlappingPositions(Map<String, PlannedPath> pathsMap, Conflict conflict) {
        Set<String> overlappingPositions = new HashSet<>();
        PlannedPath path1 = pathsMap.get(conflict.getAgv1());
        PlannedPath path2 = pathsMap.get(conflict.getAgv2());
        if (path1 == null || path2 == null ||
            path1.getCodeList() == null || path2.getCodeList() == null) {
            return overlappingPositions;
        }
        // 收集path1的所有位置
        Set<String> positions1 = new HashSet<>();
        for (PathCode code : path1.getCodeList()) {
            if (code.getCode() != null) {
                positions1.add(code.getCode());
            }
        }
        // 收集path2的所有位置
        Set<String> positions2 = new HashSet<>();
        for (PathCode code : path2.getCodeList()) {
            if (code.getCode() != null) {
                positions2.add(code.getCode());
            }
        }
        // 找到重合的位置
        for (String pos : positions1) {
            if (positions2.contains(pos)) {
                overlappingPositions.add(pos);
            }
        }
        System.out.println("[调试] 两车路径重合位置: " + overlappingPositions);
        return overlappingPositions;
    }
    /**
     * 解决时间间隔不足冲突
     * 策略:有剩余路径的AGV继续执行,新路径的AGV移动到安全等待位置
     */
    private void resolveTimeGapConflict(Map<String, PlannedPath> pathsMap,
                                        Conflict conflict,
                                        List<ExecutingTask> executingTasks,
                                        Map<String, AGVStatus> agvStatusMap,
                                        Set<String> overlappingPositions,
                                        long unifiedTimestamp) {
        String firstAgv = conflict.getAgv1();  // 先经过的AGV
        String secondAgv = conflict.getAgv2(); // 后经过的AGV
        String conflictPosition = conflict.getPosition1(); // 冲突位置
        PlannedPath path1 = pathsMap.get(firstAgv);
        PlannedPath path2 = pathsMap.get(secondAgv);
        if (path1 == null || path2 == null) {
            System.out.println("警告: 无法解决冲突,路径不存在");
            return;
        }
        // 打印原始路径信息(调试用)
        System.out.println("[冲突解决debug] 冲突位置: " + conflictPosition);
        System.out.println("[冲突解决debug] AGV " + firstAgv + " 原始路径: " +
                         (path1.getCodeList() != null && !path1.getCodeList().isEmpty() ?
                          path1.getCodeList().get(0).getCode() + " -> " +
                          path1.getCodeList().get(path1.getCodeList().size() - 1).getCode() +
                          " (共" + path1.getCodeList().size() + "点)" : "空路径"));
        System.out.println("[冲突解决debug] AGV " + secondAgv + " 原始路径: " +
                         (path2.getCodeList() != null && !path2.getCodeList().isEmpty() ?
                          path2.getCodeList().get(0).getCode() + " -> " +
                          path2.getCodeList().get(path2.getCodeList().size() - 1).getCode() +
                          " (共" + path2.getCodeList().size() + "点)" : "空路径"));
        // 检查原始路径是否经过冲突位置
        if (path1.getCodeList() != null) {
            boolean path1HasConflictPos = path1.getCodeList().stream()
                    .anyMatch(code -> conflictPosition.equals(code.getCode()));
            System.out.println("[冲突解决debug] AGV " + firstAgv + " 路径是否经过冲突位置 " + conflictPosition + ": " + path1HasConflictPos);
        }
        if (path2.getCodeList() != null) {
            boolean path2HasConflictPos = path2.getCodeList().stream()
                    .anyMatch(code -> conflictPosition.equals(code.getCode()));
            System.out.println("[冲突解决debug] AGV " + secondAgv + " 路径是否经过冲突位置 " + conflictPosition + ": " + path2HasConflictPos);
        }
        // 判断哪个AGV有剩余路径
        AGVStatus agv1Status = agvStatusMap != null ? agvStatusMap.get(firstAgv) : null;
        AGVStatus agv2Status = agvStatusMap != null ? agvStatusMap.get(secondAgv) : null;
        boolean agv1HasRemainingPath = agv1Status != null && agv1Status.hasRemainingPath();
        boolean agv2HasRemainingPath = agv2Status != null && agv2Status.hasRemainingPath();
        // 确定需要等待的AGV
        String waitingAgv;
        PlannedPath waitingPath;
        AGVStatus waitingAgvStatus;
        if (agv1HasRemainingPath && !agv2HasRemainingPath) {
            // AGV1有剩余路径,AGV2是新路径 -> AGV2等待
            waitingAgv = secondAgv;
            waitingPath = path2;
            waitingAgvStatus = agv2Status;
            System.out.println("冲突解决: AGV " + firstAgv + " 有剩余路径继续执行,AGV " + secondAgv + " 新路径需要等待");
        } else if (!agv1HasRemainingPath && agv2HasRemainingPath) {
            // AGV1是新路径,AGV2有剩余路径 -> AGV1等待
            waitingAgv = firstAgv;
            waitingPath = path1;
            waitingAgvStatus = agv1Status;
            System.out.println("冲突解决: AGV " + secondAgv + " 有剩余路径继续执行,AGV " + firstAgv + " 新路径需要等待");
        } else if (agv1HasRemainingPath && agv2HasRemainingPath) {
            // 两个都有剩余路径(最好不出现这个情况)
            AGVPriority priority1 = evaluateAgvPriority(firstAgv, path1, executingTasks);
            AGVPriority priority2 = evaluateAgvPriority(secondAgv, path2, executingTasks);
            if (priority1.priorityScore >= priority2.priorityScore) {
                // AGV1优先级高,AGV2等待
                waitingAgv = secondAgv;
                waitingPath = path2;
                waitingAgvStatus = agv2Status;
                System.out.println("冲突解决: 两个都有剩余路径,AGV " + firstAgv + " 优先级高继续执行,AGV " + secondAgv + " 等待");
            } else {
                // AGV2优先级高,AGV1等待
                waitingAgv = firstAgv;
                waitingPath = path1;
                waitingAgvStatus = agv1Status;
                System.out.println("冲突解决: 两个都有剩余路径,AGV " + secondAgv + " 优先级高继续执行,AGV " + firstAgv + " 等待");
            }
        } else {
            // 两个都是新路径 -> 根据优先级决定
            AGVPriority priority1 = evaluateAgvPriority(firstAgv, path1, executingTasks);
            AGVPriority priority2 = evaluateAgvPriority(secondAgv, path2, executingTasks);
            if (priority1.priorityScore >= priority2.priorityScore) {
                waitingAgv = secondAgv;
                waitingPath = path2;
                waitingAgvStatus = agv2Status;
                System.out.println("冲突解决: 两个都是新路径,AGV " + firstAgv + " 优先级高继续执行,AGV " + secondAgv + " 等待");
            } else {
                waitingAgv = firstAgv;
                waitingPath = path1;
                waitingAgvStatus = agv1Status;
                System.out.println("冲突解决: 两个都是新路径,AGV " + secondAgv + " 优先级高继续执行,AGV " + firstAgv + " 等待");
            }
        }
        // 找到等待AGV的当前位置(路径起点)
        String currentPosition = null;
        if (waitingPath != null && !waitingPath.getCodeList().isEmpty()) {
            currentPosition = waitingPath.getCodeList().get(0).getCode();
        }
        if (currentPosition == null && waitingAgvStatus != null) {
            currentPosition = waitingAgvStatus.getPosition();
        }
        if (currentPosition == null || conflictPosition == null) {
            System.out.println("警告: 无法找到当前位置或冲突位置,跳过冲突解决");
            return;
        }
        // 检查等待AGV的路径是否经过冲突位置
        boolean waitingPathHasConflictPos = false;
        if (waitingPath != null && waitingPath.getCodeList() != null) {
            waitingPathHasConflictPos = waitingPath.getCodeList().stream()
                    .anyMatch(code -> conflictPosition.equals(code.getCode()));
        }
        if (!waitingPathHasConflictPos) {
            System.out.println("AGV " + waitingAgv + " 的路径不经过冲突位置 " + conflictPosition + ",跳过冲突解决");
            return;
        }
        String waitPosition = findWaitPositionOnOriginalPath(waitingPath, conflictPosition, waitingAgvStatus, overlappingPositions);
        boolean waitPositionOnOriginalPath = (waitPosition != null);
        if (waitPosition == null) {
            System.out.println("原始路径上没有合适的等待位置,尝试寻找其他位置");
            waitPosition = findSafeWaitingPosition(currentPosition, conflictPosition, waitingAgvStatus, overlappingPositions);
        }
        if (waitPosition == null) {
            System.out.println("警告: 无法找到安全等待位置,AGV " + waitingAgv + " 保持当前位置");
            // 如果找不到等待位置,至少截断路径,只保留到当前位置
            truncatePathToCurrentPosition(waitingPath, currentPosition);
            return;
        }
        if (waitPositionOnOriginalPath && waitingPath != null) {
            truncatePathToWaitPosition(waitingPath, waitPosition);
            System.out.println("AGV " + waitingAgv + " 路径已截断到等待位置 " + waitPosition + "(在原始路径上,距离冲突点 " + conflictPosition + " 至少5步)");
            return;
        }
        String originalSegId = waitingPath != null ? waitingPath.getSegId() : null;
        ExecutingTask waitingTask = null;
        if (executingTasks != null) {
            for (ExecutingTask task : executingTasks) {
                if (task.getAgvId().equals(waitingAgv)) {
                    waitingTask = task;
                    break;
                }
            }
        }
        // 规划到等待位置的路径
        PlannedPath newWaitPath = planPathToWaitPosition(waitingAgv, currentPosition, waitPosition,
                                                         waitingAgvStatus, originalSegId, waitingTask, unifiedTimestamp);
        if (newWaitPath != null) {
            pathsMap.put(waitingAgv, newWaitPath);
            System.out.println("AGV " + waitingAgv + " 已规划到等待位置 " + waitPosition + "(距离冲突点 " + conflictPosition + " 至少5步)");
        } else {
            System.out.println("警告: 无法规划到等待位置的路径,AGV " + waitingAgv + " 保持当前位置");
            truncatePathToCurrentPosition(waitingPath, currentPosition);
        }
    }
    /**
     * 找到距离冲突点安全距离的安全等待位置
     */
    private String findSafeWaitingPosition(String currentPosition, String conflictPosition,
                                          AGVStatus agvStatus, Set<String> overlappingPositions) {
        if (pathPlanner == null) {
            System.out.println("警告: 路径规划器未设置,无法查找等待位置");
            return null;
        }
        Map<String, Map<String, Integer>> pathMappingToUse = pathMapping;
        if (pathMappingToUse == null && pathPlanner != null) {
            pathMappingToUse = pathPlanner.getPathMapping();
        }
        if (pathMappingToUse == null) {
            System.out.println("警告: 路径映射表未设置,无法查找等待位置");
            return null;
        }
        CTUPhysicalConfig config = agvStatus != null && agvStatus.getPhysicalConfig() != null
                ? agvStatus.getPhysicalConfig()
                : new CTUPhysicalConfig();
        // 安全距离要求
        int minTargetDistanceSteps = 5;
        int[] conflictCoord = JsonUtils.getCoordinate(conflictPosition, pathMappingToUse);
        if (conflictCoord == null) {
            System.out.println("警告: 无法获取冲突位置的坐标");
            return null;
        }
        // 使用BFS搜索满足距离要求的位置
        Queue<String> queue = new LinkedList<>();
        Map<String, Integer> visited = new HashMap<>();
        Set<String> blockedPositions = new HashSet<>();
        blockedPositions.add(conflictPosition);
        if (overlappingPositions != null) {
            blockedPositions.addAll(overlappingPositions);
        }
        int[] currentCoord = JsonUtils.getCoordinate(currentPosition, pathMappingToUse);
        if (currentCoord == null) {
            System.out.println("警告: 无法获取当前位置的坐标");
            return null;
        }
        queue.offer(currentPosition);
        visited.put(currentPosition, 0);
        final int MAX_SEARCH_DEPTH = 20;
        List<CandidatePosition> candidates = new ArrayList<>();
        while (!queue.isEmpty()) {
            String pos = queue.poll();
            int depth = visited.get(pos);
            if (depth >= MAX_SEARCH_DEPTH) {
                break;
            }
            int[] posCoord = JsonUtils.getCoordinate(pos, pathMappingToUse);
            if (posCoord == null) {
                continue;
            }
            int distanceToConflict = Math.abs(posCoord[0] - conflictCoord[0]) +
                                    Math.abs(posCoord[1] - conflictCoord[1]);
            int distanceToCurrent = Math.abs(posCoord[0] - currentCoord[0]) +
                                   Math.abs(posCoord[1] - currentCoord[1]);
            if (distanceToConflict >= minTargetDistanceSteps) {
                if (!blockedPositions.contains(pos)) {
                    candidates.add(new CandidatePosition(pos, distanceToConflict, distanceToCurrent));
                }
            }
            List<Map<String, String>> neighbors = pathPlanner.getNeighbors(pos);
            if (neighbors != null) {
                for (Map<String, String> neighbor : neighbors) {
                    String neighborPos = neighbor.get("code");
                    if (neighborPos == null || visited.containsKey(neighborPos)) {
                        continue;
                    }
                    visited.put(neighborPos, depth + 1);
                    queue.offer(neighborPos);
                }
            }
        }
        if (!candidates.isEmpty()) {
            candidates.sort((c1, c2) -> {
                int compare = Integer.compare(c1.distanceToCurrent, c2.distanceToCurrent);
                if (compare != 0) {
                    return compare;
                }
                // 如果距离当前位置相同,选择距离冲突点更近的
                return Integer.compare(c1.distanceToConflict, c2.distanceToConflict);
            });
            CandidatePosition best = candidates.get(0);
            System.out.println("找到安全等待位置: " + best.position +
                             ",距离冲突点 " + best.distanceToConflict + " 步" +
                             ",距离当前位置 " + best.distanceToCurrent + " 步");
            return best.position;
        }
        System.out.println("警告: 无法找到满足距离要求的安全等待位置");
        return null;
    }
    /**
     * 在原始路径上找一个距离冲突点足够远的位置
     */
    private String findWaitPositionOnOriginalPath(PlannedPath originalPath, String conflictPosition,
                                                 AGVStatus agvStatus, Set<String> overlappingPositions) {
        if (originalPath == null || originalPath.getCodeList() == null || originalPath.getCodeList().isEmpty()) {
            return null;
        }
        Map<String, Map<String, Integer>> pathMappingToUse = pathMapping;
        if (pathMappingToUse == null && pathPlanner != null) {
            pathMappingToUse = pathPlanner.getPathMapping();
        }
        if (pathMappingToUse == null) {
            return null;
        }
        int[] conflictCoord = JsonUtils.getCoordinate(conflictPosition, pathMappingToUse);
        if (conflictCoord == null) {
            return null;
        }
        // 安全距离要求:距离冲突点至少5步
        int minTargetDistanceSteps = 5;
        List<PathCode> codeList = originalPath.getCodeList();
        List<CandidatePosition> candidates = new ArrayList<>();
        int conflictIndex = -1;
        for (int i = 0; i < codeList.size(); i++) {
            if (conflictPosition.equals(codeList.get(i).getCode())) {
                conflictIndex = i;
                break;
            }
        }
        if (conflictIndex < 0) {
            System.out.println("[调试] 原始路径中未找到冲突位置 " + conflictPosition);
            return null;
        }
        int checkedCount = 0;
        int blockedCount = 0;
        int tooCloseCount = 0;
        for (int i = 0; i < conflictIndex; i++) {
            String pos = codeList.get(i).getCode();
            checkedCount++;
            if (overlappingPositions != null && overlappingPositions.contains(pos)) {
                blockedCount++;
                continue;
            }
            int[] posCoord = JsonUtils.getCoordinate(pos, pathMappingToUse);
            if (posCoord == null) {
                continue;
            }
            int distanceToConflict = Math.abs(posCoord[0] - conflictCoord[0]) +
                                    Math.abs(posCoord[1] - conflictCoord[1]);
            int distanceToStart = i;
            if (distanceToConflict >= minTargetDistanceSteps) {
                candidates.add(new CandidatePosition(pos, distanceToConflict, distanceToStart));
            } else {
                tooCloseCount++;
            }
        }
        System.out.println("[调试] 原始路径检查: 冲突位置=" + conflictPosition +
                         ", 索引=" + conflictIndex +
                         ", 检查了" + checkedCount + "个点, " +
                         "重合位置=" + blockedCount + ", " +
                         "距离太近=" + tooCloseCount + ", " +
                         "候选位置=" + candidates.size());
        if (!candidates.isEmpty()) {
            candidates.sort((c1, c2) -> {
                int compare = Integer.compare(c1.distanceToConflict, c2.distanceToConflict);
                if (compare != 0) {
                    return compare;
                }
                return Integer.compare(c2.distanceToCurrent, c1.distanceToCurrent);
            });
            CandidatePosition best = candidates.get(0);
            System.out.println("在原始路径上找到等待位置: " + best.position +
                             ",距离冲突点 " + best.distanceToConflict + " 步" +
                             ",在路径中的位置: 第" + (best.distanceToCurrent + 1) + "个点");
            return best.position;
        }
        System.out.println("[调试] 原始路径上没有找到合适的等待位置(距离冲突点至少5步)");
        return null;
    }
    /**
     * 候选位置内部类
     */
    private static class CandidatePosition {
        final String position;
        final int distanceToConflict;
        final int distanceToCurrent;
        CandidatePosition(String position, int distanceToConflict, int distanceToCurrent) {
            this.position = position;
            this.distanceToConflict = distanceToConflict;
            this.distanceToCurrent = distanceToCurrent;
        }
    }
    /**
     * 规划到等待位置的路径
     */
    private PlannedPath planPathToWaitPosition(String agvId, String currentPosition,
                                               String waitPosition, AGVStatus agvStatus,
                                               String originalSegId, ExecutingTask task,
                                               long unifiedTimestamp) {
        if (pathPlanner == null) {
            return null;
        }
        CTUPhysicalConfig config = agvStatus != null && agvStatus.getPhysicalConfig() != null
                ? agvStatus.getPhysicalConfig()
                : new CTUPhysicalConfig();
        try {
            PlannedPath path = pathPlanner.planPath(currentPosition, waitPosition);
            if (path != null) {
                path.setAgvId(agvId);
                String segId;
                if (originalSegId != null && !originalSegId.isEmpty()) {
                    segId = originalSegId;
                } else if (task != null && task.getTaskId() != null) {
                    segId = task.getTaskId() + "_" + agvId + "_" + (task.getTaskType() != null ? task.getTaskType() : "waiting");
                } else {
                    segId = "UNKNOWN_" + agvId + "_waiting";
                    System.out.println("警告: AGV " + agvId + " 无法获取任务信息,使用默认segId: " + segId);
                }
                path.setSegId(segId);
                // 使用统一时间戳(转换为毫秒)
                long startTimeMs = unifiedTimestamp * 1000;
                if (timeCalculator != null && path.getCodeList() != null) {
                    timeCalculator.calculatePathTiming(path, startTimeMs, config, 0.0);
                }
                if (!path.getCodeList().isEmpty()) {
                    PathCode lastCode = path.getCodeList().get(path.getCodeList().size() - 1);
                    lastCode.setTargetPoint(true);
                    lastCode.setActionType(null);
                    lastCode.setPosType(null);
                }
                return path;
            }
        } catch (Exception e) {
            System.out.println("规划到等待位置的路径失败: " + e.getMessage());
        }
        return null;
    }
    /**
     * 截断路径到等待位置
     *
     * @param path 路径
     * @param waitPosition 等待位置
     */
    private void truncatePathToWaitPosition(PlannedPath path, String waitPosition) {
        if (path == null || path.getCodeList() == null || path.getCodeList().isEmpty()) {
            return;
        }
        List<PathCode> codeList = path.getCodeList();
        List<PathCode> truncatedList = new ArrayList<>();
        int waitIndex = -1;
        for (int i = 0; i < codeList.size(); i++) {
            if (codeList.get(i).getCode().equals(waitPosition)) {
                waitIndex = i;
                break;
            }
        }
        if (waitIndex >= 0) {
            truncatedList.addAll(codeList.subList(0, waitIndex + 1));
            if (!truncatedList.isEmpty()) {
                PathCode lastCode = truncatedList.get(truncatedList.size() - 1);
                lastCode.setTargetPoint(true);
                lastCode.setActionType(null);
                lastCode.setPosType(null);
            }
            path.setCodeList(truncatedList);
            System.out.println("路径已截断到等待位置 " + waitPosition);
        }
    }
    /**
     * 截断路径到当前位置(
     */
    private void truncatePathToCurrentPosition(PlannedPath path, String currentPosition) {
        if (path == null || path.getCodeList() == null || path.getCodeList().isEmpty()) {
            return;
        }
        List<PathCode> codeList = path.getCodeList();
        List<PathCode> truncatedList = new ArrayList<>();
        int currentIndex = -1;
        for (int i = 0; i < codeList.size(); i++) {
            if (codeList.get(i).getCode().equals(currentPosition)) {
                currentIndex = i;
                break;
            }
        }
        if (currentIndex >= 0) {
            truncatedList.addAll(codeList.subList(0, currentIndex + 1));
            if (!truncatedList.isEmpty()) {
                PathCode lastCode = truncatedList.get(truncatedList.size() - 1);
                lastCode.setTargetPoint(true);
                lastCode.setActionType(null);
                lastCode.setPosType(null);
            }
            path.setCodeList(truncatedList);
            System.out.println("路径已截断到当前位置 " + currentPosition);
        }
    }
    /**
     * 评估AGV优先级
     *
     * @param agvId          AGV编号
     * @param path           路径
@@ -257,7 +899,7 @@
    }
    /**
     * 为路径添加延迟(增强版,正确重计算时间窗)
     * 为路径添加延迟
     *
     * @param path       路径
     * @param timeStep   延迟开始的时间步