Tracking AR Anchors
Designate and track points of interest in the physical environment.
Overview
An anchor is anything in the physical environment that is tracked by the AR session. When placing virtual content, add ARAnchor instances and attach your content to them. This helps your content’s position remains stable, even as the AR session updates its understanding of the environment over time.
If your AR session is configured to do so, ARPlaneAnchor and ARImageAnchor objects will be detected and added to your session automatically. Virtual content can be attached to those anchors in the same manner.
Note
ARDK does not currently support face tracking or using anchors with faces.
Example Use Case
It can be unintuitive to use AR anchors, as they’re needed to solve a problem that doesn’t appear in non-AR 3D applications.
During an AR session, frames surface a best estimate of the device’s position in the real world. Attempting to place virtual objects relative to the device’s position can lead to drift and jitter due to small errors in the estimate being compounded by basing other transforms off them. Creating an ARAnchor
tells the session that you want to track a point in the real world, letting it maintain a best estimate for that point. Because the session has access to the underlying tracking data, this estimate of the point’s position avoids compounded errors.
Thus, using anchors is important when you want to place a virtual object in the real world. For example, think of an application that allows the user to place virtual furniture in a room. The user cares most about whether the virtual table they’ve just placed stays in position relative to the real world rug, so once they’ve decided where to place it you should create an ARAnchor
at the center of the rug and every frame update the table’s position to maintain its original offset to the rug. That way it won’t be affected by the camera’s drift.
If the user then places a bookshelf next to the wall, the wall then needs its own ARAnchor
(or use a PlaneAnchor
if one was surfaced) because it matters more that the bookshelf stays in place relative to the wall than to the rug. A side effect of this is that the bookshelf and table may move relative to each other as the underlying tracking algorithm continually updates its understanding of the world. It might initially believes the bookshelf and table are 2 meters apart, but later after getting a different view might correct their positions so that they’re only 1.8 meters apart.
On the other hand, if the user wants to add chairs around the table they should be placed relative to the existing ARAnchor the table is following. It’s more important that the chairs stay in position relative to the table than that they stay in position relative to anything in the real world.
Summarizing this: The farther away a virtual object is from the phone, the more drifty and jittery it will be relative to the real world. By creating and using anchors you can create islands of stability where virtual objects that have their position computed relative to those anchors will stay stable.
Adding Anchors
To start tracking the position and orientation of static points in the world, use the IARSession.AddAnchor(transform) method to add them to your AR session.
When you need to move a virtual object that is tied to an ARAnchor
(either automatically or due to user input):
If it is a small movement, within a meter or so, you can just update the offset from the
ARAnchor
to the virtual object.If it is a larger movement, wait until the object has stopped moving and create a new
ARAnchor
to attach it to. Dispose the oldARAnchor
if nothing else is using it.
Tracking Anchors
The ARSession
will update anchors to keep it representative of the object for which the anchor was created.
An anchor’s up-to-date properties can be retrieved at any time through the IARAnchor interface.
using Niantic.ARDK.AR.Anchors; public class ARAnchorFollower : MonoBehaviour { public IARAnchor Anchor; void Update() { transform.position = Anchor.Transform.ToPosition(); transform.rotation = Anchor.Transform.ToRotation(); } }
Alternatively, anchor updates can also be subscribed to. Anchors are equatable based on their Identifier property.
void SubscribeToSession(IARSession arSession) { arSession.AnchorsUpdated += OnAnchorsUpdated; } void OnAnchorsUpdated(AnchorsArgs args) { foreach (var anchor in args.Anchors) { // Find GameObject from Dictionary containing // existing Anchor to GameObject mappings var go = virtualObjects[anchor.Identifier]; go.transform.position = anchor.Transform.ToPosition(); go.transform.rotation = anchor.Transform.ToRotation(); } }