GPU-accelerated geospatial object tracker with Arrow IPC streaming and shader-side time filtering.
Current: Phase 6 prototype — Bounded in-memory archive and historical queries. Correctness is covered by automated tests; browser performance and production capacity are not established.
- Rust 2024 edition (1.85+)
- Node.js (for esbuild + npm deps — no runtime dependency)
curl(for geodata download)
# one-time: install deps
cd client && npm install && cd ..
# one-time: download Natural Earth geodata (public domain)
bash scripts/download-geodata.sh
# build + run (defaults: 2000 objects @ 10 Hz)
bash scripts/dev.shOpen http://127.0.0.1:3000 — colored dots streaming over a vector world map with time scrubbing and server-side history.
| Variable | Default | Description |
|---|---|---|
PELORUS_OBJECTS |
2000 |
Number of tracked objects |
PELORUS_HZ |
10 |
Tick rate in Hz |
PELORUS_CHUNK_INTERVAL_US |
5000000 |
Chunk duration (μs) |
PELORUS_MAX_CHUNKS |
720 |
Maximum sealed chunks |
PELORUS_MAX_ROWS |
1200000 |
Maximum archive rows, including open chunk |
# conservative — 200 objects at 1 Hz
PELORUS_OBJECTS=200 PELORUS_HZ=1 bash scripts/dev.sh
# stress test — 5000 objects at 10 Hz (50K records/sec)
PELORUS_OBJECTS=5000 PELORUS_HZ=10 bash scripts/dev.shThe time slider filters the position buffer entirely on the GPU.
- LIVE mode (green) — cursor auto-advances to the latest timestamp
- SCRUB mode (amber) — drag the slider to scrub through history
- Window width — controls how much time around the cursor is visible
The slider range includes sealed server history. Scrubbing beyond local live retention queries overlapping whole chunks into a separate bounded history view. LIVE returns to the advancing live buffer. The archive's row cap can evict history well before one hour: at the default 20K rows/sec, the row budget holds about 60 seconds including the open chunk. See the retention and memory limits.
| Document | Description |
|---|---|
| Architecture | System design, component descriptions, key decisions |
| Data Pipeline | End-to-end data flow from server to GPU |
| Chunk Manager | Temporal chunking, retention, query protocol |
| GPU Precision | Float32 constraints and the relative timestamp solution |
| Development | Setup, build, configuration, debugging, extending |
├── Cargo.toml # workspace root
├── server/
│ ├── Cargo.toml
│ └── src/
│ ├── main.rs # Axum server, WebSocket + query handler
│ ├── schema.rs # Arrow schema definition
│ ├── generator.rs # Mock data generator
│ ├── ipc.rs # Arrow IPC serialization
│ ├── chunks.rs # Temporal chunk manager
│ └── protocol.rs # JSON command/response types
├── client/
│ ├── package.json # esbuild + apache-arrow + deck.gl
│ ├── src/
│ │ ├── main.ts # Entry point, pipeline + query state machine
│ │ ├── decode.ts # Arrow IPC decoder
│ │ ├── buffer.ts # Rolling position buffer
│ │ ├── map.ts # deck.gl renderer + DataFilterExtension
│ │ ├── basemap.ts # Natural Earth GeoJSON layers
│ │ ├── timeslider.ts # Time slider (live/scrub + server range)
│ │ ├── protocol.ts # JSON message types
│ │ ├── perf.ts # Performance monitor
│ │ └── theme.ts # Dark/light theme
│ └── dist/
│ ├── index.html
│ └── data/ # Natural Earth GeoJSON (downloaded)
├── docs/ # Engineering documentation
└── scripts/
├── dev.sh
├── watch.sh
└── download-geodata.sh
Skeleton — WebSocket echoArrow IPC schema + mock data + browser decodedeck.gl ScatterplotLayer — moving dotsNatural Earth base mapTime slider with GPU-side filtering- Bounded temporal archive + history queries ← current prototype (client uses flat buffers, not a GPU ring)
- Viewport culling with H3
- Trail lines
- Attribute coloring + filter UI
- Multi-client session management
cargo fmt --all -- --check
cargo test --workspace --locked -j 2
cargo clippy --workspace --all-targets --locked -j 2 -- -D warnings
cargo build -p server --locked -j 2
cd client
npm ci --ignore-scripts
npm run typeprep
npm run typecheck
PELORUS_SERVER_BIN=../target/debug/server npm run test:ci
npm run buildNode 24+ is required for the standard test harness. The strict TypeScript check runs separately from the esbuild bundle. Linux CI requires real-server integration with zero skips; it does not validate browser/GPU performance. See Development for the gate and test boundaries.