← ledger
v1.0.13 · l-0002May 7, 2026filed under navar

Five stages to a stable pin

Why NavAR resolves indoor anchors through ARWorldMap, ARGeoAnchor, an ORB image-match, ARCore Geospatial, and a GPS fallback — in that order.

NavAR's job is to put a pin in the world and find it again, an hour or a week later, from a different angle, possibly after the lights changed and the floor was waxed. Each relocalization method that exists has failure modes. None of them is reliable on its own. The instrument runs five of them in series and shows you whichever resolved first.

Why five

ARWorldMap is fast indoors when the room hasn't changed. ARGeoAnchor works outdoors but degrades inside concrete. Google's VPS is excellent in urban environments where Street View has been. Server-side image matching catches the case where everything else failed but the room is recognizable from a thumbnail. GPS is the last fallback and the least precise.

Stacked, they cover almost every reasonable scenario. Whichever one resolves first — usually within 1.2s — wins and the others are cancelled.

The pipeline in order

  1. ARWorldMap. A serialized snapshot of the ARKit mesh at the moment the pin was dropped. Saved locally + uploaded to social-anchors. On re-entry, ARKit loads the map and waits to match a region of the new feed against the stored mesh. Typically resolves in 200-400ms indoors when the room looks like it did.
  2. ARGeoAnchor. A GPS-anchored ARKit object — Apple's outdoor relocalization. Works on iOS 15+, requires a clear sky for the initial calibration, but stays locked once anchored. ~500ms to resolve, but useful where ARWorldMap gets confused by changing lighting.
  3. ORB image-match. When the pin was dropped, we captured a 320×320 thumbnail of the visible scene plus ORB feature descriptors. On re-entry, the current frame's descriptors are dispatched server-side (a small Blender- hosted matcher) and the best match returns a 3D pose relative to the original. ~800ms round-trip, but it catches the case where ARWorldMap failed because the room layout shifted slightly.
  4. ARCore Geospatial. Google's VPS — Visual Positioning System — uses Street View imagery to anchor. Excellent in cities that have been driven. Limited coverage elsewhere. ~1-2s when it works.
  5. GPS fallback. Best-effort, low precision. Returns a pin at the GPS-reported position, with no orientation, no occlusion. The user sees a floating arrow rather than a placed object. We show this only when every other stage has failed — it's the difference between "we have no idea" and "your phone thinks the destination is roughly that way."

The cancellation logic

Each stage runs as a Swift Task. The first one to resolve cancels the others — we don't want stage 4 to land a slightly different pose 600ms after stage 1 already drew the arrow on the floor. The wins-first wins-period rule is important because we don't want flicker.

Anchors as URLs

Each saved pin gets a public 24-hour URL — https://voirhq.com/p/<id> — which is also a deep link into the app via the voirnavar://pin/<id> scheme. Sharing a pin is sharing a place plus a window of access. The 24h TTL is deliberate; we treat shared spatial anchors as ephemeral social objects, not as permanent geography.

Indoor vs outdoor in one column

The user doesn't pick. The UI is the same for indoor and outdoor pins. ARKit + the pipeline decide which strategy applies based on signal availability. The visible difference is only the arrow style — outdoor pins are arrows on the ground; indoor pins are floating markers because there's usually no ground-plane visible from the door of a building.