14 KiB
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 目标
- 接近路径和服务路径都允许在最短物理距离 110% 范围内绕行。
- 只使用当前活动任务、节点占用、边预约和走廊方向判断交通风险,不使用历史热度。
- 按固定业务优先级比较候选路线,不使用难以解释和调参的加权总分。
- 同一交通资源连续造成 3 个调度周期 HOLD 后,从车辆当前位置重新规划剩余路线。
- 路线切换必须保持当前占用和预约安全,不能因重规划产生资源空窗。
- 将路线质量、交通执行和故障恢复分开统计。
- 相同地图、输入和交通快照必须产生相同结果。
2.2 非目标
- 不用实际行驶时间或最终任务完成时间给路径质量打分。
- 不使用历史
path_info约束新路线。 - 不在本次改造中改变现有车辆资格、低电量和车辆选择业务规则。
- 不把 PLC 失败、断线、低电量或车辆故障当成交通 HOLD。
- 不接入生产数据库、真实 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 条边,不存在跨层边。相邻站点边距离按地图坐标的欧氏距离计算:
edgeDistance = sqrt((to.x - from.x)^2 + (to.y - from.y)^2)
pathDistance = sum(edgeDistance)
距离单位是地图坐标单位,不宣称为米。未来如增加跨层边,必须由地图元数据显式提供该边距离; 不得根据楼层编号虚构垂直距离。
5.2 候选生成算法
采用确定性的 K 最短无环路径方案:
- 使用 Dijkstra 计算基准最短路线和距离
D; - 按距离从小到大生成无环候选路线;
- 下一候选距离超过
D * 1.10时停止; - 最多保留 32 条候选;
- 距离相同时按完整站点序列排序;
- 未知节点、永久封闭道路和静态禁行资源不进入候选;
- 当前临时占用和预约不从地图删除,只在质量评价阶段计入风险。
候选上限 32 是性能边界,不是业务评分。达到上限时在证据中写入
candidateLimitReached=true,但仍从已生成候选中作出确定性选择。
5.3 接近路径与服务路径
现有 VehicleAssignmentService 继续负责车辆资格和选车,不在本设计中改变选车规则。选车完成后:
- 为选中车辆计算“当前位置到任务起点”的有界接近路径;
- 独立计算“任务起点到任务终点”的有界服务路径;
- 分别保存两段路线的最短距离、候选数量和选择原因;
- 交通预约仍对拼接后的完整执行路线申请。
这样可以优化两段路线,同时避免本次改造无意改变已经验证过的自动选车行为。
6. 路线质量排序
每条候选路线生成以下固定顺序的比较元组:
(
oppositeDirectionConflictCount,
occupiedNodeCount,
incompatibleReservedEdgeCount,
activeRouteOverlapEdgeCount,
turnCount,
physicalDistance,
canonicalPath
)
排序为字典序,前一项不同时不再比较后一项。
6.1 指标定义
oppositeDirectionConflictCount:候选有向边与其他任务已预约方向相反的数量。occupiedNodeCount:候选未来节点中被其他车辆占用或独占预约的数量;当前车辆自身起点不计。incompatibleReservedEdgeCount:候选边与现有容量或方向规则不兼容的预约数量;已计为对向冲突 的边不重复计数。activeRouteOverlapEdgeCount:候选无向边与其他活动任务剩余路线重合的数量;这是未来竞争风险, 不等同于已经发生的资源冲突。turnCount:相邻两条同层边的方向向量发生变化的次数。physicalDistance:第 5 节定义的坐标距离。canonicalPath:用完整站点序列作最终稳定决胜。
安全规则仍由交通资源裁决执行。质量评价只决定优先尝试哪条路线,不能绕过节点容量、边方向或 走廊预约。
7. HOLD 后重规划
7.1 触发条件
仅以下原因进入连续 HOLD 计数:
- 下一节点被其他车辆占用或独占预约;
- 下一条边不可申请;
- 存在对向换边风险;
- 走廊方向预约冲突。
键为:
(simulationTaskId, vehicleId, blockingResourceId, holdReason)
连续第 1、2 次只保持 HOLD;连续第 3 次产生 REROUTE_TRIGGER。车辆发生移动、阻塞资源或原因
改变、HOLD 消失、车辆被重新分配时清零。
PLC 发送失败或未 ACK、低电量、车辆故障和断线不进入该计数。
7.2 重规划范围
- 尚未到达任务起点:重新计算“当前位置到起点”的接近路径,同时基于同一交通快照重新评价 “起点到终点”的服务路径。
- 已进入服务路径:只计算“当前位置到任务终点”的剩余服务路径。
7.3 防止路线抖动
满足以下条件才允许切换:
- 新剩余路线与当前剩余路线不同;
- 新路线不超过对应最短距离 110%;
- 新路线的质量元组严格优于当前路线;
- 新路线的路线级走廊预约能够安全替换;
- 上次成功换路后车辆已经至少移动一个节点,或当前路线出现永久失效。
找不到严格更优路线时产生 REROUTE_REJECTED 并继续 HOLD,不关闭任务。
8. 预约替换与资源释放
新增原子语义的路线级走廊预约替换操作:
保留车辆当前占用节点和已进入边
→ 以当前任务旧预约为可替换资源,试算新剩余路线的走廊方向
→ 在不暴露中间状态的前提下提交走廊预约替换
→ 成功后提交新 remainingPath
→ 释放旧路线不再使用的走廊预约
如果试算或替换失败,旧路线和现有合法资源保持不变。不得先释放旧预约再申请新路线。
节点和边不因重规划而整条路线预占,仍由现有交通控制器在车辆移动前逐段申请,并在车辆通过后 逐段释放。重规划不能释放车辆当前节点、正在通过的边或其他任务资源。该边界既保留现有安全 语义,也避免因整条路线预占扩大资源等待和死锁风险。
9. 失败与降级规则
- 完整地图永久不可达:任务关闭为
NO_ROUTE。 - 存在地图路线但所有候选都有临时冲突:选择风险最小候选,交给交通裁决决定 GRANT/HOLD。
- 候选达到 32 条上限:从已有候选选择并记录上限证据。
- HOLD 后无更优路线:保持当前路线和 HOLD。
- PLC 失败或未 ACK:沿用原有协议重试,不触发路径重规划。
- 车辆故障或断线:沿用重新选车流程;新车辆确定后重新规划接近路径和服务路径。
- 低电量:车辆不再接收新任务;不把低电量伪装成交通冲突。
10. 事件与审计证据
保留现有事件,并新增:
REROUTE_TRIGGER:包含连续 HOLD 次数、阻塞资源和原因;REROUTE:包含旧剩余路线、新剩余路线、两者质量元组和选择原因;REROUTE_REJECTED:包含没有更优候选、超出 110% 或预约替换失败原因。
每次初始规划和重规划输出:
shortestPhysicalDistanceselectedPhysicalDistancedetourRatiocandidateCountcandidateLimitReached- 质量元组各项指标
decisionReasonpathVersionplanningStage:APPROACH或SERVICE
浏览器继续显示完整地图、历史路径、新规划路径和实际轨迹,并在检查器中分别显示接近路径和 服务路径的选择证据。实际时间、完成时间和 PLC 重试放在“运行与故障恢复”区域,不进入路线评分。
11. 历史路线比较口径
每条历史任务先分类:
COMPARABLE:历史路径首尾与物理业务端点一致,且所有连续边都存在于权威地图;ENDPOINT_MISMATCH:历史首尾与物理业务端点不一致;INVALID_HISTORY_PATH:包含未知节点或非邻接段。
只有 COMPARABLE 任务进入路线质量统计。统计分类为:
- 完全相同;
- 物理距离更短;
- 距离相同但冲突或转弯更少;
- 距离在 110% 内略长但冲突更少;
- 新路线质量更差。
pathChanged 继续保留节点序列语义以兼容现有报告,但不能再单独作为“优化成功”指标。
12. 验收门禁
12.1 路线算法门禁
- 所有选中路线距离不超过对应最短物理距离 110%。
- 最终路线必须是已生成候选中的字典序最优质量元组。
- 临时冲突不能导致错误的
NO_ROUTE。 - 同一输入、地图和交通快照重复运行必须得到相同路线和原因。
- 历史端点不一致或存在无效段时不得计入优化比例。
12.2 HOLD 与资源门禁
- 同一交通冲突连续 1、2 次不重规划,第 3 次触发。
- PLC 失败、低电量、故障和断线不能误触发交通重规划。
- 找不到严格更优路线时保持原路线。
- 路线切换失败不能丢失旧预约。
- 车辆移动前后节点、边和走廊资源均保持单一合法归属。
- 节点双占、资源超容量、对向换边和死锁为 0。
12.3 业务闭环门禁
- 基准 240 条历史任务全部进入终态,不遗留活动或等待任务。
- 所有完成任务归档一次且仅一次。
- WMS 重复投递不产生重复业务效果。
- 失败任务必须有明确、可审计的失败原因。
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 调度实现。