# EM 完整方向段可视化修复 — Phase 03 交接

## 状态

完成，2026-08-07。

启动分支为 `trajplanner`，启动 HEAD 为 `162f1a2`（Phase 02 handoff）。已确认 `3269d55` 与 `162f1a2` 均为本阶段提交的祖先。

本阶段实现提交：

- `0bba8d7` — `fix: accelerate EM trajectories from rest`
- `e844fe0` — `feat: validate EM terminal world pose`

本交接文件单独提交；其真实提交哈希应由提交后的 Phase 03 最终答复提供给 Phase 04。

## 目标与非目标

完成主计划 Task 4–5：完整方向段可从静止起步，非终端全零候选被精确拒绝，并且在发布前验证真实终端位姿和样本数量上限。

未进入 MovementTest、UI、Web、Native Painter、跨段衔接或任何后续阶段；未新增执行器或硬件写输出。

## Task 4：静止起步与 NoProgress

- 完整方向段的纵向目标跟踪自适应 knot schedule 的参考速度，而不是在每个结点只追踪当前速度上限；滚动窗口保持原有速度上限目标。
- 静止、零加速度的完整段优先构造并严格验证可达的 S/U/A/J 精确停车种子，因此清晰 5 m 段能够起步、加速、推进并在边界停车。
- 停车包络使用实际初始加速度。此前预计算阶段按最大正加速度计算，过早将可用速度压为零；现在服务层的预计算和纵向输入使用同一实际状态。
- 自适应 schedule 在加速→巡航、巡航→减速和换向的转折点保留站点；时间可达性计算保持原始请求时间，不会因原地改写时间而产生非递增结点。
- `LongitudinalSolutionValidator` 对路径长度超过终端位置容差的 `FullDirectionSegment` 检查实际推进量。若不超过空间容差，返回精确的 `EmPlanningStatus.NoProgress` 与诊断；合法的终端容差内保持不误判。
- 初始可行投影把 `NoProgress` 直接传回服务层；服务结果不包含 trajectory。

Task 4 修改：

- `ClumsyPilot/ParkrobTrajplanner/EMPlanner/Longitudinal/SequentialLongitudinalOptimizer.cs`
- `ClumsyPilot/ParkrobTrajplanner/EMPlanner/Longitudinal/LongitudinalObjectiveBuilder.cs`
- `ClumsyPilot/ParkrobTrajplanner/EMPlanner/Longitudinal/LongitudinalSolutionValidator.cs`
- `ClumsyPilot/ParkrobTrajplanner/EMPlanner/Longitudinal/PathSpeedLimitBuilder.cs`
- `ClumsyPilot/ParkrobTrajplanner/EMPlanner/Longitudinal/FullDirectionSegmentScheduleBuilder.cs`
- `ClumsyPilot/ParkrobTrajplanner/EMPlanner/Facade/EmPlanningService.cs`
- `ClumsyPilot/tests/EMPlannerVerificationHost/LongitudinalModelChecks.cs`
- `ClumsyPilot/tests/EMPlannerVerificationHost/LongitudinalIntegrationChecks.cs`
- `ClumsyPilot/tests/EMPlannerVerificationHost/EmPlanningServiceChecks.cs`

`PathSpeedLimitBuilder.cs` 和 `FullDirectionSegmentScheduleBuilder.cs` 是为复现并修复静止起步包络/结点前提而获用户明确授权纳入的最小附加范围；`EmPlannerConfiguration.cs` 未修改。

## Task 5：终端位姿、样本上限与发布门禁

- `EmTrajectoryValidator` 新增接收 `Pose2D terminalPose` 的验证重载。只有真正的 `Goal` 与 `GearSwitchApproach` 精确终端锚点才检查世界位置和航向；滚动安全窗终点不进入此门禁。
- 位置误差使用欧氏距离并受 `TerminalPositionToleranceMeters`（3 cm）约束；航向误差归一化到 `[-π, π]`，再受 `TerminalYawToleranceRadians`（5°）约束。失败码为 `EmTrajectoryValidationFailure.TerminalPoseMismatch`。
- 服务层把 Local G2 的最后一个 `LateralPathPoint` 作为期望终端世界位姿，并把该验证失败映射为 `EmPlanningStatus.TerminalPoseMismatch`；失败不发布 trajectory。
- `TrajectorySampleSchedule.ExceedsMaximumSampleCount` 在组装点列表前按实际采样规则预检：包含终端锚点与停止保持样本。超过 `MaximumPublishedSampleCount` 时 `EmTrajectoryAssembler.TryAssemble` 返回 `FullSegmentResourceLimitExceeded`，trajectory 为 `null`，不会截断、放宽采样周期或返回半成品。
- 原有时间严格递增、终端锚点、N-1 jerk、S/U/A/J 停止尾和世界碰撞验证保持不变。

Task 5 修改：

- `ClumsyPilot/ParkrobTrajplanner/EMPlanner/Validation/EmTrajectoryValidator.cs`
- `ClumsyPilot/ParkrobTrajplanner/EMPlanner/Facade/EmPlanningService.cs`
- `ClumsyPilot/ParkrobTrajplanner/EMPlanner/Trajectory/TrajectorySampleSchedule.cs`
- `ClumsyPilot/ParkrobTrajplanner/EMPlanner/Trajectory/EmTrajectoryAssembler.cs`
- `ClumsyPilot/tests/EMPlannerVerificationHost/TrajectoryChecks.cs`
- `ClumsyPilot/tests/EMPlannerVerificationHost/EmPlanningServiceChecks.cs`

新增测试覆盖 2.9 cm/3.1 cm、4.9°/5.1°、179°/-179° yaw 绕回、滚动安全窗豁免、恰好多一个发布样本、组装拒绝无部分 trajectory，以及服务状态映射。

