Files
FT546-WCS/docs/superpowers/specs/2026-08-06-javaTest-bounded-conflict-aware-routing-design.md

347 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# javaTest 有界绕行与冲突感知路径规划设计
**日期:** 2026-08-06
**状态:** 已完成方案讨论,等待书面确认
**适用范围:** `javaTest` 历史任务中心调度仿真与调度路径审计页面
## 1. 背景
当前 `javaTest` 使用 `GridPathPlanner` 在完整地图上执行 BFS,得到边数最少且结果确定的路径。
历史 `path_info` 只用于结果对照,不参与重新规划。240 条历史任务的初步结果为 137 条路径序列
发生变化,但该数字不能直接证明路径优化有效:
- 130 条历史路径的首尾与解析后的物理业务端点不一致;
- 2 条历史路径含未知或非邻接段;
- 剩余 108 条可公平比较的任务中,103 条完全相同,4 条路线不同但边数相同,只有 1 条更短;
- 可比较任务的平均边数仅从 10.14 降到 10.12。
因此,本设计不再用“路径是否不同”或受故障影响的实际完成时间证明优化效果,而是在最短物理
距离附近选择交通冲突更少、路线重叠更少、转弯更少的候选路线,并提供完整、可解释的决策证据。
## 2. 目标与非目标
### 2.1 目标
1. 接近路径和服务路径都允许在最短物理距离 110% 范围内绕行。
2. 只使用当前活动任务、节点占用、边预约和走廊方向判断交通风险,不使用历史热度。
3. 按固定业务优先级比较候选路线,不使用难以解释和调参的加权总分。
4. 同一交通资源连续造成 3 个调度周期 HOLD 后,从车辆当前位置重新规划剩余路线。
5. 路线切换必须保持当前占用和预约安全,不能因重规划产生资源空窗。
6. 将路线质量、交通执行和故障恢复分开统计。
7. 相同地图、输入和交通快照必须产生相同结果。
### 2.2 非目标
1. 不用实际行驶时间或最终任务完成时间给路径质量打分。
2. 不使用历史 `path_info` 约束新路线。
3. 不在本次改造中改变现有车辆资格、低电量和车辆选择业务规则。
4. 不把 PLC 失败、断线、低电量或车辆故障当成交通 HOLD。
5. 不接入生产数据库、真实 PLC、真实 WMS 或实时交通服务。
## 3. 业务术语
- **接近路径:** 重新选中的车辆当前位置到任务物理起点 A 的路线。
- **服务路径:** 任务物理起点 A 到物理终点 B 的路线。
- **基准最短距离 D:** 在永久禁行条件下,起终点间可达路线的最小坐标距离。
- **有界候选路线:** 物理距离不超过 `D * 1.10` 的无环路线。
- **交通快照:** 某次调度决策时的车辆占用节点、边预约、走廊方向和其他活动路线。
- **交通 HOLD:** 下一步因节点、边、对向或走廊方向冲突而暂时不能安全推进。
- **相同阻塞:** 任务、车辆、阻塞资源标识和交通 HOLD 原因均相同。
## 4. 总体架构
### 4.1 `RouteCandidatePlanner`
职责:根据完整 `GridMap`、起点、终点和永久禁行资源生成确定性的有界候选路线。
输入:
- `GridMap`
- 起点、终点
- 永久禁行节点或边
- `RoutePlanningPolicy`
输出:
- 基准最短距离
- 最短路线
- 不超过 110% 的候选路线
- 是否命中候选数量上限
该模块不读取车辆状态、交通预约、历史路径或任务优先级,只负责生成地图上合法的路线候选。
### 4.2 `RouteQualityEvaluator`
职责:使用同一时刻的 `TrafficRouteSnapshot` 对候选路线进行可解释的业务排序。
输入:候选路线、交通快照、当前任务和车辆。
输出:每条路线的 `RouteQuality` 以及最终 `RoutePlanDecision`。
### 4.3 `TrafficRouteSnapshot`
职责:为一次规划决策提供不可变交通证据,避免候选路线使用不同时间点的数据。
包含:
- 车辆当前占用节点及归属车辆;
- 已预约的有向边、方向和归属任务;
- 走廊方向预约及归属任务;
- 其他活动任务尚未完成的剩余路线;
- 当前任务和车辆自身已经合法持有的资源。
### 4.4 `HoldReroutePolicy`
职责:只累计交通 HOLD,并在同一阻塞连续出现 3 个调度周期时触发重规划。
### 4.5 `RouteDecisionEvidence`
职责:保存候选生成、路线评分、HOLD 触发、资源替换和最终选择的可审计证据,供 JSON 报告和
HTML 页面展示。
## 5. 物理距离与候选路线
### 5.1 边距离
当前完整地图共有 8 层、1239 条边,不存在跨层边。相邻站点边距离按地图坐标的欧氏距离计算:
```text
edgeDistance = sqrt((to.x - from.x)^2 + (to.y - from.y)^2)
pathDistance = sum(edgeDistance)
```
距离单位是地图坐标单位,不宣称为米。未来如增加跨层边,必须由地图元数据显式提供该边距离;
不得根据楼层编号虚构垂直距离。
### 5.2 候选生成算法
采用确定性的 K 最短无环路径方案:
1. 使用 Dijkstra 计算基准最短路线和距离 `D`;
2. 按距离从小到大生成无环候选路线;
3. 下一候选距离超过 `D * 1.10` 时停止;
4. 最多保留 32 条候选;
5. 距离相同时按完整站点序列排序;
6. 未知节点、永久封闭道路和静态禁行资源不进入候选;
7. 当前临时占用和预约不从地图删除,只在质量评价阶段计入风险。
候选上限 32 是性能边界,不是业务评分。达到上限时在证据中写入
`candidateLimitReached=true`,但仍从已生成候选中作出确定性选择。
### 5.3 接近路径与服务路径
现有 `VehicleAssignmentService` 继续负责车辆资格和选车,不在本设计中改变选车规则。选车完成后:
1. 为选中车辆计算“当前位置到任务起点”的有界接近路径;
2. 独立计算“任务起点到任务终点”的有界服务路径;
3. 分别保存两段路线的最短距离、候选数量和选择原因;
4. 交通预约仍对拼接后的完整执行路线申请。
这样可以优化两段路线,同时避免本次改造无意改变已经验证过的自动选车行为。
## 6. 路线质量排序
每条候选路线生成以下固定顺序的比较元组:
```text
(
oppositeDirectionConflictCount,
occupiedNodeCount,
incompatibleReservedEdgeCount,
activeRouteOverlapEdgeCount,
turnCount,
physicalDistance,
canonicalPath
)
```
排序为字典序,前一项不同时不再比较后一项。
### 6.1 指标定义
- `oppositeDirectionConflictCount`:候选有向边与其他任务已预约方向相反的数量。
- `occupiedNodeCount`:候选未来节点中被其他车辆占用或独占预约的数量;当前车辆自身起点不计。
- `incompatibleReservedEdgeCount`:候选边与现有容量或方向规则不兼容的预约数量;已计为对向冲突
的边不重复计数。
- `activeRouteOverlapEdgeCount`:候选无向边与其他活动任务剩余路线重合的数量;这是未来竞争风险,
不等同于已经发生的资源冲突。
- `turnCount`:相邻两条同层边的方向向量发生变化的次数。
- `physicalDistance`:第 5 节定义的坐标距离。
- `canonicalPath`:用完整站点序列作最终稳定决胜。
安全规则仍由交通资源裁决执行。质量评价只决定优先尝试哪条路线,不能绕过节点容量、边方向或
走廊预约。
## 7. HOLD 后重规划
### 7.1 触发条件
仅以下原因进入连续 HOLD 计数:
- 下一节点被其他车辆占用或独占预约;
- 下一条边不可申请;
- 存在对向换边风险;
- 走廊方向预约冲突。
键为:
```text
(simulationTaskId, vehicleId, blockingResourceId, holdReason)
```
连续第 1、2 次只保持 HOLD;连续第 3 次产生 `REROUTE_TRIGGER`。车辆发生移动、阻塞资源或原因
改变、HOLD 消失、车辆被重新分配时清零。
PLC 发送失败或未 ACK、低电量、车辆故障和断线不进入该计数。
### 7.2 重规划范围
- 尚未到达任务起点:重新计算“当前位置到起点”的接近路径,同时基于同一交通快照重新评价
“起点到终点”的服务路径。
- 已进入服务路径:只计算“当前位置到任务终点”的剩余服务路径。
### 7.3 防止路线抖动
满足以下条件才允许切换:
1. 新剩余路线与当前剩余路线不同;
2. 新路线不超过对应最短距离 110%;
3. 新路线的质量元组严格优于当前路线;
4. 新路线的路线级走廊预约能够安全替换;
5. 上次成功换路后车辆已经至少移动一个节点,或当前路线出现永久失效。
找不到严格更优路线时产生 `REROUTE_REJECTED` 并继续 HOLD,不关闭任务。
## 8. 预约替换与资源释放
新增原子语义的路线级走廊预约替换操作:
```text
保留车辆当前占用节点和已进入边
→ 以当前任务旧预约为可替换资源,试算新剩余路线的走廊方向
→ 在不暴露中间状态的前提下提交走廊预约替换
→ 成功后提交新 remainingPath
→ 释放旧路线不再使用的走廊预约
```
如果试算或替换失败,旧路线和现有合法资源保持不变。不得先释放旧预约再申请新路线。
节点和边不因重规划而整条路线预占,仍由现有交通控制器在车辆移动前逐段申请,并在车辆通过后
逐段释放。重规划不能释放车辆当前节点、正在通过的边或其他任务资源。该边界既保留现有安全
语义,也避免因整条路线预占扩大资源等待和死锁风险。
## 9. 失败与降级规则
- 完整地图永久不可达:任务关闭为 `NO_ROUTE`。
- 存在地图路线但所有候选都有临时冲突:选择风险最小候选,交给交通裁决决定 GRANT/HOLD。
- 候选达到 32 条上限:从已有候选选择并记录上限证据。
- HOLD 后无更优路线:保持当前路线和 HOLD。
- PLC 失败或未 ACK:沿用原有协议重试,不触发路径重规划。
- 车辆故障或断线:沿用重新选车流程;新车辆确定后重新规划接近路径和服务路径。
- 低电量:车辆不再接收新任务;不把低电量伪装成交通冲突。
## 10. 事件与审计证据
保留现有事件,并新增:
- `REROUTE_TRIGGER`:包含连续 HOLD 次数、阻塞资源和原因;
- `REROUTE`:包含旧剩余路线、新剩余路线、两者质量元组和选择原因;
- `REROUTE_REJECTED`:包含没有更优候选、超出 110% 或预约替换失败原因。
每次初始规划和重规划输出:
- `shortestPhysicalDistance`
- `selectedPhysicalDistance`
- `detourRatio`
- `candidateCount`
- `candidateLimitReached`
- 质量元组各项指标
- `decisionReason`
- `pathVersion`
- `planningStage`:`APPROACH` 或 `SERVICE`
浏览器继续显示完整地图、历史路径、新规划路径和实际轨迹,并在检查器中分别显示接近路径和
服务路径的选择证据。实际时间、完成时间和 PLC 重试放在“运行与故障恢复”区域,不进入路线评分。
## 11. 历史路线比较口径
每条历史任务先分类:
- `COMPARABLE`:历史路径首尾与物理业务端点一致,且所有连续边都存在于权威地图;
- `ENDPOINT_MISMATCH`:历史首尾与物理业务端点不一致;
- `INVALID_HISTORY_PATH`:包含未知节点或非邻接段。
只有 `COMPARABLE` 任务进入路线质量统计。统计分类为:
- 完全相同;
- 物理距离更短;
- 距离相同但冲突或转弯更少;
- 距离在 110% 内略长但冲突更少;
- 新路线质量更差。
`pathChanged` 继续保留节点序列语义以兼容现有报告,但不能再单独作为“优化成功”指标。
## 12. 验收门禁
### 12.1 路线算法门禁
1. 所有选中路线距离不超过对应最短物理距离 110%。
2. 最终路线必须是已生成候选中的字典序最优质量元组。
3. 临时冲突不能导致错误的 `NO_ROUTE`。
4. 同一输入、地图和交通快照重复运行必须得到相同路线和原因。
5. 历史端点不一致或存在无效段时不得计入优化比例。
### 12.2 HOLD 与资源门禁
1. 同一交通冲突连续 1、2 次不重规划,第 3 次触发。
2. PLC 失败、低电量、故障和断线不能误触发交通重规划。
3. 找不到严格更优路线时保持原路线。
4. 路线切换失败不能丢失旧预约。
5. 车辆移动前后节点、边和走廊资源均保持单一合法归属。
6. 节点双占、资源超容量、对向换边和死锁为 0。
### 12.3 业务闭环门禁
1. 基准 240 条历史任务全部进入终态,不遗留活动或等待任务。
2. 所有完成任务归档一次且仅一次。
3. WMS 重复投递不产生重复业务效果。
4. 失败任务必须有明确、可审计的失败原因。
## 13. 测试策略
### 13.1 单元测试
- 坐标距离和路线距离;
- 110% 边界内外候选过滤;
- 无环候选和 32 条数量上限;
- 固定质量元组排序;
- 转弯、重叠、占用和对向冲突计数;
- 相同输入的确定性;
- 历史路线三类可比性判定。
### 13.2 集成测试
- 最短路线有冲突,10% 内存在无冲突绕行,必须选择绕行;
- 无冲突绕行超过 10%,必须保留允许范围内的最优路线;
- 所有候选有临时冲突时保持可调度而非 `NO_ROUTE`;
- 连续第 3 次相同交通 HOLD 重规划;
- 阻塞资源变化后计数重新开始;
- 成功换路后移动一个节点前不再次普通重规划;
- 新预约失败时旧预约保持完整;
- PLC 重试和车辆故障不污染交通 HOLD 计数。
### 13.3 历史负载和浏览器验收
- 重新执行 240 条历史任务并输出 `COMPARABLE/ENDPOINT_MISMATCH/INVALID_HISTORY_PATH`;
- 报告接近路径和服务路径的候选、质量、绕行比例和重规划证据;
- 在完整地图中显示初始路线、HOLD 点和重规划后的剩余路线;
- 验证所有路线切换均能从事件和资源证据追溯;
- 验证归档、WMS 幂等和所有安全门禁。
## 14. 性能与兼容性
- 不新增生产依赖,保持 Java 8 编译目标。
- 候选数量固定上限为 32,避免历史批量回放搜索量失控。
- 现有 `plannedPath`、`pathChanged` 和历史证据字段保持兼容;新增字段只扩展 JSON。
- 当前 BFS 行为保留为基准测试和最短边数对照,不再承担最终冲突感知选路职责。
- 本设计只修改 `javaTest`,不直接替换生产 WCS 调度实现。