From dc3d072343e25e1bdd9b08dae8f985b412d158a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E8=96=84=E4=BA=91?= Date: Wed, 5 Aug 2026 22:39:26 +0800 Subject: [PATCH] docs: design EM observation web visualization --- ...em-observation-web-visualization-design.md | 285 ++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 docs/superpowers/specs/2026-08-05-em-observation-web-visualization-design.md diff --git a/docs/superpowers/specs/2026-08-05-em-observation-web-visualization-design.md b/docs/superpowers/specs/2026-08-05-em-observation-web-visualization-design.md new file mode 100644 index 0000000..945b397 --- /dev/null +++ b/docs/superpowers/specs/2026-08-05-em-observation-web-visualization-design.md @@ -0,0 +1,285 @@ +# EM 轨迹闭环观察与独立网页可视化设计 + +## 1. 背景与目标 + +现有 `TrajectoryObservationMovementTest` 从 MDCS 读取实时定位和带符号纵向速度,重复执行 EM 规划并显示最新轨迹。它是规划观察闭环,不向底盘、转向、电机、制动或档位接口发送命令。 + +EMPlanner 已修正两类纵向滚动规划语义: + +1. `RollingContinuation` 的滚动视界末点不再被强制当作静止停车点。 +2. jerk 变量只对应真实相邻时间节点之间的区间,不为滚动轨迹最后一个点之后不存在的后继点施加或展示虚假的 jerk 约束。 + +本次工作修改 MovementTest 观察任务,使实车环境可以直接验证这些语义;同时新增可复用、可独立升级的本机网页可视化类库。网页提供全局路径、方向分段、LS、ST、曲率、速度、加速度、加加速度、规划配置及周期历史。现有测试继续保持 `OBSERVE_ONLY`。 + +## 2. 范围与非目标 + +### 2.1 范围 + +- 保持实车定位/速度输入和滚动重规划,不增加任何车辆控制输出。 +- 支持完整多方向段观察,在可靠确认车辆实际运动方向后顺序推进至下一段。 +- 在鸟瞰图中显示完整全局路径,并高亮当前 EM 规划方向段及本轮时域覆盖区间。 +- 增加独立 `TrajectoryPlanningVisualization` 类库,供当前及未来规划测试复用。 +- 提供只监听本机回环地址的实时网页看板。 +- 保留原生 Painter 作为显式可选的兼容显示方式。 +- 保留用户已调整的 MovementTest 默认运行参数,并同步设置对象、测试与文档: + - `SolverTimeoutSeconds = 5.0 s` + - `MaximumOsqpIterations = 100000` + - `TimeHorizonSeconds = 2.0 s` + - `OutputTimeStepSeconds = 0.10 s` + +### 2.2 非目标 + +- 不实现轨迹跟踪、档位控制、底盘写入或自动驾驶闭环。 +- 不开放局域网或公网访问。 +- 不用网页按钮强制切换方向段。 +- 不记录无限历史,不默认写入磁盘,不实现实验回放文件格式。 +- 不修改 EMPlanner 的约束、权重、容差或已确认的滚动规划语义。 + +## 3. 总体架构 + +新增独立类库: + +```text +ClumsyPilot/TrajectoryPlanningVisualization/ +├── TrajectoryPlanningVisualization.csproj +├── Contracts/ # 不可变快照、曲线、配置和状态 DTO +├── Runtime/ # 回环 HTTP/SSE 服务、最新帧和有界历史 +└── Web/ # 内嵌 HTML/CSS/JavaScript 科研风前端 +``` + +现有观察模块新增 EM 适配层: + +```text +ClumsyPilot/ParkrobTrajplanner/tarjplanner_movementtest/ +├── TrajectoryObservationVisualizationAdapter.cs +├── TrajectoryObservationSegmentTracker.cs +└── 现有 MovementTest、Pipeline、Contracts、Diagnostics、Presentation +``` + +依赖方向固定为: + +```text +EM / Map / PathSmoothing / MovementTest + │ + ▼ +TrajectoryObservationVisualizationAdapter + │ 只发布通用不可变快照 + ▼ +TrajectoryPlanningVisualization + │ + ▼ +localhost browser +``` + +可视化类库不得引用 EMPlanner、MDCS、ClumsyCore、Painter 或 MovementTest。MovementTest 负责生命周期和浏览器打开行为;类库只返回本机访问 URI。 + +主项目通过 `ProjectReference` 引用新类库,并排除对子项目源码的重复编译。插件发布流程必须包含新增程序集及其必要依赖。网页资源作为程序集嵌入资源发布,不依赖 CDN、Node.js 或外网。 + +## 4. 可视化类库公共边界 + +类库只暴露三个主要生命周期操作: + +```csharp +visualization.Start(options); +visualization.Publish(snapshot); +visualization.Stop(); +``` + +`Start` 返回包含随机会话令牌的完整本机 URI。`Publish` 必须是非阻塞操作:用原子替换保存最新不可变快照,不等待序列化、网络、浏览器或绘图。`Stop` 取消服务任务、关闭连接并释放端口;重复调用安全。 + +快照分为两类: + +- 静态快照:地图边界、障碍物、全局粗路径、Local G2 路径、全部方向段、换向点和冻结后的生效配置。每次会话只生成并传输一次。 +- 动态快照:实车状态、当前段、当前/上一轮轨迹、当前采样点、本轮规划结果、交接指标和诊断摘要。 + +服务只绑定 `127.0.0.1`。页面和事件接口均校验随机会话令牌。服务最多接受两个浏览器客户端,额外连接被拒绝。前端静态资源通过普通 HTTP 获取,动态帧通过 Server-Sent Events 发送;客户端断开或读取缓慢时丢弃旧帧,不对发布者形成反压。 + +## 5. 资源与性能约束 + +- 默认网页刷新率为 `10 Hz`,与 `ObserverPeriodSeconds` 解耦。 +- 最新动态帧容量固定为 `1`;新帧覆盖旧帧。 +- 只保留当前轮和上一轮的完整轨迹点。 +- 周期历史默认保留最近 `60` 轮,历史项只含摘要,不含完整轨迹。 +- 地图占用信息、全局路径、方向段和配置不进入重复动态帧。 +- 没有浏览器客户端时不重复序列化相同动态帧。 +- 网页关闭或变慢不能改变重规划周期、求解器超时或规划结果。 +- `EnableWebVisualization=false` 时不启动服务、不创建网页快照或历史缓冲。 +- 任何网页服务、快照转换或前端异常均被隔离:记录一次中文诊断并关闭本次网页输出,规划观察继续运行。 + +## 6. MovementTest 配置 + +新增公开字段: + +```text +EnableWebVisualization = false +AutoOpenWebVisualization = true +WebVisualizationPort = 0 +WebRefreshRateHz = 10 +VisualizationHistoryCycleLimit = 60 +EnableNativePainterVisualization = false +DirectionConfirmationSpeedMetersPerSecond = 0.02 +DirectionConfirmationSamples = 3 +GearSwitchProjectionToleranceMeters = 0.50 +GearSwitchStopHoldSeconds = 0.20 +``` + +校验规则:开关字段不需数值校验;端口为 `0` 或 `1024..65535`;刷新率、历史容量、速度阈值、投影容差和等待时间必须为有限正值;连续确认样本数必须为正整数。 + +端口为 `0` 时选择空闲回环端口。启动成功后,完整带令牌 URI 同时写入 MDCS UI 状态和控制台;`AutoOpenWebVisualization=true` 时由 MovementTest 尝试打开默认浏览器。打开失败只报告地址,不中止观察。 + +原生 Painter 与网页独立控制。`EnableNativePainterVisualization=false` 时不取得或刷新 World、LS、ST Painter,避免与浏览器重复绘图。两种显示都关闭时,规划循环和控制台诊断仍工作。 + +## 7. 多方向段观察状态机 + +现有硬编码 `segmentIndex = 0` 改为只允许顺序前进的活动段状态机。 + +### 7.1 正常规划 + +- 活动段初始为第 `0` 段。 +- 每轮请求使用活动段索引、方向及同段上一条已发布轨迹。 +- 只有同一 `SegmentIndex` 和 `TravelDirection` 的上一条轨迹可以作为软参考。 +- 网页与原生 Painter 均从同一个活动段状态读取高亮和 LS/ST 投影对象。 + +### 7.2 换向确认 + +到达 `GearSwitchApproach` 后: + +1. 车辆位姿必须能在 `GearSwitchProjectionToleranceMeters` 内投影到换向点邻域。 +2. 带符号实际速度绝对值必须不超过 EM 生效配置的 `StopSpeedToleranceMetersPerSecond`,并持续至少 `GearSwitchStopHoldSeconds`。 +3. 状态机进入“等待下一方向实际运动”状态。 +4. 随后实际速度绝对值必须至少为 `DirectionConfirmationSpeedMetersPerSecond`,符号与下一段一致,且车辆可投影到下一段起始区域。 +5. 条件连续满足 `DirectionConfirmationSamples` 次后,活动段从 `N` 切换到 `N+1`。 + +零速时方向不明确,状态机保持原段;瞬时反号、位置不匹配、丢失定位或不连续样本都会清零确认计数。状态机不得跳段、自动回退或跨越两个换向点。 + +切段时创建新的分段规划协调状态,清除可执行的旧段发布轨迹;旧轨迹仅作为网页历史证据保留,不传入新段 EM 请求。新段首次规划前网页显示“已确认换向,等待下一段首条轨迹”。 + +## 8. 网页信息架构与视觉规范 + +界面采用已确认的科研绘图风:纯白背景、浅灰细网格、细坐标轴、`0.8–1.2 px` 曲线、低饱和语义色和论文式多子图。当前轨迹为蓝色实线,上一轮为灰色虚线,交接点和换向点为橙色,红色只表示真实越界或失败。 + +页面说明、状态、告警、按钮和配置名称使用中文。坐标变量、单位和数学符号保留领域惯例,例如 `s (m)`、`t (s)`、`κ (m⁻¹)`、`v (m/s)`、`a (m/s²)`、`j (m/s³)`。 + +### 8.1 路径总览 + +- 地图、障碍物、粗路径、完整 Local G2 全局路径和实车位姿。 +- 已完成方向段为灰色细实线,当前段为蓝色细实线,未来方向段为浅灰虚线。 +- 换向点使用带顺序编号的橙色菱形。 +- 当前 EM 距离/时间视界实际覆盖区间使用更深蓝色叠加。 +- 当前和上一轮 EM 轨迹叠加,并以橙色标出绝对时间交接位置。 +- 显示活动 `SegmentIndex`、前进/倒车方向、纵向模式、终端类型、规划耗时和轨迹年龄。 + +### 8.2 LS / ST + +- `l(s_ref)`:将当前已发布 EM 轨迹投影到完整活动方向段后,横向偏移随共享方向段 `ReferenceS` 的变化。 +- `PathS(t)`:当前规划时域内的实际局部 `PathS` 随 `TimeFromStart` 的变化,这是 ST 求解结果使用的坐标。 +- 两类横轴必须使用不同标签,网页不得把方向段 `ReferenceS` 与每轮从局部起点累计的 `PathS` 混为一谈。 +- 标明方向段索引、方向、边界类型和投影失败数。 +- LS/ST 只展示当前活动方向段,不跨换向边界拼接。 + +### 8.3 曲率与运动学 + +- `κ(s)` 与 `κ(t)`。 +- `v(t)`、`a(t)`、`j(t)` 与 `yaw rate(t)`。 +- 对应生效限制以细虚线绘制。 +- `j[i]` 表示真实区间 `[tᵢ,tᵢ₊₁)`;jerk 曲线点数严格为轨迹点数减一。最后一个轨迹点不绘制伪造的 `j=0`,而标注“末点后无时间区间”。 +- 同图展示实际带符号车速与当前选中轨迹点速度。 + +### 8.4 周期历史 + +最近 `VisualizationHistoryCycleLimit` 个周期展示:周期号、时间、成功/失败、是否发布、规划耗时、段索引、方向、纵向模式、终端类型、末端速度、末端加速度和失败原因摘要。 + +### 8.5 生效配置 + +配置页只展示本次冻结后真正传给规划器的值,不读取启动后的可编辑字段。每个条目包含中文名称、原始字段名、数值和单位: + +- 调度:重规划周期、ST 时域、输出步长、距离视界、求解超时、交接前视时间和状态最大年龄。 +- OSQP:最大外层迭代、最大 OSQP 迭代、绝对/相对/严格残差容差、warm start、polish 和 native verbose。 +- 车辆与安全:长、宽、安全余量、最大曲率或最小转弯半径。 +- 纵向限制与权重:前进/倒车速度、加速度、减速度、jerk、横向加速度、曲率变化率、停车速度容差、零速保持时间及全部 ST 权重。 +- 横向限制、走廊参数和全部 LS 权重。 +- 地图边界、分辨率、障碍物数量和快照版本。 +- 当前地图、参考路径、车辆状态、当前轨迹和上一轨迹 ID。 +- 可视化刷新、历史容量和换向确认参数。 + +## 9. 滚动规划专项诊断 + +网页必须把规划语义与数值结果分开显示: + +- `RollingContinuation` 或 `ApproachStopBoundary`:显示“滚动末端停车硬约束:未启用”,并展示实际末端 `v/a`。滚动末速为零不单独判定失败,因为车辆状态或最优结果仍可能产生零速;关键证据是纵向模式没有启用精确停车约束。 +- `ExactStopAtBoundary`:显示真实 Goal 或 GearSwitch 停车锚点、稳定段起点和零速稳定区间。 +- jerk 图只显示真实区间,末点显示“不适用”,避免把缺失的末端后继区间解释为加加速度约束。 +- 当前轮和上一轮按 `EffectiveAtUtc + TimeFromStart` 对齐,在交接时刻插值并展示世界坐标 `Δposition`、共享方向段上的 `ΔReferenceS`、`Δv` 和 `Δa`。不得直接比较两轮各自从局部起点累计的 `PathS`;任一轨迹无法投影到共享方向段时,`ΔReferenceS` 显示“不可用”。 +- 交接指标仅作为观察诊断,不改变规划、发布或执行状态。 + +## 10. 错误处理与状态显示 + +- 可视化启动失败:记录一次中文错误,规划观察继续。 +- 快照中单个字段不可用:对应值显示“不可用”,其他图继续刷新。 +- 浏览器超过两个预期刷新周期没有收到新帧:显示“数据已过期”及最后时间戳,不把旧值伪装成实时状态。 +- 换向确认失败:保持当前段,显示位置、停车保持、速度方向或连续样本中未满足的条件。 +- EM 新周期失败:保留上一条成功轨迹,醒目显示本轮状态与未改写的原始失败原因。 +- 服务或前端异常:本次网页输出熔断关闭,不自动循环重启。 +- `TestStop()`:取消规划观察、停止发布、关闭 HTTP/SSE、释放端口;仍连接的页面显示“会话已结束”。 + +## 11. 测试策略 + +### 11.1 独立可视化类库 + +新增独立验证宿主,覆盖: + +- 类库不引用 MDCS、ClumsyCore、Painter 或 EMPlanner。 +- 快照不可变与 JSON 序列化稳定。 +- `Publish` 非阻塞且最新帧容量为 `1`。 +- 历史严格受容量限制。 +- 服务只监听回环地址并校验令牌。 +- 慢客户端不阻塞发布者。 +- 静态快照不重复进入动态帧。 +- 启停、重复停止和端口释放。 +- 内嵌页面包含中文说明、科研坐标单位和所有必需页签。 + +### 11.2 EM Adapter 与观察任务 + +扩展 `EMPlannerVerificationHost` 的 `trajectory-observation` 检查: + +- 生效配置来自冻结快照,并包含本节规定的全部参数组。 +- MovementTest、settings 默认值和 README 对 `5.0 s / 100000 / 2.0 s / 0.10 s` 保持一致。 +- rolling、approach、exact-stop 三种模式映射正确。 +- jerk 区间数等于轨迹点数减一,末点没有伪造区间。 +- 当前/上一轮绝对时间对齐和 `Δposition/ΔReferenceS/Δv/Δa` 计算正确,且不直接比较两轮局部 `PathS`。 +- 多方向路径完整输出,活动段和当前视界高亮。 +- 换向状态机必须满足位置、停车保持和连续方向样本才顺序推进。 +- 切段后不复用旧方向段轨迹。 +- 可视化关闭时不启动服务或构造快照。 +- 网页异常不会终止观察循环。 +- 源码审计继续确认没有底盘写方法。 + +### 11.3 集成与实车验收 + +运行: + +```powershell +dotnet run --project ClumsyPilot/tests/TrajectoryPlanningVisualizationVerificationHost/TrajectoryPlanningVisualizationVerificationHost.csproj +dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- trajectory-observation +dotnet run --project ClumsyPilot/tests/EMPlannerVerificationHost/EMPlannerVerificationHost.csproj -- em-all +dotnet build ClumsyPilot/ClumsyPilot.csproj -p:ExcludeLegacyAutoAvoidance=true +``` + +实车观察清单: + +1. 开启网页、关闭原生 Painter,确认页面地址、令牌和中文科研风界面。 +2. 确认全局路径所有方向段可见,当前段和本轮规划视界高亮。 +3. 观察 `RollingContinuation -> ApproachStopBoundary -> ExactStopAtBoundary`,确认滚动末点未显示停车硬约束。 +4. 确认 `j(t)` 最后一个区间结束于最后一个轨迹点之前,不出现虚假 point-21 后继区间或 `JerkLimitExceeded`。 +5. 在真实换向场景确认状态机先等待停车,再以连续实际运动方向样本推进至下一段。 +6. 断开或关闭浏览器,确认规划周期和耗时无异常变化。 +7. 停止 MovementTest,确认服务退出、端口释放且无底盘命令。 + +## 12. 完成标准 + +- 独立类库、EM Adapter、多段观察和网页看板均按上述边界实现。 +- 所有自动化验证通过,主项目构建成功。 +- 页面使用中文说明和科研绘图规范,数学符号与单位准确。 +- 滚动末端语义、jerk 区间语义和换向分段高亮均能由页面直接观察。 +- 可视化关闭或失败时不改变 EM 规划行为。 +- 源码和运行时证据均证明 `OBSERVE_ONLY` 不变。