feat: add live V2X Cesium preview overlay

This commit is contained in:
2026-08-24 14:20:16 +08:00
parent 71ba536c7c
commit ee273c5cd6
20 changed files with 760 additions and 3 deletions

View File

@@ -55,6 +55,7 @@ cp config/examples/template.json config/areas/my-area.json
| `osm2streets` | | 见下 | 透传给 osm2streets 的选项 |
| `blender` | | 见下 | Blender 侧选项 |
| `nativeRoad` | | 见下 | 原生道路编译选项 |
| `v2xPreview` | | 见下 | 可选的 Cesium 预览实时 V2X 叠加设置 |
| `compress` | | 见下 | 默认交付压缩阶段的 GLB 压缩选项 |
| `budget` | | 见下 | 区域 GLB 性能与体量预算 |
| `outputs` | | 从 `id` 推导 | 输出路径覆盖,逃生舱 |
@@ -146,6 +147,24 @@ cp config/examples/template.json config/areas/my-area.json
| `junctionTemplates.clusters[].cornerRadiusMeters` | `12`425 | 仅 `complex-junction-v1`:相邻进口夹角处路缘圆角的半径。圆角切于两侧最外道路边缘,只补齐夹角处的路面,不改变 connector、信号或停止线。 |
| `junctionTemplates.clusters[].outerRadiusExtraMeters` | `18`1835 | 仅 `complex-junction-v1`:路口中心到外部进口交接边界的额外半径。用于让圆角包住角部斑马线;未配置时保持原有 18 m。 |
### `v2xPreview`
这是 Cesium 验证预览的可选实时叠加层,不进入发布的 `package/`。默认值:
```json
{
"enabled": false,
"apiBaseUrl": "/api",
"wsBaseUrl": "/websocket",
"crossCode": ""
}
```
`apiBaseUrl``wsBaseUrl` 应使用同源反向代理路径,不能写入私有上游主机、账号或令牌。
V2X 接口返回的地图数据是 GCJ-02浏览器预览在创建 Cesium entity 前一次性转为 WGS84
而 native package 的 WGS84/ENU 契约保持不变。详见
[`docs/v2x-cesium-preview.md`](../../../docs/v2x-cesium-preview.md)。
### `compress`
完整构建和显式 `--stages compress` 都使用此配置。默认压缩链是 texture resize + WebP

View File

@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}

View File

@@ -0,0 +1,80 @@
# Design: Live V2X Cesium Intersection View
## Architecture
The native pipeline remains the source of static scene geometry and package
placement. The existing Cesium preview gains an operations overlay and a compact
V2X sign-in gate. The implementation stays in the current generated static
preview architecture and does not import the source dashboard's Vue, AMap, or
Three dependencies.
The generated preview runtime is divided into four browser concerns:
1. `auth`: presents the V2X sign-in form, MD5-hashes the password to match the
source contract, stores a successful token in `sessionStorage`, and clears it
on sign-out or authorization failure.
2. `v2x-client`: owns configured REST/WS origins, adds the raw `Authorization`
request header, normalizes the source API envelope, and reports a capability
status rather than blanking the preview if an optional resource fails.
3. `coordinates`: labels external values as GCJ-02 and native values as WGS84 or
ENU. It converts V2X GCJ-02 positions to WGS84 exactly once before Cesium
entity creation; the existing native package placement contract is unchanged.
4. `cesium-v2x-overlay`: adds V2X links, devices, pole/configuration evidence,
metrics, and real signal phase updates to the existing Cesium viewer, with
independent visibility controls and diagnostics.
## Data Flow
```text
V2X sign-in -> session token
| |
| +--> Authorization header / WS query parameter
v
configured V2X REST + WS endpoints -> GCJ-02 V2X geometry, devices, metrics, lamps
|
v
GCJ-02-to-WGS84 adapter
|
native package + route/signal descriptors -> WGS84/ENU -> existing Cesium viewer
^
|
Cesium V2X operations overlay
```
## Endpoint Contract
The first delivery consumes `queryCrossLinkInfo`, `queryPoles`, bound-device,
cross-device-config, and weekly flow-ratio APIs. It subscribes to
`/network/ws/network/signal` only after link data establishes usable phases.
Endpoint host/prefixes and selected `crossCode` are deployment configuration. A
development proxy forwards REST and WebSocket traffic so the browser never needs
a hard-coded private origin.
## Coordinate Contract
| Producer | Source CRS | Consumer rule |
| --- | --- | --- |
| Native compiler package, traffic signals, route descriptor | WGS84 / local ENU | Preserve the existing Cesium package placement and WGS84 entity contracts. |
| V2X dashboard link, road, device, and pole data | GCJ-02 | Convert to WGS84 once before creating Cesium entities. |
| High德 reference GeoJSON | GCJ-02 | Calibration-only compiler input; no runtime map or SDK dependency. |
The existing `gaode-junction-reference` inverse conversion is an appropriate
source for the V2X adapter. It will be factored or safely reused only when doing
so preserves its compiler behavior and test coverage.
## Compatibility And Failure Handling
- Existing Cesium preview and its static-only workflow remain usable.
- The V2X overlay is optional and starts only after successful sign-in.
- An expired token returns the user to sign-in and removes live entities rather
than presenting stale data as current.
- A REST/WS capability failure is shown in diagnostics; native scene, signals,
and traffic simulation remain usable.
- Removing the optional overlay/support files restores current preview behavior
without changing static package contracts.
## Security
`sessionStorage` limits the upstream token to the current tab session. Credentials
are never persisted. Configuration examples use placeholders, and deployment
documentation requires an HTTPS same-origin reverse proxy for V2X API/WS traffic.

