| | |
| | | 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.*; |
| | | |
| | | /** |
| | |
| | | /** |
| | | * 最大搜索深度 |
| | | */ |
| | | private final int maxSearchDepth = 15000; |
| | | private final int maxSearchDepth = 50000; |
| | | |
| | | /** |
| | | * 距离缓存 |
| | |
| | | */ |
| | | 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(); |
| | |
| | | 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; |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | 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 |
| | |
| | | * @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); |
| | |
| | | // 时空A*算法实现 |
| | | PlannedPath result = spaceTimeAStarSearch( |
| | | startCode, endCode, startCoord, endCoord, |
| | | constraints, spaceTimeOccupancyMap, physicalConfig |
| | | constraints, spaceTimeOccupancyMap, physicalConfig, startTimeMs |
| | | ); |
| | | |
| | | if (result != null) { |
| | |
| | | * @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<>( |
| | |
| | | Map<String, Double> gScores = new HashMap<>(); |
| | | Map<String, SpaceTimeAStarNode> cameFrom = new HashMap<>(); |
| | | |
| | | // 起始时间 |
| | | long startTime = System.currentTimeMillis(); |
| | | long startTime = startTimeMs; |
| | | |
| | | // 初始化起始节点 |
| | | SpaceTimeAStarNode startNode = new SpaceTimeAStarNode( |