What I wanted to solve
I wanted to prevent a simple but serious mismatch: the router uses one version of a building while the 2D plan or 3D view shows another. The project compiles a single spatial model for every client and keeps closures and lift outages explicit.
What made it difficult
- A multi-floor route has to respect its accessibility profile and the current closures.
- An inaccessible or restricted edge must be treated as unavailable when its state is uncertain.
- An offline package needs an integrity check and a safe way to roll back.
- Route progress cannot look confident when the localization estimate is not.
- The 2D plan, 3D twin, search index, and routing worker must agree on the package identity.
- A printed check-in code is trustworthy only when it was generated from the package and physically placed at the declared anchor.
- A real deployment needs venue data that is authorized and physically verified.
How it works
- 1
Building source
The source describes floors, spaces, portals, POIs, connectors, restrictions, accessibility, and localization anchors.
- 2
Schema and compiler
The compiler checks geometry, connectivity, reachability, and operational attributes before the package reaches a client.
- 3
Content-addressed package
One reproducible artifact feeds routing, search, the 2D plan, and the 3D viewer.
- 4
Routing worker
A Web Worker runs multi-floor A* for standard and wheelchair profiles, applying closures and fail-closed exclusions.
- 5
Verified package registry
The registry checks SHA-256 digests and keeps the active and previous packages atomically in IndexedDB.
- 6
QR check-in
Package-generated codes resolve to declared anchors on the correct floor without a beacon, fingerprint database, or lookup service.
- 7
Localization runtime
The runtime replays observations in a stable order, tracks covariance-aware quality states, and pauses route matching when uncertainty is too high.
Choices I made
Compile topology before runtime
I make the compiler responsible for malformed geometry and missing connectivity. A client either receives a valid package or receives nothing; it does not repair the building on its own.
Share one artifact across every client surface
Routing, search, 2D, and 3D all derive from the same hashed package. That keeps a view from quietly drifting to different topology.
Fail closed for accessibility and restrictions
If a lift is unavailable or an edge is inaccessible, I exclude it. Missing or uncertain state never makes the route more permissive.
Emit route receipts
Each result records the package hash, routing profile, applied closures, chosen connectors, and exclusion counts. That is enough to explain and reproduce the route.
Make localization uncertainty explicit
I use covariance-aware quality states to gate route matching. An unstable estimate triggers recovery instead of being shown as reliable guidance.
Generate check-in codes from the package
The printable code sheet is derived from compiled venue anchors and round-trip tested through the decoder. Placement remains a physical field procedure, so the software does not pretend to verify where a sign was mounted.
How I tested it
- The repository check runs linting, type checking, tests, package reproducibility checks, replay verification, and the production build.
- Committed building packages are recompiled and compared with their stored versions.
- Reference localization replay output is compared byte for byte.
- A structurally different two-floor ferry, market, and community venue can be switched in at runtime without rebuilding the app.
- The main benchmark tests standard and wheelchair routing during a reproducible public-lift outage.
- Generated check-in codes are checked against published package anchors and round-trip tested through the decoder used by the client.
Known failure modes
- A wheelchair route is rejected when its required lift is unavailable and there is no accessible alternative.
- Invalid topology stops compilation; the browser does not try to repair it.
- Tampered packages fail digest verification.
- High localization uncertainty stops confident route matching and invokes the recovery rules.
- A code from an old package or one mounted at the wrong junction can produce a bad physical check-in even when its payload is valid.
What works now
- The four-floor synthetic benchmark contains 60 spaces, 56 portals, 36 POIs, 216 routing nodes, and 224 edges.
- Multi-floor A* supports standard and wheelchair routing profiles.
- Offline updates retain the active and previous package as one atomic change.
- The compiled package drives search, the architectural plan, and the 3D spatial twin.
- Localization observations can be replayed with explicit uncertainty states.
- A QR code can establish a floor-aware position fix against the package without an online positioning service.
What it doesn't do yet
- The Asterion medical-centre benchmark is synthetic. It is not a deployed venue.
- Deployment would require authorized building data, calibrated coordinate transforms, checked accessibility attributes, and physical route testing.
- The camera guidance is screen-aligned, not world-anchored augmented reality.
- True world anchoring would need live localization and a surveyed transform between the building and the device.
- A cold reload while offline is not yet supported.