View File

@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}

View File

@@ -0,0 +1,40 @@
# Implementation Plan: Live V2X Cesium Intersection View
1. Read preview and pipeline specifications, then add a focused V2X preview
configuration. Keep secrets and private origins out of defaults and tracked
area configuration.
2. Add browser-safe GCJ-02-to-WGS84 conversion and focused tests for source
coordinate labels and prevention of duplicate conversion. Preserve the current
compiler reference conversion behavior.
3. Implement the V2X browser client: login, session token lifecycle, REST
envelope handling, capability errors, and signal WebSocket lifecycle.
4. Extend the generated Cesium preview with V2X entities and operations controls
for links, devices, poles/configuration, metrics, and live signal state.
5. Add a local development/proxy configuration example and deployment
documentation for V2X REST/WS proxying. Do not add an AMap key, SDK, or page.
6. Add focused tests for HTML generation, configuration escaping, login/request
construction, coordinate conversion, source-layer diagnostics, and graceful
unavailable/auth states. Run existing preview and native-road regressions.
7. Validate in a browser with a real V2X account and configured proxy: sign in,
inspect aligned native/V2X features, verify REST panels and signal updates,
then verify sign-out/token expiry behavior.
## Validation Commands
```bash
node --check scripts/lib/area-preview.js
node --check scripts/lib/cesium-preview.js
npm run test:gaode-junction-reference
npm run test:preview-assets
npm run test:native-preview-traffic
npm run test:traffic-signals
npm run road:compile -- --config config/areas/fengshu-er-road.json
npm run build:area -- --config config/areas/fengshu-er-road.json --stages preview
```
## Review Gates
- Confirm no token, account, or private host is committed.
- Verify V2X GCJ-02 coordinates convert once before Cesium use.
- Verify the existing native WGS84/ENU scene contract remains unchanged.
- Verify the current Cesium preview works without V2X configuration or sign-in.

View File

