Files
osmWorkflow/.trellis/tasks/08-24-v2x-realtime-cross-fidelity/prd.md
que01 bc845444bb fix: restore live V2X signal and vehicle fidelity in Cesium preview
The ported overlay used the correct REST paths but lost the data handling
from the source dashboard's live-intersection view (HologramCross), so
signals rendered permanently red and vehicles often never appeared.

- Lamp status codes now follow the dashboard dictionary (11/21/22/23/31).
  The previous 2/3 reading made every real push fall through to red. The
  dictionary lives only in the overlay; the preview consumes normalized
  {nodeKeys, color, countDown} entries so the two copies cannot drift.
- Bind V2X phases to native signal heads geometrically. The runtime
  document has no phaseNo, so the old lookup fell back to signal.id and
  never matched, leaving the dynamic assembly dark. Travel heading is
  recovered as faceHeadingDegrees + 180, per the generator's
  mast = travel - 90 / face = travel + 180. Verified 7/7 exact matches
  against the fengshu-er-road runtime document.
- A phase now lights every approach it drives; the phase -> single entity
  map silently overwrote all but the last.
- Drive the countdown assets from the push's countDown field.
- All three sockets heartbeat every 30s and reconnect with backoff,
  replaying their subscription frame. Without this the service dropped
  the connection and the scene emptied after about a minute.
- The OBU socket sends its bounds frame on connect and on camera move;
  it previously sent nothing at all.
- Vehicles are swept when a push goes stale and their slots reused, so
  they no longer accumulate as ghosts. Models follow the dashboard's
  car_obu.glb / ${type}${subType}.glb naming.
- Parse vehicle pushes leniently, since the dashboard uses saferEval and
  the payload is not guaranteed to be strict JSON. Failures are counted
  and surfaced rather than dropped; no eval is introduced.
- Drop FlowTravelRatio/queryListWeek, which is not part of this view.

Also corrects a stale spec rule that required vehicleModelNames to be
empty. Live V2X vehicles need packaged models; the real invariant is no
generated routes or traffic simulation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 09:20:50 +08:00

5.8 KiB
Raw Blame History

还原 V2X 实时路口信号灯与车辆展示

Goal

v2x_web dashboard「实时路口」(HologramCross) 的实时数据行为完整搬到本项目的 Cesium 预览中,使 outputs/<area>/…-cesium-preview.html 在登录后能持续、正确地显示 信号灯相位灯色与倒计时OBU / 目标识别车辆

当前实现Codex 移植)接口地址是对的,但数据处理与渲染层基本失真,实际效果是:灯永远红、车可能一辆都不出现、 出现后也不消失、连接几十秒后被服务端断开。本任务修复这条链路。

Source of Truth

参照实现(只读,不修改): /Users/que01/Project/v2x_web/applications/dashboard/src/views/dashboard/components/Content/Map/HologramCross/

  • components/CrossTrafficLights3D.vue — 信号灯link 相位、WS 订阅、灯色/倒计时
  • components/utils.ts — 灯色状态字典、航向角计算
  • components/CrossCars/hooks/useObuCars.ts — OBU 车辆
  • components/CrossCars/hooks/useTargetCars.ts — 目标识别车辆
  • components/CrossCars/type.ts — 车辆数据结构

Requirements

R1 WebSocket 连接层对齐

  • 三个 socketsignal / obuPosition / targetPosition)均按源项目发送心跳 {"heartBeat":"ping"},间隔 30000ms。
  • 断线自动重连重连后重新发送各自的订阅消息signal 发 junctionIdtarget 发 deviceIdobu 发 bounds
  • 页面 visibilitychange 回到可见时行为不得导致重复连接堆积;dispose() 必须清掉心跳与重连计时器。

R2 信号灯灯色映射修正

  • 采用源项目 utils.ts 的状态字典:11=灭灯 21=红 22=黄 23=绿 31=其他
  • 现有 lampColor()overlaylampColorName()cesium-preview.js)中基于 2/3 的判断必须移除。
  • 未知状态码按「其他/灭灯」处理,不得静默落到红色。

