Skip to content

Commit 8bf208c

Browse files
authored
docs: add Docusaurus documentation site (#185)
* docs: add Docusaurus documentation site with Lichtblick alignment - Switch from MkDocs to Docusaurus to align with Lichtblick docs framework - Add 10 documentation pages: home, getting started, panel settings, architecture overview, converter pipeline, caching, features, frame transforms, lanes/logical lanes reference, contributing - Reference Lichtblick documentation for shared concepts (extensions, message converters, 3D panel) instead of re-explaining them - Add GitHub Actions workflow for Pages deployment - Migrate existing docs/lanes.md and docs/logical-lanes.md to docs/reference/ with corrected image paths - Website lives in website/ with isolated package.json (no impact on extension dependencies) * docs: fix inaccuracies found during audit - Fix broken URL for asam-osi-utilities convert_osi2mcap.cpp (moved to cpp/examples/) - Move STOP-only admonition from Traffic Lights to Road Markings section - Clarify BB Center → Rear Axle transform is conditional on bbcenter_to_rear - Fix NONDRIVING lane color to match exact source value (111/255, 91/255) --------- Signed-off-by: jdsika <carlo.van-driesten@bmw.de>
1 parent c81f1da commit 8bf208c

20 files changed

Lines changed: 923 additions & 3 deletions

.github/workflows/docs.yaml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Deploy Documentation
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "docs/**"
8+
- "website/**"
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
pages: write
14+
id-token: write
15+
16+
concurrency:
17+
group: pages
18+
cancel-in-progress: false
19+
20+
jobs:
21+
build:
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v4
25+
26+
- uses: actions/setup-node@v4
27+
with:
28+
node-version: 20
29+
30+
- name: Install dependencies
31+
working-directory: website
32+
run: npm install
33+
34+
- name: Build documentation
35+
working-directory: website
36+
run: npm run build
37+
38+
- name: Upload artifact
39+
uses: actions/upload-pages-artifact@v4
40+
with:
41+
path: website/build
42+
43+
deploy:
44+
environment:
45+
name: github-pages
46+
url: ${{ steps.deployment.outputs.page_url }}
47+
runs-on: ubuntu-latest
48+
needs: build
49+
steps:
50+
- name: Deploy to GitHub Pages
51+
id: deployment
52+
uses: actions/deploy-pages@v5

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,7 @@ dist
117117

118118
# Playground
119119
.playground/
120+
121+
# Docusaurus
122+
website/build/
123+
website/.docusaurus/

docs/architecture/caching.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
---
2+
sidebar_position: 3
3+
---
4+
5+
# Caching
6+
7+
The converter uses a multi-layer caching system to avoid redundant work across frames. This is critical for performance — lane geometry and 3D models rarely change between frames but are expensive to rebuild.
8+
9+
## Cache layers
10+
11+
### Frame cache
12+
13+
**Purpose:** Skip entire conversion if the same message object arrives again with the same config.
14+
15+
| Property | Value |
16+
|----------|-------|
17+
| Structure | `Map<configSignature, WeakMap<GroundTruth, PartialSceneEntity[]>>` |
18+
| Key | Config signature (outer), message object reference (inner) |
19+
| Hit condition | Same config + same message object identity |
20+
| Invalidation | Outer map entry cleared when config signature changes |
21+
22+
The `WeakMap` allows garbage collection of message objects no longer referenced by the runtime.
23+
24+
### Lane boundary cache
25+
26+
**Purpose:** Reuse rendered lane boundary entities when the set of boundaries hasn't changed.
27+
28+
| Property | Value |
29+
|----------|-------|
30+
| Structure | `Map<string, PartialSceneEntity[]>` |
31+
| Key | Hash of all `lane_boundary[].id` values |
32+
| Hit condition | Same set of boundary IDs (regardless of data changes) |
33+
| Invalidation | Cleared on config change or when `caching` is disabled |
34+
35+
### Lane cache
36+
37+
**Purpose:** Reuse rendered lane entities when both lanes and their referenced boundaries are unchanged.
38+
39+
| Property | Value |
40+
|----------|-------|
41+
| Structure | `Map<string, PartialSceneEntity[]>` |
42+
| Key | Hash of all `lane[].id` values |
43+
| Hit condition | Boundary cache was hit **and** same set of lane IDs |
44+
| Invalidation | Cleared on config change; depends on boundary cache state |
45+
46+
:::note[Cache dependency]
47+
48+
The lane cache is only checked if the boundary cache was hit. This ensures coherence — if boundaries changed, lanes must be rebuilt even if their IDs are the same.
49+
50+
:::
51+
52+
### Logical lane boundary / lane caches
53+
54+
Same pattern as physical lane caches, for `LogicalLaneBoundary` and `LogicalLane` entities.
55+
56+
### Model cache
57+
58+
**Purpose:** Reuse loaded 3D model primitives across frames.
59+
60+
| Property | Value |
61+
|----------|-------|
62+
| Structure | `Map<string, ModelPrimitive>` |
63+
| Key | `defaultModelPath + model_reference` (full file path) |
64+
| Hit condition | Same model path |
65+
| Invalidation | Cleared on config change |
66+
67+
## Invalidation triggers
68+
69+
All caches are cleared when:
70+
71+
- Panel settings change (detected by comparing JSON-stringified config signatures)
72+
- The `caching` panel setting is `false` (geometry caches are bypassed entirely)
73+
74+
## Cache flow diagram
75+
76+
```
77+
New frame arrives
78+
79+
├── Config changed? → Clear ALL caches
80+
81+
├── Frame cache hit? → Return cached entities (skip everything)
82+
83+
├── Boundary IDs unchanged?
84+
│ ├── Yes → Reuse boundary entities
85+
│ │ └── Lane IDs unchanged? → Reuse lane entities
86+
│ └── No → Rebuild boundaries and lanes
87+
88+
├── Build remaining entities (moving objects, signs, etc.)
89+
90+
└── Update all caches
91+
```
92+
93+
## Performance characteristics
94+
95+
- **Best case** (frame cache hit): O(1) — returns cached array directly
96+
- **Static scene** (boundary/lane cache hits): Only moving objects, signs, and lights are rebuilt
97+
- **Config change**: Full rebuild of all entities (unavoidable)
98+
- **Typical frame**: Moving objects rebuilt (they change position), geometry reused from cache
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
---
2+
sidebar_position: 2
3+
---
4+
5+
# Converter Pipeline
6+
7+
This page describes the end-to-end conversion flow for `osi3.GroundTruth → foxglove.SceneUpdate`, the primary converter. For general information about message converters, see the [Lichtblick message converter guide](https://lichtblick-suite.github.io/docs/guides/create-message-converter).
8+
9+
## Pipeline stages
10+
11+
### 1. Configuration
12+
13+
The converter reads panel settings from `event.topicConfig` (typed as `GroundTruthPanelSettings`). If no config is provided, it falls back to `DEFAULT_CONFIG`.
14+
15+
A **config signature** (JSON-stringified config) is computed. If the signature differs from the previous frame, all caches are invalidated.
16+
17+
### 2. Host vehicle resolution
18+
19+
The host vehicle is identified by `message.host_vehicle_id.value`. If absent, a fallback from the SensorView wrapper is used. Warnings are emitted via `emitAlert()` for:
20+
21+
- Missing host vehicle ID (both sources)
22+
- Host vehicle ID not found in `moving_object` array
23+
- Divergence between GroundTruth and SensorView host vehicle IDs
24+
25+
### 3. Frame cache check
26+
27+
If caching is enabled, the converter checks a `WeakMap<GroundTruth, entities>` keyed by config signature. If the exact same message object was already converted with the same config, the cached result is returned immediately.
28+
29+
### 4. Deletion detection
30+
31+
For each entity type, the converter compares current-frame entity IDs against a stored `Set<number>` from the previous frame. Missing IDs generate `SceneEntityDeletion` entries with the current timestamp.
32+
33+
### 5. Entity building
34+
35+
Entities are built by feature modules in this order:
36+
37+
| Step | Feature | Condition | Builder |
38+
|------|---------|-----------|---------|
39+
| 1 | Moving objects | Always | `buildMovingObjectEntity()` |
40+
| 2 | Stationary objects | Always | `buildStationaryObjectEntity()` |
41+
| 3 | Traffic signs | Always | `buildTrafficSignEntity()` |
42+
| 4 | Traffic lights | Always | `buildTrafficLightEntity()` |
43+
| 5 | Road markings | Always (STOP only) | `buildRoadMarkingEntity()` |
44+
| 6 | Lane boundaries | `showPhysicalLanes` | `buildLaneBoundaryEntity()` |
45+
| 7 | Lanes | `showPhysicalLanes` | `buildLaneEntity()` |
46+
| 8 | Logical lane boundaries | `showLogicalLanes` | `buildLogicalLaneBoundaryEntity()` |
47+
| 9 | Logical lanes | `showLogicalLanes` | `buildLogicalLaneEntity()` |
48+
| 10 | Reference lines | `showReferenceLines` | `buildReferenceLineEntity()` |
49+
50+
### 6. Geometry cache reuse
51+
52+
Lane and boundary entities are expensive to rebuild. The converter uses geometry-aware caching:
53+
54+
```
55+
Compute hash of lane_boundary IDs
56+
→ If cached, reuse lane boundary entities (skip rebuild)
57+
→ If boundaries unchanged, check lane cache too
58+
→ Same logic for logical lanes/boundaries
59+
```
60+
61+
See [Caching](caching.md) for details.
62+
63+
### 7. State update
64+
65+
After building entities:
66+
67+
- Update `previousXyzIds` sets for next frame's deletion detection
68+
- Store current config and config signature
69+
- Populate frame cache and geometry caches
70+
71+
### 8. Return
72+
73+
```typescript
74+
{
75+
deletions: SceneEntityDeletion[], // Entities removed since last frame
76+
entities: SceneEntity[] // All current-frame entities
77+
}
78+
```
79+
80+
## Error handling
81+
82+
The entire conversion is wrapped in `try/catch`. On failure:
83+
84+
- Error is logged to `console.error`
85+
- An alert is emitted with `severity: "error"`
86+
- An empty `SceneUpdate` (no entities) is returned — deletions are still applied
87+
- Exceptions never propagate to the Lichtblick runtime
88+
89+
## Feature builder pattern
90+
91+
Each feature module exports:
92+
93+
- `build*Entity()` — Creates a `PartialSceneEntity` with Foxglove primitives (cubes, models, triangles, arrows)
94+
- `build*Metadata()` — Creates `KeyValuePair[]` metadata for panel displays
95+
96+
Builders receive the OSI entity cast as `DeepRequired<T>` (from `ts-essentials`), which satisfies TypeScript but does **not** validate field presence at runtime.

docs/architecture/features.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
---
2+
sidebar_position: 4
3+
---
4+
5+
# Features
6+
7+
Each feature module in `src/features/` is responsible for converting one OSI entity type into [Foxglove scene primitives](https://lichtblick-suite.github.io/docs/docs/visualization/message-schemas).
8+
9+
## Moving objects
10+
11+
**Module:** `src/features/movingobjects/`
12+
**OSI type:** `MovingObject`
13+
**Primitives:** CubePrimitive, ModelPrimitive, ArrowPrimitive
14+
15+
Renders vehicles, pedestrians, and animals. The host vehicle is colored blue; others are colored by type:
16+
17+
| Type | Color |
18+
|------|-------|
19+
| VEHICLE | Red |
20+
| PEDESTRIAN | Yellow |
21+
| ANIMAL | Green |
22+
| HOST_OBJECT | Blue |
23+
| UNKNOWN | Gray |
24+
| OTHER | Cyan |
25+
26+
Includes optional 3D model rendering (when `show3dModels` is enabled) and light state visualization for vehicles (brake lights, indicators).
27+
28+
## Stationary objects
29+
30+
**Module:** `src/features/stationaryobjects/`
31+
**OSI type:** `StationaryObject`
32+
**Primitives:** CubePrimitive, ModelPrimitive, ArrowPrimitive
33+
34+
Renders static scene objects with bounding boxes. Colors are determined by the object's `classification.color` field. Supports 3D model loading.
35+
36+
## Traffic lights
37+
38+
**Module:** `src/features/trafficlights/`
39+
**OSI type:** `TrafficLight`
40+
**Primitives:** ModelPrimitive (embedded glTF with texture), CubePrimitive, ArrowPrimitive
41+
42+
Renders traffic lights using built-in 3D models with dynamically colored textures based on the light state (red, yellow, green). Includes mode handling (standard, flashing, counting).
43+
44+
## Traffic signs
45+
46+
**Module:** `src/features/trafficsigns/`
47+
**OSI type:** `TrafficSign` (main + supplementary)
48+
**Primitives:** ModelPrimitive
49+
50+
Renders traffic signs using dynamically loaded PNG textures. Textures are preloaded at extension activation via `preloadDynamicTextures()` and cached for reuse.
51+
52+
## Road markings
53+
54+
**Module:** `src/features/roadmarkings/`
55+
**OSI type:** `RoadMarking`
56+
**Primitives:** CubePrimitive
57+
58+
Renders road markings (currently STOP markings only) as oriented cubes. Position is centered on `base.position`, orientation applied from `base.orientation`, and dimensions follow the OSI road marking coordinate system where the x-axis is the surface normal.
59+
60+
:::note
61+
62+
Only road markings with `traffic_main_sign_type == STOP` are currently rendered. Other marking types are filtered out.
63+
64+
:::
65+
66+
## Lanes
67+
68+
**Module:** `src/features/lanes/`
69+
**OSI type:** `Lane`, `LaneBoundary`
70+
**Primitives:** TriangleListPrimitive
71+
72+
Renders lane surfaces and lane boundaries as triangle meshes. Lane boundaries are extruded from point lists with width and optional dashing. Lanes are filled surfaces connecting their left and right boundaries.
73+
74+
Lane colors vary by type:
75+
76+
| Type | Color |
77+
|------|-------|
78+
| DRIVING | Cyan |
79+
| INTERSECTION | Red |
80+
| NONDRIVING | Coral |
81+
| UNKNOWN / OTHER | Gray |
82+
83+
The host vehicle's lane is highlighted in orange when identifiable.
84+
85+
See [Lanes Reference](../reference/lanes.md) for detailed color tables.
86+
87+
## Logical lanes
88+
89+
**Module:** `src/features/logicallanes/`
90+
**OSI type:** `LogicalLane`, `LogicalLaneBoundary`
91+
**Primitives:** TriangleListPrimitive
92+
93+
Same rendering approach as physical lanes but with distinct colors (green surfaces, red boundaries) and a slight height offset (`0.02m`) to visually separate them from physical lanes.
94+
95+
See [Logical Lanes Reference](../reference/logical-lanes.md) for details.
96+
97+
## Reference lines
98+
99+
**Module:** `src/features/referenceline/`
100+
**OSI type:** `ReferenceLine`
101+
**Primitives:** TriangleListPrimitive
102+
103+
Renders reference lines as green line strips with a configurable width (`0.2m`).

0 commit comments

Comments
 (0)