docs: add trajectory flow demo plan

This commit is contained in:
梁薄云
2026-08-10 10:00:35 +08:00
parent bc8e695654
commit cdd61705f2
@@ -0,0 +1,179 @@
# Trajectory Planning Flow Demo Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Build an offline single-page Chinese interactive demo that explains the map-to-control trajectory-planning evidence chain.
**Architecture:** A standalone HTML file embeds coherent illustrative map, coarse-path, smoothing-path, EM-trajectory and control-command data. Inline CSS and JavaScript render a fixed-coordinate SVG map, stage-specific layers, time-based vehicle playback, data contracts and control-output semantics without network or project-runtime dependencies. A PowerShell verifier asserts required content before browser review.
**Tech Stack:** HTML5, inline CSS, vanilla JavaScript, inline SVG, PowerShell 7 verification.
## Global Constraints
- Create exactly `ClumsyPilot/ParkrobTrajplanner/Trajplanner_output/trajectory-planning-flow-demo.html`.
- Local-file operation only: no `http://`, `https://`, `fetch`, XHR or WebSocket.
- Use illustrative metric data; do not claim OSQP, localization, hardware or controller execution.
- Use existing `EmTrajectory` / `TrajectoryControlCommand` field names verbatim.
- Preserve and never stage unrelated user changes.
---
### Task 1: Add a deterministic web-asset contract verifier
**Files:**
- Create: `ClumsyPilot/tests/verify_trajectory_planning_flow_demo.ps1`
- Test: `ClumsyPilot/tests/verify_trajectory_planning_flow_demo.ps1`
**Interfaces:**
- Consumes UTF-8 text from `ClumsyPilot/ParkrobTrajplanner/Trajplanner_output/trajectory-planning-flow-demo.html`.
- Produces exit code `0` and `Trajectory planning flow demo checks passed.` only when all page contracts pass.
- [ ] **Step 1: Write the failing test**
```powershell
$ErrorActionPreference = 'Stop'
$page = Join-Path $PSScriptRoot '..\ParkrobTrajplanner\Trajplanner_output\trajectory-planning-flow-demo.html'
if (-not (Test-Path -LiteralPath $page)) { throw "Missing demo page: $page" }
$html = Get-Content -LiteralPath $page -Raw -Encoding UTF8
$required = @('轨迹规划全链路 Demo', 'data-stage="map"', 'data-stage="coarse"', 'data-stage="smooth"', 'data-stage="em"', 'data-stage="control"', 'id="planning-map"', 'id="timeline"', 'Hybrid A* 粗路径', 'Local G2 平滑路径', 'EmTrajectory', 'TrajectoryControlCommand', 'mapSnapshotId', 'referencePathId', 'SignedLongitudinalVelocity', 'RequestDirectionChange', 'HoldBrake', 'IsTrajectoryComplete', 'function render()', 'function controlCommandForPoint(', 'addEventListener')
foreach ($token in $required) { if (-not $html.Contains($token)) { throw "Missing required demo contract: $token" } }
foreach ($forbidden in @('http://', 'https://', 'fetch(', 'XMLHttpRequest', 'WebSocket')) { if ($html.Contains($forbidden)) { throw "Demo must remain offline: $forbidden" } }
Write-Output 'Trajectory planning flow demo checks passed.'
```
- [ ] **Step 2: Run the test and verify initial failure**
Run `pwsh -NoProfile -File ClumsyPilot/tests/verify_trajectory_planning_flow_demo.ps1`.
Expected: `Missing demo page`.
- [ ] **Step 3: Commit the test**
Run `git add -- ClumsyPilot/tests/verify_trajectory_planning_flow_demo.ps1` followed by `git commit -m "test: verify trajectory planning flow demo"`.
### Task 2: Implement the offline stage-and-playback page
**Files:**
- Create: `ClumsyPilot/ParkrobTrajplanner/Trajplanner_output/trajectory-planning-flow-demo.html`
- Test: `ClumsyPilot/tests/verify_trajectory_planning_flow_demo.ps1`
**Interfaces:**
- Consumes static `identity`, `map`, `coarsePath`, `smoothPath`, and `trajectory` constants.
- Produces `render()` which updates SVG layers, selected point, stage JSON, control command and boundary explanation.
- [ ] **Step 1: Implement the responsive semantic shell**
Use this exact control structure:
```html
<nav aria-label="规划阶段">
<button type="button" data-stage="map">1. 地图</button>
<button type="button" data-stage="coarse">2. 粗路径</button>
<button type="button" data-stage="smooth">3. 平滑路径</button>
<button type="button" data-stage="em" aria-pressed="true">4. EM 轨迹</button>
<button type="button" data-stage="control">5. 控制接口</button>
</nav>
<svg id="planning-map" viewBox="0 0 800 520" role="img" aria-label="停车场地图与轨迹"></svg>
<input id="timeline" type="range" min="0" value="0" aria-label="EM 轨迹时间点">
<pre id="data-sample"></pre>
<pre id="control-sample"></pre>
```
Inline CSS must make the map dominant, panels stack at narrow width, and identify every layer with text plus distinct marker/line pattern. Include visible units `m`, `rad`, `m/s`, `rad/s` and a label that data is illustrative. Do not import fonts, assets or libraries.
- [ ] **Step 2: Implement internally consistent data and the exact control adapter**
Create frozen `identity` fields: `mapSnapshotId`, `referencePathId`, `vehicleStateSequenceId`, `trajectoryId`, `effectiveAtUtc`. Use a 4 m by 3 m map with three obstacles; include a forward coarse/smooth segment, a shared gear-switch pose, and reverse parking into the Goal. Implement `trajectory` with six time samples at `0`, `1.0`, `2.0`, `2.2`, `3.2`, `4.3` seconds; samples `2.0` and `2.2` share the gear pose and Goal is the last sample. Each point contains `x`, `y`, `yaw`, `signedVelocity`, `acceleration`, `yawRate`, `direction`, `segmentIndex`, `boundaryType`.
Implement this declared contract exactly:
```javascript
function controlCommandForPoint(point) {
const holding = point.boundaryType === "GearSwitchApproach" ||
point.boundaryType === "GearSwitchDeparture" || point.boundaryType === "Goal";
return {
SignedLongitudinalVelocity: holding ? 0 : point.signedVelocity,
YawRate: holding ? 0 : point.yawRate,
Direction: point.direction,
RequestDirectionChange: point.boundaryType === "GearSwitchApproach",
HoldBrake: holding,
IsTrajectoryComplete: point.boundaryType === "Goal"
};
}
```
- [ ] **Step 3: Implement SVG render behavior**
Implement `function render()` using one world-to-screen transform. Always draw map boundary, three obstacles, start/goal and current vehicle. For `map`, show only map information; for `coarse`, add discrete `Hybrid A* 粗路径` nodes and direction arrows; for `smooth`, add the `Local G2 平滑路径`, segment labels and curvature text; for `em` and `control`, add timed `EmTrajectory` points, selected-point highlight and heading arrow. Update `#data-sample` with stage-specific JSON. Update `#control-sample` with `controlCommandForPoint(selectedPoint)` only in control stage, otherwise state that control does not consume the stage yet.
Every view must visibly state `Success` or `SuccessWithFallback` plus a complete trajectory is required for publication. Control view must state coarse/smoothed path is observability evidence, not a controller command.
- [ ] **Step 4: Implement local interactions**
Click handlers on `[data-stage]` update `aria-pressed`, visibility and `render()`. An `input` handler on `#timeline` selects the trajectory point and calls `render()`. Disable timeline in map/coarse/smooth; initialize stage `em`, selected point `0`, then call `render()` exactly once after event binding.
- [ ] **Step 5: Run test and perform browser acceptance checks**
Run `pwsh -NoProfile -File ClumsyPilot/tests/verify_trajectory_planning_flow_demo.ps1`.
Expected: `Trajectory planning flow demo checks passed.`
Open the local page. Verify all five stage buttons change layers/data; EM/control timeline updates vehicle pose; gear sample returns zero speed/yaw rate plus `RequestDirectionChange: true` and `HoldBrake: true`; Goal returns zero speed/yaw rate plus `HoldBrake: true` and `IsTrajectoryComplete: true`; mobile reflow has no horizontal clipping.
- [ ] **Step 6: Commit the page**
Run `git add -- ClumsyPilot/ParkrobTrajplanner/Trajplanner_output/trajectory-planning-flow-demo.html` followed by `git commit -m "feat: add trajectory planning flow demo"`.
### Task 3: Document the relationship to the executable output demo
**Files:**
- Modify: `ClumsyPilot/ParkrobTrajplanner/Trajplanner_output/README.md`
- Modify: `ClumsyPilot/tests/verify_trajectory_planning_flow_demo.ps1`
- Test: `ClumsyPilot/tests/verify_trajectory_planning_flow_demo.ps1`
**Interfaces:**
- Consumes the local HTML page and `TrajectoryOutputDemoRunner` documentation.
- Produces a README link that identifies the page as an illustrative observability/interface explainer, never a live planner.
- [ ] **Step 1: Extend the test with a failing README assertion**
Before final output, add:
```powershell
$readme = Get-Content -LiteralPath (Join-Path $PSScriptRoot '..\ParkrobTrajplanner\Trajplanner_output\README.md') -Raw -Encoding UTF8
if (-not $readme.Contains('trajectory-planning-flow-demo.html')) { throw 'README must link to the trajectory-planning-flow demo.' }
```
- [ ] **Step 2: Run the test and verify initial README failure**
Run `pwsh -NoProfile -File ClumsyPilot/tests/verify_trajectory_planning_flow_demo.ps1`.
Expected: `README must link`.
- [ ] **Step 3: Add the exact README content**
Add after the existing data-flow diagram:
```markdown
## 全链路可视化(Offline Flow Demo
双击打开 [trajectory-planning-flow-demo.html](trajectory-planning-flow-demo.html),可在同一米制地图中按阶段查看地图、Hybrid A* 粗路径、Local G2 平滑路径、`EmTrajectory` 和控制层采样命令。该页面使用内置说明数据,帮助理解版本身份与数据边界;它不调用 OSQP、定位、硬件或真实控制器。
控制器只消费已验证完整轨迹的采样结果或执行层导出的 `TrajectoryControlCommand`。粗路径、平滑路径、地图和规划诊断属于观测、回放和问题定位证据链,不是逐周期的底盘命令。
```
- [ ] **Step 4: Run final checks**
Run `pwsh -NoProfile -File ClumsyPilot/tests/verify_trajectory_planning_flow_demo.ps1` and `dotnet run --project ClumsyPilot/ParkrobTrajplanner/Trajplanner_output/Tests/TrajectoryOutputDemo.Tests.csproj`.
Expected: verifier passes and existing output-demo self-check succeeds.
- [ ] **Step 5: Commit documentation and final verifier**
Run `git add -- ClumsyPilot/ParkrobTrajplanner/Trajplanner_output/README.md ClumsyPilot/tests/verify_trajectory_planning_flow_demo.ps1` followed by `git commit -m "docs: explain trajectory planning flow demo"`.
## Plan self-review
- Spec coverage: Tasks 12 cover offline behavior, five-stage navigation, fixed-coordinate map, planning artifacts, version identity, playback, gear-switch behavior and control-command contract. Task 3 makes the Demo discoverable and separates observability data from controller inputs.
- Placeholder scan: no task relies on unspecified files, functions, test expectations or external services.
- Type consistency: JavaScript and verifier use exactly `SignedLongitudinalVelocity`, `YawRate`, `Direction`, `RequestDirectionChange`, `HoldBrake`, `IsTrajectoryComplete`; README names the same boundary.