R3 相位到原生信号灯的映射

  • traffic-signals.json 中不存在 V2X phaseNo(只有 phaseGroup: 0),当前回退到 signal.id 导致永不匹配。 必须建立一条真实可用的 V2X phaseNo → 原生信号灯头的映射。
  • 映射结果必须可诊断面板要能显示「N 个相位已绑定 / M 个未绑定」。
  • 允许区域配置提供显式覆盖映射。

R4 一个相位可点亮多条进口道

  • 同一 phaseNo 对应的所有 link / 信号灯头都要被点亮,当前 Map<phase, entity> 的覆盖行为必须消除。

R5 倒计时

  • 使用推送中的 countDown 字段(源项目 phaseValue['time'] = signal.countDown),驱动预览中已有的 countdown 资产或等效显示。

R6 车辆订阅正确建立

  • OBU socket 连接后必须发送订阅消息(源项目 send(bounds || '')),相机视野变化时发送 {"bounds": "<lng,lat;…>"}
  • target socket 连接后发送 {"deviceId": "<ids joined by comma>"},无配置时发送 {"deviceId": null}

R7 车辆生命周期

  • 按源项目实现超时隐藏:超过 interval * 1.5 未更新的车辆隐藏并可复用槽位;interval 取自推送体, 0 时回退 500
  • socket 断开时清空车辆列表。
  • 车辆位置更新使用推送间隔做平滑插值,避免逐帧跳变。

R8 车辆模型命名对齐

  • OBU 固定使用 car_obu.glb 语义的模型槽;目标识别车辆使用 ${type}${subType}.glb 语义的模型槽。
  • 包内缺少对应模型时回退到默认车模型,并在面板提示,不得静默显示错误车型。

R9 推送体解析健壮性

  • 源项目对两个车辆 socket 使用 saferEval 而非 JSON.parse,说明载荷不保证严格 JSON。
  • 解析必须容忍非严格 JSON且解析失败要计数并在面板可见不得整条静默丢弃。

R10 范围纠正

  • /facilities/api/FlowTravelRatio/queryListWeek(周流量比)不属于「实时路口」,从实时加载链路移除。

Non-Goals

  • 不移植 AMap 底图 / 矢量瓦片图层(linkVectorHdMapTileUrl)。
  • 不移植 CrossDevices/Model3D.vue 的 3D 杆件模型;设备维持点位显示(可后续独立任务)。
  • 不移植 useV2XEvents 的 V2X 事件气泡。
  • 不改变原生包产物GLB / metadata / traffic-signals.json 的生成逻辑)。

Constraints

  • 不得提交上游地址、账号、令牌、AMap keyv2xPreview 配置保持非敏感。
  • 令牌只存 sessionStorage,页面始终从登录门进入。
  • 坐标契约不变V2X 数据 GCJ-02进 Cesium 前转一次 WGS84原生数据不得二次转换。
  • v2xPreview.enabled 默认 false,关闭时生成页不含 V2X 面板。
  • 生成的预览为静态页无构建步骤overlay 保持零依赖 IIFE。

Acceptance Criteria

  • AC1 三个 socket 均可见 30s 心跳;模拟服务端在 60s+ 后连接仍存活。
  • AC2 单测覆盖灯色映射:21→红 22→黄 23→绿 11→灭 31→其他,且 2/3 不再被当作黄/绿。
  • AC3 单测覆盖相位映射:给定 V2X link 相位与 traffic-signals.json,输出的绑定数 > 0 未绑定项被明确列出。
  • AC4 单测覆盖同相位多进口道:一个 phaseNo 对应 2 条 link 时,两条都被点亮。
  • AC5 单测覆盖车辆超时:注入两次推送并推进时间超过 interval*1.5,车辆转为不可见。
  • AC6 单测覆盖 OBU/target 订阅消息:连接后发出的首帧内容与源项目一致。
  • AC7 单测覆盖非严格 JSON 推送体能被解析,且失败计数可读。
  • AC8 npm run test:v2x-cesium-previewtest:v2x-preview-servertest:preview-assets 全绿。
  • AC9 真机(npm run serve:v2x-preview 接真实上游)登录后可见:信号灯随相位变色并显示倒计时、 车辆出现并移动、离开后消失。此项由开发者人工确认。
  • AC10 v2xPreview.enabled=false 重新生成后,页面不含 V2X 面板,包产物字节不变。