Files
ParkingRobot/docs/superpowers/specs/2026-08-10-em-closed-loop-offline-scenario-verification-design.md
T

112 lines
6.2 KiB
Markdown
Raw 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.
# EM 闭环 MovementTest 本地离线场景验证设计
## 1. 目标
基于现有 `EM闭环测试` 的规划入口,在本地验证宿主中执行多组一次性规划,提前暴露路径搜索、EM 轨迹发布、求解预算和速度回退问题。测试只运行到轨迹发布成功为止,不创建控制执行器、不读取实车状态、不启动可视化服务器、不下发任何底盘命令。
本轮保持规划速度上限和期望速度为 `1.0 m/s`,核心判据是最终发布轨迹峰值是否大于 `0.2 m/s`,而不是测试超过 `1.0 m/s`
## 2. 方案选择
### 方案 A:只扩展纵向速度测试
直接向 `EmSpeedProfileChecks` 注入更多已生成的 `LateralPath`。优点是快速、容易定位纵向问题;缺点是绕过粗路径搜索、平滑、分段和 MovementTest 发布链,无法回答完整一次性规划耗时。
### 方案 B:直接启动 MovementTest Runner
调用 `EmClosedLoopMovementTestRunner`。优点是表面上最接近部署;缺点是发布后会进入控制器接管和底盘相关路径,不符合纯离线安全边界。
### 方案 C:复用 MovementTest 的规划前半段(采用)
在验证宿主中复用以下调用链,并在发布成功处停止:
```text
TrajectoryObservationSetupFactory.CreateBootstrapJob
→ TrajectoryObservationBootstrapper.Bootstrap
→ TrajectoryObservationController.StartCycle
→ PublishedTrajectory
→ 停止
```
该方案覆盖 MovementTest 实际使用的地图、粗路径、平滑、方向段选择、EM 规划和发布门禁,同时不进入 `ParkingGeometricController``TrajectoryTrackingMovement` 或底盘命令执行。
## 3. 测试结构
新增验证宿主入口 `em-closed-loop-offline`,实现独立的 `EmClosedLoopOfflinePlanningChecks`。测试使用与 `MovementTest.EmClosedLoopTest.cs` 一致的关键设置:
- `PlanningScope = FullDirectionSegment`
- `SolverTimeoutSeconds = 5`
- `MaximumOsqpIterations = 100000`
- `OutputTimeStepSeconds = 0.10`
- 车辆长度 `0.80 m`
- 车辆宽度 `0.60 m`
- 安全余量 `0.05 m`
- 最大曲率 `1 / 1.20 m⁻¹`
- 规划速度上限与期望速度保持 `1.0 m/s`
每个场景从静止状态 `(0, 0, 0)` 独立建立地图和规划任务,只调用一次 `StartCycle`。场景之间不复用上一条轨迹,不模拟车辆沿轨迹运动。
## 4. 仅前进场景矩阵
场景坐标和障碍物尺寸在实现时作为固定测试夹具保存,若粗路径搜索证明某组几何不可行,只允许调整该夹具,不降低安全余量或通过门禁。
1. **15 m 直线基准**:无障碍,目标 `(15, 0, 0)`
2. **单圆障碍绕行**:路径中央放置一个圆形障碍,要求绕开后回到目标轴线。
3. **单矩形障碍绕行**:使用较宽矩形制造持续弯道,验证转弯后直线加速。
4. **交错双圆 S 形**:两个障碍在中心线两侧交错布置,迫使参考路径连续转弯并回正。
5. **连续双矩形弯**:两个错位矩形形成较长的连续双弯,增加曲率变化和节点数量。
6. **紧凑局部绕行**:在车辆曲率能力和安全余量内放置更靠近起点的局部障碍,观察短距离内加速、转弯和停车是否触发保守回退。
所有场景必须满足:活动方向段为 `Forward`,发布轨迹中所有点的方向为 `Forward`,速度不出现超出容差的负值。若粗路径产生倒车段,场景测试失败并报告方向分段,不自动忽略。
## 5. 耗时口径
每个场景分别记录:
- `BootstrapElapsed`:地图建立、粗路径搜索、路径平滑和方向分段耗时;
- `EmPlanPublishElapsed``StartCycle``PublishedTrajectory` 可用的耗时;
- `TotalOneShotElapsed`:从创建 bootstrap job 到轨迹发布完成的端到端墙钟耗时;
- `TrajectoryPeakSpeed`:最终发布轨迹的最大绝对纵向速度;
- `PlanningStatus``Published`、方向段数、轨迹点数和是否包含 fallback 诊断。
第一次场景运行可能包含 OSQP DLL 加载和 JIT 冷启动,因此报告中明确标注首场为冷启动样本,其余为同一进程内的热启动样本。测试不以单次机器耗时设置过紧断言,只要求端到端时间不超过现有 `5 s` 规划预算;具体毫秒数作为诊断输出。
## 6. 通过标准
每个场景同时满足以下条件才算通过:
1. bootstrap 成功;
2. `StartCycle` 返回且 `Published = true`
3. `PublishedTrajectory` 非空;
4. 活动方向段和所有发布点均保持前进;
5. 峰值速度严格大于 `0.2 m/s`
6. 峰值速度不超过 `1.0 m/s` 加数值容差;
7. 终点速度为零;
8. 端到端一次性规划耗时小于 `5 s`
9. 失败时输出阶段、状态、诊断和已消耗时间,不吞掉异常。
测试只证明本机离线规划链路;不声称已经验证控制跟踪效果、底盘限速、定位反馈或实车安全性。
## 7. TDD 与验证
先新增测试入口和六个场景断言,确认在缺少离线场景运行器时测试按预期失败。随后实现最小的本地规划夹具与计时记录,使测试转绿。最终运行:
```text
dotnet build ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -c Release --no-restore
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -c Release --no-build -- em-closed-loop-offline
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -c Release --no-build -- em-speed-profile
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -c Release --no-build -- longitudinal-integration
ClumsyPilot/tests/verify_em_closed_loop_movement.ps1
```
验收输出汇总每个场景的 bootstrap、EM发布和端到端耗时,并给出最慢场景、平均热启动耗时、所有场景峰值速度范围以及是否出现 fallback。
## 8. 明确不做的内容
- 不启动 `EM闭环测试` 的在线运行线程;
- 不实例化或调用现有控制器;
- 不读取 `Shared`、状态估计或底盘的实时状态;
- 不修改 `Control``Shared`、状态估计和他人的底盘代码;
- 不打开网页或原生可视化;
- 不模拟车辆沿轨迹逐步反馈,本轮仅验证一次性规划和发布。