bev-stack
ActiveA bird's-eye-view perception viewer built around one canonical scene contract: backends adapt datasets and models, the renderer only ever sees SceneFrames.
One contract, many backends
Every perception team ends up with a zoo of visualizers: one per dataset, one per model, each with its own coordinate-frame bugs. bev-stack is my answer: a single canonical SceneFrame contract that decouples data providers from rendering entirely.
Backend adapters (nuScenes, detector outputs, tracker outputs, BEV fusion results) each translate their world into SceneFrame JSON. Dataset-specific coordinate transforms live only in those adapters, enforced by schema contract tests. The TypeScript web viewer consumes SceneFrames and nothing else: ego vehicle, object boxes, HD-map context, range rings, and a stats HUD on a dark, driving-console-style canvas.
Why this architecture
The boring-sounding decision — “the renderer never sees dataset coordinates” — is the entire point. It means:
- A new dataset is a new adapter, not a new frontend.
- Model predictions and ground truth render through the same path, so comparing them is trivial rather than a project.
- Coordinate-frame conventions are documented and tested in exactly one place. (Anyone who has debugged a BEV visualizer knows why.)
Status
Actively being built. Working today: the SceneFrame schema and contract tests, the nuScenes adapter, and the web viewer rendering ground-truth scenes; that’s what’s looping in the clip above. On the bench next: streaming playback, detector/tracker overlays, and side-by-side prediction-vs-ground-truth views.