Repository navigation
Why outdoor webxr drifts
Every time someone hears "location-based AR in the browser", the same objection arrives, and it is a good one:
Markerless tracking falls apart outdoors. In an open park there are almost no stable feature points to track. Your content will swim.
The objection is right about the physics and wrong about the architecture. It collapses two different layers into one, and once you separate them the question becomes answerable instead of rhetorical.
Layer one is visual-inertial odometry, and it is not ours. When you enter
an immersive-ar session, the device's own AR stack is already fusing the
camera with the IMU to produce local 6-DoF pose at frame rate. That fusion is
why tracking survives a stretch of featureless grass at all: when the camera
has little to say, the inertial half carries the pose for a while.
(In practice this means ARCore on Android. iOS does not expose WebXR AR at all — ARKit is its native counterpart, not something a web page can reach today.) This layer decides whether your virtual cube stays on the ground as you step around it. A WebXR framework does not reimplement it, and should not — it consumes it.
Layer two is the mapping from that local pose to the real world, and this
is the layer that people actually mean when they say "location-based". Your
odometry gives you a coordinate system whose origin is wherever the session
happened to start, pointing wherever the phone happened to be pointing. To
put a model at a specific latitude and longitude, something has to work out
the transform between that arbitrary local frame and the Earth. That is what
gps-plus-slam-js does: it continuously estimates the GPS↔AR alignment and
refines it as observations accumulate.
Conflating the two produces the wrong prediction. The worry "sparse features means my content swims" is a layer-one worry, and it is largely handled by a mature native AR stack you get for free. The real question for layer two is different: how accurately do you know where the local frame sits on the planet, and how does that estimate behave over time?
Raw GPS jitters by metres, and altitude is the channel to trust least. If you naively snapped your scene to each new GPS reading, your content would twitch several metres on every update — the failure everyone has seen in a location-based app that draws a marker at your reported position.
The fix is not to smooth the GPS harder. It is to treat each GPS reading as one noisy observation of a transform you are estimating, alongside the odometry that tells you precisely how you moved between readings. Walking gives the estimator a baseline: the shape of your path in local coordinates has to match the shape of your path in GPS coordinates, and only some alignments make both true at once. That is why the honest claim is motion-dependent: the estimate improves as you walk and is at its worst when you stand still. How fast it improves is a number worth treating carefully — short rules of thumb circulate, and this project's own corpus measurements are less flattering than they are. The piece on measuring alignment says what has actually been measured and what has not.
Two things follow, and both are worth saying plainly:
- Global placement is GPS-accurate. Sub-metre, not centimetre. If your experience needs a label to sit on a particular building, that is enough. If it needs to sit on a particular brick, it is not.
- Local stability is motion-dependent, not guaranteed. Standing still at the start of a session is the worst case, because nothing has yet constrained the fit.
If you need precision from the very first frame instead of after a few seconds of walking, there is a different lever: a printed marker at a surveyed spot can supply a high-confidence position fix that seeds the alignment immediately. The components for that — detection, pose solving, and turning a solved pose into observations the fusion consumes — exist and are tested, though wiring them into an app is currently work you would do yourself. There is a whole post on that.
Once the layers are separate, design decisions stop being guesses:
- Content that must be exactly on a spot, immediately, wants a marker.
- Content that must be roughly in a place and stable once you are there — a waypoint arrow, a trail marker, a label on a statue — is exactly what GPS↔AR alignment is for.
- Content the user creates during the session — a drawn path, a dropped pin — can live purely in the local frame and never care about GPS at all.
The last one surprises people. Not everything in a location-based app needs a location.
The unusual thing about doing this on the web is that evaluation costs nothing. There is no build to install and no store review between you and the question. Open the anchor demo on an ARCore-capable phone, walk outside, drop an object, and walk a circle around it. The source is on GitHub if you would rather read it first. Either it holds its spot or it does not, and you will know within a minute which claims in this post survive contact with your own park.
Start here
Building with it
How the alignment works
Testing & debugging
Perception
Shipping it
12 more pages — see the page list above.