@@ -0,0 +1,81 @@
# Integrate live V2X intersection data into Cesium preview
## Goal
Provide a Cesium-based operational view of the current complex intersection in
this repository. It must show live data from the existing V2X platform while
retaining the native road compiler's WGS84/ENU output as the geometry authority.
## Confirmed Facts
- The source dashboard's holographic-intersection view uses V2X REST resources for
road/link geometry, device bindings, poles, configuration, traffic metrics, and
a token-authenticated signal WebSocket.
- The dashboard development proxy targets `172.16.1.159:50400` under `/api`,
`/websocket`, and `/vectortile`; the application sends the upstream token as the
`Authorization` header.
- The source dashboard uses AMap and therefore its road/link data is GCJ-02. Its
road-network exporter converts that data from GCJ-02 to WGS84 before export.
- This repository's native road, signal, and simulation artifacts are WGS84/ENU.
- The target is the existing Cesium preview, not AMap. High德 data in this
repository is a calibration/reference GeoJSON only, not a target runtime map.
- The requested page has a simple login gate; V2X data must remain real live
interface data, not copied mock data.
## Requirements
- R1: Add a Cesium-based complex-intersection operations view to this repository, protected by
a simple application login.
- R2: Integrate the real V2X REST endpoints used by the source dashboard, including
current intersection/link geometry, devices, poles/configuration, traffic metrics,
and signal state where upstream authorization permits it.
- R3: Keep the V2X platform credentials separate from the simple application login;
do not put a reusable upstream credential into browser source or committed files.
- R4: Treat V2X map-facing coordinates as GCJ-02. Treat native compiler artifacts
as WGS84/ENU, and convert V2X GCJ-02 coordinates to WGS84 exactly once before
adding them to Cesium.
- R5: Surface a clear unavailable/authentication state when live data cannot be
loaded while leaving the native complex-intersection view usable.
- R6: Make endpoint origin, selected V2X intersection code, and authorization
mechanism deployment configuration rather than hard-coded source values.
## Candidate Upstream Resources
- `GET /network/api/link/network/queryCrossLinkInfo/{crossCode}`: intersection
link geometry and signal phase association.
- `GET /network/api/pole/network/queryPoles/{crossCode}`: pole and light placement
configuration.
- `GET /facilities/api/crossDevice/findDeviceByCrossCode/{crossCode}`: bound devices.
- `GET /facilities/api/crossDeviceConfig/{crossCode}`: target-device configuration.
- `GET /facilities/api/FlowTravelRatio/queryListWeek?code={crossCode}` and related
cross-monitor resources: operational metrics.
- `WS /network/ws/network/signal?authorization={token}`: live signal lamps.
## Acceptance Criteria
- [ ] A user can pass the local login gate and open the current complex-intersection
Cesium view.
- [ ] The page retrieves and renders live V2X data for a configurable intersection
code without source-dashboard runtime dependencies.
- [ ] The page identifies the coordinate reference of each source and visually
aligns native WGS84 geometry with V2X data converted from GCJ-02.
- [ ] A missing/expired upstream credential or unavailable service is visible and
does not make the native intersection view unusable.
- [ ] Upstream URL, intersection code, and credentials/tokens are excluded from
tracked application source and documented for deployment.
## Out Of Scope
- Copying the source dashboard's Vue, AMap/Three, or proprietary UI component stack.
- Building a full user/role management service.
- Replacing native road geometry or traffic-signal contracts with V2X data.
## Authentication Decision
- The page signs in to the upstream V2X service with the user-entered account,
posting `userName` and MD5-hashed `password` to
`/facilities/api/sys/login` through the configured API prefix.
- The returned token lives only in `sessionStorage`, is sent as the raw
`Authorization` header for REST requests, and is supplied as the
`authorization` WebSocket query parameter for the signal subscription.
- No default credentials, reusable token, or API secret may be committed.

View File

@@ -0,0 +1,26 @@
{
"id": "v2x-amap-intersection-data",
"name": "v2x-amap-intersection-data",
"title": "Integrate live V2X intersection data into AMap preview",
"description": "",
"status": "in_progress",
"dev_type": null,
"scope": null,
"package": null,
"priority": "P2",
"creator": "dingkang",
"assignee": "dingkang",
"createdAt": "2026-08-24",
"completedAt": null,
"branch": null,
"base_branch": "fengshu-er-road",
"worktree_path": null,
"commit": null,
"pr_url": null,
"subtasks": [],
"children": [],
"parent": null,
"relatedFiles": [],
"notes": "",
"meta": {}
}