Files
ParkingRobot/docs/superpowers/specs/2026-07-27-planning-operation-budget-design.md
T

4.2 KiB

规划操作预算与诊断收尾设计

目标

在进入 P1 的 UI 集成前,使一次 CoarsePathPlanningService.Plan 调用的取消与超时语义覆盖完整链路:地图创建、距离场构建、二维 Dijkstra 启发式和 Hybrid A* 搜索。同时让现有 PlanningDiagnostics 中的 Open List 陈旧条目数与峰值容量反映真实搜索数据。

成功、无解、输入无效和碰撞安全语义不改变;任何取消或超时结果均不得发布部分路径或部分地图。

方案选择

采用一个内部共享的、基于单调 StopwatchPlanningOperationBudget。它保存调用方的 CancellationToken、整次调用开始时刻与总超时,并在每个耗时循环中返回三态结果:继续、已取消、已超时。

不采用“只在 Dijkstra 前后检查”的方案,因为大图 Dijkstra 和 EDT 仍可能长时间无响应;也不替换 Dijkstra 启发式,避免在收尾阶段改变 Hybrid A* 的搜索特性。

边界与数据流

CoarsePathPlanningService.Plan(job, token)
  -> PlanningOperationBudget(token, job.Configuration.SearchTimeout)
  -> PlanningMapFactory.Create(mapRequest, budget)
       -> EnvironmentMapBuilder / PlanningMapAdapter / EDT
  -> HybridAStarPlanner.Plan(planningRequest, budget)
       -> GridDijkstraHeuristic
       -> HybridAStarSearch Open List
  -> PlanningResult + PlanningDiagnostics

PlanningOperationBudget 放在不依赖 MapCoarsePath 的公共工具层,仅暴露中立的停止原因。Map 与粗规划分别把该原因映射到自己的结果类型,避免 Map 反向依赖 CoarsePath

地图构建结果增加明确的终止状态(成功、普通构建失败、取消、超时)。CoarsePathPlanningService 将地图阶段的取消映射为 PlanningStatus.Cancelled,地图阶段的超时映射为 PlanningStatus.SearchTimeout;两种结果都保留地图构建诊断但路径和分段为空。

现有不带预算参数的 PlanningMapFactory.CreateHybridAStarPlanner.PlanGridDijkstraHeuristic 入口保持可用,作为不受取消限制的兼容包装;业务门面只使用带共享预算的内部入口。

响应与一致性规则

  • 每个耗时循环在开始处及每处理最多 256 个工作单元后检查预算;检查不改变正常情况下的栅格、启发式或 Open List 排序。
  • 等待地图工厂创建锁时使用可轮询的获取方式,以便取消和超时也能中断排队等待。
  • 缓存命中仍立即返回原有不可变快照;预算已停止时优先返回取消/超时,不能借缓存绕过调用方停止请求。
  • 已被取消或超时的地图构建不得写入任何缓存,也不得发布部分 PlanningGridMap
  • 规划器总耗时从门面开始计时;搜索器不重新开始独立的 5 秒窗口。

诊断

HybridAStarSearchResult 增加陈旧 Open List 条目数和 Open List 峰值。每次丢弃失效的普通节点时递增陈旧计数;每次成功入堆后更新峰值。HybridAStarPlanner 原样将这两个统计写入 PlanningDiagnostics

目标候选仍保留其当前规则:不受普通离散键的 best-G 压制,出队时复核。它们占用 Open List 容量,因此计入峰值;不因候选自身而计为陈旧条目。

测试与验收

  • 在大于一个检查批次的地图上,Dijkstra 预计算期间取消,断言返回 Cancelled、空路径和有限响应时间。
  • 使用足以覆盖 Dijkstra 工作的极短总超时,断言返回 SearchTimeout、空路径,且总耗时不超出预算一个检查批次的合理余量。
  • 在地图适配器/EDT 处理中取消和超时,断言地图结果带对应状态、没有地图快照且缓存未被污染。
  • 使用产生失效 Open List 条目的场景,断言陈旧数大于零;任意正常搜索断言峰值至少为一,并与最终 PlanningDiagnostics 一致。
  • 重新运行 Debug 构建、所有既有 P0 地图/粗规划检查,以及新增取消、超时和诊断检查。

非目标

  • 不修改运动原语、碰撞保守性、代价公式、目标候选排序或路径装配。
  • 不在本次收尾中实现 UI、Painter、场景工厂或 Release 性能门槛;这些仍属于 P1。