SB
projects
Production · 2024-2026 Greenfield

SLAM Mapping Back-office

SLAM mapping back-office for an accessible indoor navigation product. Async pipeline from 360° video to navigable map, with a C++ SLAM engine driven remotely, interactive Sim(2) georeferencing, 2D/3D visualisation and operator curation. Greenfield, end-to-end.

The pipeline

From 360° video to a usable map

Field operators capture buildings as equirectangular 360° video. The back-office then orchestrates the full pipeline: 3D reconstruction, interactive georeferencing, operator curation, export. At the scale of large public venues: airports, train stations, museums, industrial sites.

1
Capture
2
Upload
3
SLAM
4
Parsing
5
Georef
6
Curation
7
Export
1 — Capture

Equirectangular 360° MP4 (handheld camera), several segments per site, walked at a steady pace.

2 — Upload

GCS signed URL (15 min, scoped). The client uploads straight to the bucket, the backend never proxies the file.

3 — SLAM

C++ engine driven remotely on a dedicated external host. Adaptive YAML config (indoor / outdoor). Output: a binary MSG (msgpack) + trajectory.txt.

4 — Parsing

msgpack → keyframes serialised as JSON in the jobs table. Sub-second for a typical trajectory. Map points stay on GCS for debug.

5 — Georef

The operator pins GPS constraints on keyframes. Sim(2) solved via SVD / Umeyama as soon as ≥ 2 constraints. Solve is instant, even with a couple dozen points.

6 — Curation

Manual validation: only trajectories flagged as "validated" reach the production map. Avoids pollution by tests and A/B retries.

7 — Export

GeoJSON (FeatureCollection LineString + keyframe Points) is downloadable. Consumed by the downstream mobile app.

What I built

From scratch, end-to-end

01

SLAM driven remotely

FastAPI invokes the C++ SLAM engine over HTTPS on a dedicated external host (native deps, GPU for bundle adjustment). Three modes: remote prod, Docker dev, mock CI. Status tracking, clean retries, HTTP threads never block.

02

Synchronised 2D & 3D viewers

Mapbox GL for the floor plan with trajectories as LineStrings, keyframes as Points and draggable GPS constraints. Three.js for camera frustums, a filterable point cloud and the 3D trajectory. Selection and hover propagated across both views.

03

Interactive Sim(2) georeferencing

1 constraint → translation only. ≥ 2 constraints → Umeyama solve (SVD on the centred covariance matrix, det forced to +1 to avoid flips). Level override when all constraints live on the same floor. Solve is instant.

04

Large-file friendly upload

GCS signed URL (PUT, 15 min, scoped to the exact path). The client uploads its video straight to the bucket via XHR with progress, no file transits through the backend pod, which stays lean on RAM.

05

Operator curation

A trajectory only reaches the production map after manual validation. Avoids pollution by retries and A/B comparisons. Reversible via a confirm dialog.

06

"Calm / loud" server dashboard

Infra monitoring with a simple rule: a quiet one-liner when healthy, a full panel when something is off. Covers uptime, DB, disk, RAM, SSL certs, GCP billing. Avoids Grafana fatigue.

07

Auth & audit

Keycloak OIDC, three roles (admin / operator / reader), full audit trail grouped by day, RFC 4180 CSV export with UTF-8 BOM (Excel FR friendly).

08

In-house design system

CSS tokens, systematic dark mode, shared components (EmptyState, UserChip, ConfirmDialog, Escape-to-close), unit + Playwright E2E coverage per scenario.

Stack

How it is built

Backend
Python 3.11 FastAPI SQLAlchemy 2.0 Pydantic 2 Alembic PostgreSQL 15 slowapi
Frontend
React 18 TypeScript Vite Zustand TanStack Query sonner
2D / 3D
Mapbox GL Three.js OpenCV msgpack
SLAM
moteur SLAM C++ g2o Eigen 3 OpenCV 4 FBoW CMake
Ops
GCP (GKE) GCS Cloud Build dedicated SLAM host Keycloak OIDC GitLab CI
Trade-offs

A few technical calls

SLAM off-GKE, on a dedicated external host

The C++ engine has heavy native dependencies and benefits from a GPU for bundle adjustment. A GKE GPU node would have cost more than a dedicated external server. Three fallback modes (remote / Docker / mock) make it testable without depending on the prod host.

FastAPI over Spring Boot

The SLAM ecosystem (open-source C++ engine, OpenCV, msgpack) is Python-native. A JNI bridge to Java would have doubled the technical surface for no gain.

Plain Three.js, not React Three Fiber

Need fine control over the scene and per-frame perf (thousands of frustums). RTF adds a React cost per frame we cannot afford.

Zustand + TanStack Query, not Redux

Limited client state, simpler API. TanStack Query handles cache, invalidation and refetch on its own, no reason to re-implement that.

Direct upload to GCS, not via a backend proxy

Videos weigh several gigabytes. Streaming a file that size through the backend pod would OOM it. A scoped signed URL + client-side XHR keeps the backend lean and lets the bucket handle throughput.

No DB mocks in integration tests

A divergent mock masked a broken migration in prod. Now: Testcontainers / ephemeral DBs, and that class of bug cannot ship again.