## RED / GREEN / 回归证据

Task 4 的静止起步集成测试先暴露了全零参考/不可行的停止包络；修复后以下命令均以退出码 0 通过：

```powershell
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- longitudinal-model
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- longitudinal-integration
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- em-planning-service
```

Task 5 的 RED 是新增测试后编译失败，原因精确为缺少带终端 `Pose2D` 的验证重载、`TerminalPoseMismatch` 失败码和拒绝式 `TryAssemble` 接口。实现后以下命令均以退出码 0 通过：

```powershell
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- em-planning-service
```

最终新鲜回归：

```powershell
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- em-core-all
git diff --check
```

`em-core-all` 退出码为 0，输出依次为 `PASS longitudinal-model`、`PASS longitudinal-integration`、`PASS trajectory`、`PASS em-planning-service`。`git diff --check` 通过。

已知且保留的两条编译 warning：过时的 `Lidar2dDetect2LegTray.LegWidth` 与 `MultiWheelChassis.GetSteerWheels()`。

## 工作区保护

保留并未编辑/暂存用户原有的脏工作区内容，包括 `ClumsyPilot/ParkrobTrajplanner/EMPlanner/Configuration/EmPlannerConfiguration.cs`、`ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/MovementTest.TrajectoryObservationTest.cs`、PathSmoothing、CoarsePath、Map、文档和未跟踪报告等改动。未使用 `git reset --hard`、`git checkout --`、`git clean`、`git add .` 或 `git add -A`。

## Phase 04 完整启动提示词

```text
执行 EM 全方向段可视化修复的 Phase 04：MovementTest 每个方向段仅规划一次。

仓库：D:\Users\Desktop\项目\prakrobot\ParkingRobot
预期分支：trajplanner
Phase 03 实现提交必须可达：0bba8d7、e844fe0。
Phase 03 handoff：docs/superpowers/handoffs/em-full-direction-visualization/phase-03.md；同时要求调用方提供并验证该 handoff 的提交哈希可达。

只执行主计划 Task 6；不得进入 Task 7+、Web、Painter、跨段规划扩展或实车操作。MovementTest 必须保持 OBSERVE_ONLY，严禁新增底盘、转向、制动、电机或换挡写输出。不得派生子智能体，也不要重新 brainstorming 或重设计已批准行为。

开始时必须：
1. 读取 executing-plans、test-driven-development、verification-before-completion；仅在真实失败或意外行为后读取 systematic-debugging。
2. 完整阅读功能设计、主计划 Task 6、分阶段执行计划 Phase 04、阶段执行设计及本 Phase 03 handoff；发生矛盾则停止并写阻塞交接，请求用户裁决。
3. 运行并记录：
   git branch --show-current
   git rev-parse HEAD
   git log -5 --oneline
   git status --short
   git diff --cached --name-only
   git merge-base --is-ancestor 3269d55 HEAD
   git merge-base --is-ancestor 162f1a2 HEAD
   git merge-base --is-ancestor 0bba8d7 HEAD
   git merge-base --is-ancestor e844fe0 HEAD
   以及调用方提供的 Phase 03 handoff 哈希。
4. 保留所有既有脏文件；修改已脏目标前先记录 diff 并逐 hunk 保留用户改动。严禁 git reset --hard、git checkout --、git clean、git add .、git add -A。

本阶段唯一允许修改/新增：
- ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/TrajectoryObservationContracts.cs
- ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/TrajectoryObservationPipeline.cs
- ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/MovementTest.TrajectoryObservationTest.cs
- ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/TrajectoryObservationStaticSnapshotBuilder.cs
- ClumsyPilot/tests/EMPlannerVerificationHost/TrajectoryObservationSettingsChecks.cs
- ClumsyPilot/tests/EMPlannerVerificationHost/TrajectoryObservationChecks.cs
- ClumsyPilot/tests/EMPlannerVerificationHost/TrajectoryObservationSegmentChecks.cs
- docs/superpowers/handoffs/em-full-direction-visualization/phase-04.md

按 TDD 先编写 Task 6 指定的失败测试，然后运行：
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation
确认首个有效 RED 是完整方向段仍按协调器节拍重复开始计划周期。

实现且仅实现：TrajectoryObservationSettings.PlanningScope（默认 FullDirectionSegment）、经过验证快照/请求的 scope 传播、批准的观察默认值，以及每个活动方向段最多一次计划尝试。尝试标志必须在启动异步计划前置位；只有 TryAdvanceSegment 确认 N→N+1 后才复位。失败的完整段计划保持可见但不自动滚动重试。保留已有停车保持和三条带符号速度样本握手、显式等待文案及 active segment 高亮。

GREEN 后运行：
dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation
rg -n "SendXYThSpeed|SendMotion|DriveStop|PredefinedDriveStop|AccumulateSpeed|SetGear|SetBrake" ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest
git diff --check
期望 trajectory-observation PASS，且观察运行时源中没有执行器调用。

只显式暂存本阶段白名单实现/测试文件，并提交：
git commit -m "feat: observe one full EM direction segment"

随后仅用 apply_patch 创建 phase-04.md，记录入口 HEAD、实现提交、RED/GREEN、执行器审计、保留脏工作区、warning、未运行项及 Phase 05 事实；只提交该 handoff：
git commit -m "docs: record EM full-direction phase 04 handoff"

成功门禁：完整范围由显式设置启用；每个方向段仅计划一次；观察继续、停车/换向握手保持；无硬件写输出。若被阻塞，创建阻塞 handoff 和同阶段恢复提示词，不得进入 Phase 05。
```
