CollisionAvoidanceSystem/doc/design/road_network_design.md

6.5 KiB
Raw Blame History

设计方案:机场道路网络配置集成

1. 引言

本文档描述了将机场道路网络配置信息(定义在 src/main/resources/config/airport_roads.yaml 文件中)加载到碰撞避免系统中,并提供统一接口供其他模块使用的设计方案。目标是实现配置的结构化加载、地理空间表示和便捷查询。

2. 设计目标

  • 自动加载: 在应用程序启动时自动加载并解析 airport_roads.yaml 文件。
  • 类型安全: 将 YAML 配置映射到强类型的 Java 对象。
  • 空间表示: 使用标准的地理空间库 (JTS) 将道路中心线和边界表示为内存中的几何对象。
  • 统一访问: 提供一个中心服务 (RoadNetworkService) 来封装道路数据的访问逻辑。
  • 高效查询: 支持根据 ID 获取道路信息,以及基于地理位置(点)查询所在道路及其属性(如限速)。
  • 模块解耦: 其他模块(如数据处理)通过依赖注入使用服务,无需关心配置文件的具体加载和解析细节。

3. 核心组件

  1. 配置属性 POJOs: 位于 com.dongni.collisionavoidance.config.properties 包下,用于映射 airport_roads.yaml 文件结构的 Java 类 (如 AirportRoadsProperties, RoadProperties, GeometryProperties, DimensionValue)。
  2. 配置加载器: 位于 com.dongni.collisionavoidance.config 包下的 Spring 配置类 (如 RoadNetworkConfig) 和辅助类 (YamlPropertySourceFactory),负责指定加载 airport_roads.yaml 文件并启用属性绑定到 POJOs。
  3. 运行时数据模型 (RoadInfo): 位于 com.dongni.collisionavoidance.roads.model 包下包含道路静态属性ID, name, limits 等,已进行单位转换)以及预处理的 JTS 地理空间对象(LineString 类型的 centerlinePolygon 类型的 boundary)。
  4. 道路网络服务 (RoadNetworkService): 位于 com.dongni.collisionavoidance.roads.service 包下的 Spring Service Bean负责初始化和提供道路数据查询。

4. 依赖库

  • Java Topology Suite (JTS): org.locationtech.jts:jts-core:1.19.0 (或最新版)
  • SnakeYAML: (通常由 Spring Boot 包含)
  • Lombok: (可选)

5. 实现细节

5.1 配置加载

  • 使用 @PropertySource 注解配合自定义的 YamlPropertySourceFactory 来指定加载 classpath:config/airport_roads.yaml
  • 使用 @EnableConfigurationProperties 将加载的配置绑定到 AirportRoadsProperties POJO 类及其嵌套类。
  • AirportRoadsProperties 类使用 @ConfigurationProperties (无前缀) 注解。
  • POJO 类结构需与 airport_roads.yaml 文件结构精确匹配(字段名、数据类型、列表、嵌套对象)。

5.2 运行时数据模型 (RoadInfo)

此类应设计为不可变对象 (e.g., 使用 Lombok @Value@Builder),包含以下关键信息:

  • id: String
  • name: String
  • speedLimitMetersPerSecond: Double (单位统一为 m/s)
  • directionality: Enum (RoadDirectionality)
  • heightLimitMeters: Double (单位统一为 m)
  • widthLimitMeters: Double (单位统一为 m)
  • prohibited: boolean
  • centerline: org.locationtech.jts.geom.LineString (JTS 对象)
  • boundary: org.locationtech.jts.geom.Polygon (JTS 对象)
  • relatedZones: List<String>

5.3 道路网络服务 (RoadNetworkService)

  • 职责:
    • 注入 AirportRoadsProperties
    • 在初始化阶段 (@PostConstruct) 执行以下操作:
      1. 遍历从配置加载的 RoadProperties 列表。
      2. 对每个 RoadProperties
        • 使用 JTS GeometryFactorycoordinates 列表转换为 LineString 对象 (centerline)。
        • 根据 width 属性,使用 LineString.buffer() 方法计算道路边界 Polygon 对象 (boundary)。(注意:需要处理米到地理坐标度数的近似转换,或采用投影坐标系进行精确缓冲)。
        • 进行必要的单位转换(如速度 km/h -> m/s长度单位 -> m
        • 解析方向性、禁止通行等属性。
        • 创建 RoadInfo 实例。
      3. 将所有创建的 RoadInfo 实例存储在内存中的 Map 中 (e.g., Map<String, RoadInfo>),以 roadId 为键。
      4. (推荐) 将所有 RoadInfoboundary (Polygon) 添加到 JTS 空间索引 (如 STRtree) 中,以优化空间查询。
    • 提供公共方法用于查询道路信息。
  • 主要接口方法签名示例:
    public Optional<RoadInfo> getRoadById(String roadId);
    public List<RoadInfo> findRoadsContainingPoint(GeoPosition geoPosition);
    public Optional<RoadInfo> findDominantRoadAt(GeoPosition geoPosition); // 处理点在多条路重叠区域的情况
    public Optional<Double> getSpeedLimitMetersPerSecondAt(GeoPosition geoPosition);
    // ... 其他必要的查询方法 ...
    
  • 内部逻辑:
    • findRoadsContainingPoint: 使用空间索引 (STRtree.query()) 粗筛候选道路,然后使用 Polygon.covers(Point) 进行精确判断。
    • 包含健壮的单位转换和错误处理逻辑。

5.4 在其他模块中使用

  • 需要访问道路信息的模块(如 CollisionDetectionService)通过 Spring 的依赖注入 (@Autowired 或构造函数注入) 获取 RoadNetworkService 实例。
  • 调用 RoadNetworkService 提供的公共方法获取道路属性或执行空间查询。

6. 目录结构影响

引入以下新的包和类:

src/main/java/com/dongni/collisionavoidance/
├── config/
│   ├── properties/             # 新包:存放配置属性 POJOs
│   │   ├── AirportRoadsProperties.java
│   │   ├── RoadProperties.java
│   │   ├── GeometryProperties.java
│   │   └── DimensionValue.java
│   ├── RoadNetworkConfig.java    # 新类:加载道路配置
│   └── YamlPropertySourceFactory.java # 新类(如果不存在)
├── roads/                      # 新包:道路网络相关
│   ├── model/                  # 新包:运行时道路模型
│   │   ├── RoadInfo.java
│   │   └── RoadDirectionality.java
│   └── service/                # 新包:道路服务
│       └── RoadNetworkService.java

7. 未来考虑

  • 精确缓冲: 实现基于 UTM 或其他合适投影坐标系的缓冲计算。
  • 复杂交叉口: 可能需要更高级的拓扑模型或规则处理。
  • 动态更新: 考虑配置热加载机制。
  • 单位转换: 实现更健壮的单位转换库。