DOCS mcap 3d visualization
Support# Tutorial: 3D WebGL MCAP Telemetry Visualization Pipeline
In this tutorial, you will configure, deploy, and verify Bauxite's clientless 3D WebGL telemetry visualization pipeline. By the end of this guide, you will understand how edge nodes scan local recordings, sync lightweight metadata indexes to the Hub database, and stream raw point clouds on-demand over WebRTC DataChannels directly into a zero-allocation Svelte viewport.
---
## Prerequisites
Before starting, ensure you have:
* A Linux development machine with Docker and Rust installed.
* The `bauxite-agent` and `bauxite-dispatch` crates building cleanly.
* An active terminal to run cargo tests.
---
## Architecture Overview
Traditional robotics workflows require edge units to upload gigabyte-scale logs (like lidar point clouds) to the cloud before operators can run playbacks. Bauxite bypasses this overhead using a **local-first, on-demand streaming** approach:
```
+------------------+ +------------------+ +--------------------+
| Edge Robot SSD | | Bauxite Hub DB | | Operator Browser |
+------------------+ +------------------+ +--------------------+
| raw .mcap logs | --(1. Hashed)--> | SQLite metadata | <--(2. Query)---- | Svelte Dashboard |
| | | index entries | | |
| time-sync chunks | =================(3. WebRTC P2P DataChannel)===========> | Zero-Allocation |
| | | WebGL viewport |
+------------------+ +--------------------+
```
---
## Step 1: Database Schema Migration
The central registry stores edge indexes inside an SQLite table called `mcap_index`. The schema is defined in `000009_add_mcap_index.up.sql`:
```sql
CREATE TABLE IF NOT EXISTS mcap_index (
file_id TEXT PRIMARY KEY,
node_id TEXT NOT NULL,
file_name TEXT NOT NULL,
file_size_bytes INTEGER NOT NULL,
duration_seconds INTEGER NOT NULL,
start_time_epoch_ms INTEGER NOT NULL,
end_time_epoch_ms INTEGER NOT NULL,
topics TEXT NOT NULL, -- JSON array of strings
schemas TEXT NOT NULL, -- JSON array of strings
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(node_id) REFERENCES nodes(id) ON DELETE CASCADE
);
```
When the `bauxite-dispatch` service boots, it automatically runs migrations to provision this table.
---
## Step 2: Edge Scanning & Metadata Fingerprinting
To prevent CPU spikes on constrained edge nodes when hashing multi-gigabyte recording files, the scanner daemon in `telemetry.rs` calculates a lightweight fingerprint:
1. **Read Target Directory:** Scans `/root/.bauxite/recordings` for files ending in `.mcap` or `.db3`.
2. **Generate Signature:** Combines the file name, file size, and modification time (`mtime`).
3. **BLAKE3 Hashing:** Hashes this concatenated string to generate a unique `file_id`.
4. **Sync Index:** Reports the lightweight metadata payload back to the Hub via the `SyncMcapIndex` gRPC API.
On the Hub, the Telemetry service parses the incoming array and calls `HubRegistry::save_mcap_index` to update the central SQLite registry.
---
## Step 3: Wire-Format Frame Alignment
Robotics serialization standards like ROS 2 Common Data Representation (CDR) depend on strict 4-byte or 8-byte boundaries. Variable-length Protobuf structures shift byte positions, throwing unaligned memory access errors when cast to typed arrays on the browser side.
To resolve this, Bauxite uses the `McapMessageFrame` Protobuf wrapper:
```protobuf
message McapMessageFrame {
string topic = 1;
int64 timestamp_ms = 2;
string schema_type = 3;
uint32 payload_alignment_padding = 4; // Enforces alignment boundary shifts
bytes payload = 5;
}
```
This padding ensures the raw binary slice lands on a clean 8-byte address alignment before WebGL renders the points.
---
## Step 4: Zero-Allocation 3D WebGL Viewport
High-frequency point cloud playbacks (e.g., 150k vertices at 20Hz) cause major Garbage Collection (GC) pauses if arrays are re-allocated inside reactive blocks.
The `PointcloudViewport.svelte` component bypasses the GC thread-stutter trap:
1. **Instantiate Pools Once:** Pre-allocates two large static typed arrays (`positionsPool` and `colorsPool`) in `onMount`.
2. **Mutate In-Place:** Mutates array values directly from incoming DataChannel packets without releasing or allocating new buffers.
3. **Explicit WebGL Updates:** Sets `posAttr.needsUpdate = true` and `colorAttr.needsUpdate = true` to redraw the Three.js viewport fluidly.
---
## Step 5: Verification & Testing
Verify that your schema registry, metadata syncing, and chunk alignment structures operate correctly using the automated verification harness:
```bash
# Executed from the repo root
./scripts/test_mcap_pipeline.sh
```
You should see all assertions pass successfully:
```text
=========================================================
Initializing Bauxite MCAP Data Integration Verification Suite
=========================================================
[*] Step 1: Evaluating Index Daemon Metadata Extraction & DB Synchronization...
test registry::tests::test_mcap_index ... ok
[*] Step 2: Testing On-Demand Seek Optimization & Frame Alignment...
test registry::tests::test_mcap_frame_alignment ... ok
=========================================================
[✓] All MCAP Pipeline Architecture Integration Tests Passed.
=========================================================
```