7.1 KiB
自动匹配 Cesium 巡航车道中心:技术设计
设计目标
巡航路线以 osm2streets internal road topology 与已渲染的 Driving lane polygon 为几何事实源。道路区间直接使用 polygon 的中轴,不再对 OSM way 中心线施加固定米数偏移;OSM 只提供原始标签和转向语义,不再作为最终路口拓扑。
数据流
network.json ──▶ internal road/intersection directed graph
OSM XML ──▶ turn:lanes semantics
│
lane_polygons.geojson ──▶ validated Driving lane centerlines
│
▼
maneuver-aware lane selection
│
▼
internal road lane sections + surface-constrained junction curves
│
▼
vehicle-route.json + diagnostics
scripts/build-area.js 在 preview stage 调用 buildVehicleRoute(osmPath, lanePolygonsPath)。lane_polygons.geojson 同时写入 preview manifest inputs,scripts/lib/area-diagnostics.js 使用既有 SHA-256 freshness 检查自动识别过期路线。
模块边界
scripts/lib/lane-geometry.js
新增纯几何共享模块,承载:
- 校验 Driving
Polygonring; - 通过 polygon 两侧对应顶点中点提取 lane centerline;
- 米制距离、方向对齐、端点排序和 polyline 拼接所需的无副作用 helper。
scripts/lib/turn-lane-arrows.js 改为导入共享 laneCenterline(),确保箭头和巡航对 osm2streets polygon 顺序使用同一契约。
scripts/lib/vehicle-route.js
保留现有 OSM 路线拓扑搜索,替换 LANE_OFFSET_METERS / offsetClosedRouteRight() 路径:
- 加载并严格校验
lane_polygons.geojson为 FeatureCollection。 - 按
road、laneindex和direction=Fwd|Back建立 Driving lane 索引;osm_way_ids仅用于追溯 OSM 标签。 - 对每条 directed edge,使用实际横向位置按行驶方向排列同向车道;renderer
index只作为稳定 tie-breaker,不单独决定车道顺序。 - 将 edge 末端的 maneuver 与
turn:lanes:forward|backward对齐。左转/掉头选最左兼容车道,右转选最右兼容车道,直行选最右兼容车道;无显式 lane restriction 时按相同位置规则选择。 - 每个 edge 对应一个 osm2streets internal road;禁止把同一 OSM way 下多个 internal road 当作无语义 fragment 直接拼接。
- 车道中轴端点之间使用 tangent Bezier / U-turn 连接,并绑定共同的 internal intersection;全部采样点必须落在对应
intersection_surface内或边界容差内。 - 任一 edge 无法可靠匹配时丢弃该候选 route;继续搜索其他候选,最多输出 5 条。
输出契约
保留顶层 routes、兼容别名 segments、loop、speedMetersPerSecond,以及每条路线的 coordinates、centerlineCoordinates、edgeIds、maneuvers 和 lengthMeters。
每条路线新增 laneSegments,每段至少记录:
edgeId、osmWayId、direction;laneIndex、widthMeters、centerOffsetMeters;maneuver、source="lane_polygon_centerline";- 参与拼接的 polygon/road 标识。
顶层新增 diagnostics,按稳定 reason code 汇总被拒绝的 edge/route,例如 missing_lane_polygon、invalid_lane_polygon、ambiguous_lane_order、no_compatible_turn_lane 和 disconnected_lane_fragments。固定 laneOffsetMeters 不再作为几何输入;为避免伪造单值,不以平均偏移替代逐段事实。
错误与降级语义
- 整个 lane polygon 文件缺失、JSON 无法解析或不是 FeatureCollection:preview stage 在写产物前失败。
- 单个 polygon 无效:记录诊断,该 polygon 不参与匹配。
- directed edge 缺少唯一可信车道:候选 route 被拒绝,生成器继续选择其他 route。
- 所有候选都被拒绝:生成合法的空
routes和完整诊断;Cesium 场景仍可加载,但不显示巡航车辆。 - 禁止回退到固定
1.3 m、固定1.5 m或默认 lane width。
兼容性
- Blender scene 经纬度投影改为 WGS84 ECEF→ENU,与 Cesium
eastNorthUpToFixedFrame的锚点坐标系一致;这是 route 与最终 GLB 道路重合的必要 跨层契约。 segments继续与routes引用相同数组。- Cesium runtime 当前只消费
coordinates等既有字段,无需理解laneSegments即可运行。 - preview manifest 新增 lane polygon input 后,旧 manifest 会被诊断为缺少记录并要求重建,这是预期迁移行为。
验证策略
- 纯几何测试:四边形、曲线 polygon、反向 geometry、坏 ring。
- 路线 fixture:不同宽度、双向/单向、多车道和转向车道选择。
- 精度断言:路线道路区间采样点到 polygon 中轴距离不超过
0.10 m。 - 连续性断言:车道变化和路口连接处没有由数据拼接产生的异常横跳。
- 集成验证:目标区域重跑 preview,检查 route JSON diagnostics、manifest freshness、区域质量门和 Cesium 实际显示。
- 端到端视觉验证:重跑
blender,cesium,preview,对最终画面做道路横截面检查;不能用 route 与 lane polygon 的厘米级一致性代替 GLB/Entity 对齐验证。
Bug Analysis:GLB 与巡航路线随距离漂移
1. Root Cause Category
- Category:B - Cross-Layer Contract;D - Test Coverage Gap。
- Specific Cause:Blender 使用固定米/度的平面近似,Cesium 使用 WGS84 椭球 ENU; 两层没有共享坐标转换契约。
2. Why Fixes Failed
- 固定车道偏移:只处理症状,且假定所有车道宽度相同。
- 从 Driving polygon 重建中轴:解决了车道宽度与 lane 选择,但只证明 GeoJSON 内部正确。
- 路口切线连接:改善了 connector,却没有解释直线路段整套坐标同向平移。
3. Prevention Mechanisms
| Priority | Mechanism | Specific Action | Status |
|---|---|---|---|
| P0 | Architecture | Projector 使用 WGS84 ECEF→ENU,与 Cesium 锚点一致 |
DONE |
| P0 | Test Coverage | 测试 WGS84 局部经纬度比例与 ENU 方向 | DONE |
| P1 | Documentation | 在 Blender、preview 与 cross-layer spec 固化契约 | DONE |
| P1 | Integration | 坐标变更后强制重跑 blender,cesium,preview 并视觉核对 |
DONE |
4. Systematic Expansion
- Similar Issues:交通信号、语义模型、route polyline 等所有叠加在 GLB 上的 Cesium Entity 都依赖同一契约。
- Design Improvement:坐标转换只有
Projector一个 Blender 事实源。 - Process Improvement:跨运行时几何必须验证最终组合画面,不能停在单层数值测试。
5. Knowledge Capture
- 更新 Blender asset generation spec。
- 更新 preview vehicle route spec。
- 更新 cross-layer thinking guide。
- 增加
ProjectorTestWGS84 断言。
回滚
代码回滚只涉及 preview 路线生成和共享 JS helper;重跑 preview 即可恢复旧路线产物,不需要重建 Blender/GLB。用户已有区域配置修改保持不动。