package com.algo.service; import com.algo.model.Conflict; import com.algo.model.ExecutingTask; import com.algo.model.PathCode; import com.algo.model.PlannedPath; import java.util.*; /** * 碰撞解决器 * 用于解决AGV路径之间的冲突 */ public class CollisionResolver { /** * 碰撞检测器 */ private final CollisionDetector collisionDetector; /** * 构造函数 * * @param collisionDetector 碰撞检测器 */ public CollisionResolver(CollisionDetector collisionDetector) { this.collisionDetector = collisionDetector; } /** * 解决路径冲突 * * @param plannedPaths 规划路径列表 * @param conflicts 冲突列表 * @param executingTasks 执行中任务列表 * @return 解决冲突后的路径列表 */ public List resolveConflicts(List plannedPaths, List conflicts, List executingTasks) { if (conflicts == null || conflicts.isEmpty()) { return plannedPaths; } System.out.println("开始解决 " + conflicts.size() + " 个路径冲突"); // 构建路径字典便于快速访问 Map pathsMap = new HashMap<>(); for (PlannedPath path : plannedPaths) { pathsMap.put(path.getAgvId(), path); } // 按时间步排序处理冲突 List sortedConflicts = new ArrayList<>(conflicts); sortedConflicts.sort(Comparator.comparingInt(Conflict::getTimeStep)); // 逐个解决冲突 for (Conflict conflict : sortedConflicts) { resolveSingleConflict(pathsMap, conflict, executingTasks); } List resolvedPaths = new ArrayList<>(pathsMap.values()); // 验证解决结果 List remainingConflicts = collisionDetector.detectConflicts(resolvedPaths); System.out.println("冲突解决完成,剩余冲突数量: " + remainingConflicts.size()); return resolvedPaths; } /** * 解决单个冲突 * * @param pathsMap 路径映射 * @param conflict 冲突 * @param executingTasks 执行中任务列表 */ private void resolveSingleConflict(Map pathsMap, Conflict conflict, List executingTasks) { String conflictType = conflict.getType(); switch (conflictType) { case "vertex": resolveVertexConflict(pathsMap, conflict, executingTasks); break; case "edge": resolveEdgeConflict(pathsMap, conflict, executingTasks); break; case "follow": resolveFollowingConflict(pathsMap, conflict, executingTasks); break; default: System.out.println("未知冲突类型: " + conflictType); } } /** * 解决顶点冲突 * * @param pathsMap 路径映射 * @param conflict 冲突 * @param executingTasks 执行中任务列表 */ private void resolveVertexConflict(Map pathsMap, Conflict conflict, List executingTasks) { String agv1 = conflict.getAgv1(); String agv2 = conflict.getAgv2(); int timeStep = conflict.getTimeStep(); // 评估AGV优先级 AGVPriority priority1 = evaluateAgvPriority(agv1, pathsMap.get(agv1), executingTasks); AGVPriority priority2 = evaluateAgvPriority(agv2, pathsMap.get(agv2), executingTasks); // 优先级低的AGV进行延迟 if (priority1.priorityScore >= priority2.priorityScore) { // agv2优先级低,延迟agv2 addDelayToPath(pathsMap.get(agv2), timeStep, 1); System.out.println("为解决顶点冲突,AGV " + agv2 + " 在时间步 " + timeStep + " 延迟1步"); } else { // agv1优先级低,延迟agv1 addDelayToPath(pathsMap.get(agv1), timeStep, 1); System.out.println("为解决顶点冲突,AGV " + agv1 + " 在时间步 " + timeStep + " 延迟1步"); } } /** * 解决边冲突 * * @param pathsMap 路径映射 * @param conflict 冲突 * @param executingTasks 执行中任务列表 */ private void resolveEdgeConflict(Map pathsMap, Conflict conflict, List executingTasks) { String agv1 = conflict.getAgv1(); String agv2 = conflict.getAgv2(); int timeStep = conflict.getTimeStep(); // 评估AGV优先级 AGVPriority priority1 = evaluateAgvPriority(agv1, pathsMap.get(agv1), executingTasks); AGVPriority priority2 = evaluateAgvPriority(agv2, pathsMap.get(agv2), executingTasks); // 优先级低的AGV进行延迟 if (priority1.priorityScore >= priority2.priorityScore) { // agv2优先级低,延迟agv2 addDelayToPath(pathsMap.get(agv2), timeStep, 2); System.out.println("为解决边冲突,AGV " + agv2 + " 在时间步 " + timeStep + " 延迟2步"); } else { // agv1优先级低,延迟agv1 addDelayToPath(pathsMap.get(agv1), timeStep, 2); System.out.println("为解决边冲突,AGV " + agv1 + " 在时间步 " + timeStep + " 延迟2步"); } } /** * 解决跟随冲突 * * @param pathsMap 路径映射 * @param conflict 冲突 * @param executingTasks 执行中任务列表 */ private void resolveFollowingConflict(Map pathsMap, Conflict conflict, List executingTasks) { String agv1 = conflict.getAgv1(); String agv2 = conflict.getAgv2(); int timeStep = conflict.getTimeStep(); // 评估AGV优先级 AGVPriority priority1 = evaluateAgvPriority(agv1, pathsMap.get(agv1), executingTasks); AGVPriority priority2 = evaluateAgvPriority(agv2, pathsMap.get(agv2), executingTasks); // 优先级低的AGV进行延迟 if (priority1.priorityScore >= priority2.priorityScore) { // agv2优先级低,延迟agv2 addDelayToPath(pathsMap.get(agv2), timeStep, 1); System.out.println("为解决跟随冲突,AGV " + agv2 + " 在时间步 " + timeStep + " 延迟1步"); } else { // agv1优先级低,延迟agv1 addDelayToPath(pathsMap.get(agv1), timeStep, 1); System.out.println("为解决跟随冲突,AGV " + agv1 + " 在时间步 " + timeStep + " 延迟1步"); } } /** * 评估AGV优先级 - 优化版本,只保留必要字段 * * @param agvId AGV编号 * @param path 路径 * @param executingTasks 执行中任务列表 * @return AGV优先级信息 */ private AGVPriority evaluateAgvPriority(String agvId, PlannedPath path, List executingTasks) { // 查找对应的执行任务 ExecutingTask task = null; for (ExecutingTask et : executingTasks) { if (et.getAgvId().equals(agvId)) { task = et; break; } } double priorityScore = 0.0; String explanation = "默认优先级"; if (task != null) { String taskStatus = task.getTaskType(); int taskPriority = task.getPriority(); // 基于任务类型的优先级评分 switch (taskStatus) { case "delivery": priorityScore += 50; // 送货任务优先级高 explanation = "送货任务 - 高优先级"; break; case "pickup": priorityScore += 30; // 取货任务中等优先级 explanation = "取货任务 - 中等优先级"; break; case "charging": priorityScore += 20; // 充电任务低优先级 explanation = "充电任务 - 低优先级"; break; default: priorityScore += 10; // 其他任务最低优先级 explanation = "其他任务 - 最低优先级"; } // 任务优先级加成 priorityScore += taskPriority * 10; // 路径长度因子(路径越短优先级越高) if (path != null && path.getCodeList() != null) { double pathLengthFactor = Math.max(0, 50 - path.getCodeList().size()); priorityScore += pathLengthFactor; } } return new AGVPriority(agvId, priorityScore, explanation); } /** * 为路径添加延迟 * * @param path 路径 * @param timeStep 延迟开始的时间步 * @param delaySteps 延迟步数 */ private void addDelayToPath(PlannedPath path, int timeStep, int delaySteps) { if (path == null || path.getCodeList() == null || path.getCodeList().isEmpty()) { return; } List codeList = path.getCodeList(); // 确保时间步在有效范围内 if (timeStep < 0 || timeStep >= codeList.size()) { return; } // 获取延迟位置的路径代码 PathCode delayCode = codeList.get(timeStep); // 创建延迟步骤 List delaySteps_list = new ArrayList<>(); for (int i = 0; i < delaySteps; i++) { PathCode waitCode = new PathCode(delayCode.getCode(), delayCode.getDirection()); waitCode.setActionType(delayCode.getActionType()); waitCode.setTaskId(delayCode.getTaskId()); waitCode.setPosType(delayCode.getPosType()); waitCode.setLev(delayCode.getLev()); waitCode.setTargetPoint(false); // 等待步骤不是目标点 delaySteps_list.add(waitCode); } // 插入延迟步骤 codeList.addAll(timeStep, delaySteps_list); // 更新路径 path.setCodeList(codeList); } /** * AGV优先级评估结果内部类 - 优化版本,只保留必要字段 */ private static class AGVPriority { final String agvId; final double priorityScore; final String explanation; public AGVPriority(String agvId, double priorityScore, String explanation) { this.agvId = agvId; this.priorityScore = priorityScore; this.explanation = explanation; } @Override public String toString() { return String.format("AGV %s: 优先级=%.1f, 说明=%s", agvId, priorityScore, explanation); } } }