1. Introduction
WebXR Anchors module enables applications to ask the underlying XR system to track changes to a particular three-dimensional pose (position and orientation) as the system’s understanding of the world changes. This allows the application to adjust the location of the virtual objects that it placed in the scene in a way that helps with maintaining the illusion that the placed objects are really present in the user’s environment.
1.1. Terminology
Pose, as understood by this document, signifies a position and orientation in 3D space.
Anchor, as understood by this document, is an entity that keeps track of the pose that is fixed relative to the real world, and is created by the application.
2. Initialization
2.1. Feature descriptor
In order for the applications to signal their interest in using anchors during a session, the session must be requested with appropriate feature descriptor. The string anchors is introduced by this module as a new valid feature descriptor for anchors feature.
A device is capable of supporting the anchors feature if the device’s tracking system exposes a native anchors capability. The inline XR device MUST NOT be treated as capable of supporting the anchors feature. The user agents SHOULD attempt to support anchors feature for sessions with mode equal to "immersive-ar"
.
Note: Even though anchors feature support is not required, anchors are one of the basic features needed by the AR-enabled applications to provide good user experience. Therefore, it is *highly* recommended that the user agents support them for "immersive-ar"
sessions.
3. Anchors
3.1. XRAnchor
In only one current engine.
OperaNoneEdge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone
In only one current engine.
OperaNoneEdge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone
In only one current engine.
OperaNoneEdge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone
[SecureContext ,Exposed =Window ]interface {
XRAnchor readonly attribute XRSpace ; [
anchorSpace NewObject ]Promise <DOMString >();
requestPersistentHandle undefined (); };
delete
An XRAnchor
contains anchorSpace
that can be used to locate the anchor relative to other XRSpaces
. If this attribute is accessed when deleted is set to true
, the user agent MUST throw an InvalidStateError
.
Each XRAnchor
has an associated deleted boolean value that is initially set to false
.
Each XRAnchor
has an associated native origin.
Each XRAnchor
has an associated session.
-
Let anchor be a new
XRAnchor
. -
Set anchor’s native origin to native origin.
-
Set anchor’s session to session.
-
Set anchor’s deleted to
false
. -
Set anchor’s
anchorSpace
to a newXRSpace
object created with session set to anchor’s session and native origin set to native origin. -
Return anchor.
requestPersistentHandle()
method, when invoked on an XRAnchor
anchor, MUST run the following steps:
-
Let promise be a new Promise in the relevant realm of this
XRSystem
. -
If anchor’s deleted is
true
, reject promise withInvalidStateError
, return promise, and abort these steps. -
Let session be anchor’s session.
-
If session’s map of persistent anchors contains the value anchor, run the following steps:
-
Let uuid be the key of the mapping of the anchor value on session’s map of persistent anchors.
-
Resolve promise with uuid.
-
Return promise.
-
Abort these steps.
-
-
Let uuid be the empty string.
-
Generate a UUID [RFC4122] as a string and append it to uuid.
-
Add uuid and anchor to session’s map of persistent anchors.
-
Resolve promise with uuid.
-
Return promise.
Note: when the XRSystem
creates the unique ID, it MUST be unique and only known to the current origin.
4. Anchor creation
The XRSession
is extended to contain an associated set of tracked anchors.
The XRSession
is extended to contain an associated map of persistent anchors that is keyed with a UUID string and maps to an XRAnchor
.
The XRSession
is extended to contain an associated map of new anchors that is keyed with XRAnchor
object and maps to
object.Promise
<XRAnchor
>
In only one current engine.
OperaNoneEdge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone
In only one current engine.
OperaNoneEdge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone
partial interface XRFrame {Promise <XRAnchor >(
createAnchor XRRigidTransform ,
pose XRSpace ); };
space partial interface XRSession {Promise <XRAnchor >(
restorePersistentAnchor DOMString );
uuid Promise <undefined >(
deletePersistentAnchor DOMString ); };
uuid partial interface XRHitTestResult {Promise <XRAnchor >(); };
createAnchor
The XRHitTestResult
is extended to contain an associated native entity. If the underlying system does not provide information about native entity that resulted in computing the result, it will be assumed that native entity is set to null
.
The application can create an anchor using one of the 2 ways:
-
By creating an anchor from frame - created anchor will not be attached to any particular real world object.
-
By creating an anchor from hit test result - created anchor will be attached to a real world object if the underlying XR device supports it.
In order to create an anchor from frame, the application can call XRFrame
's createAnchor(pose, space)
method.
createAnchor(pose, space)
method, when invoked on an XRFrame
frame with pose and space, MUST run the following steps:
-
Let promise be a new Promise.
-
If frame’s active boolean is
false
, reject promise withInvalidStateError
, return promise, and abort these steps. -
Let session be frame’s session.
-
Add update anchors algorithm to session’s list of frame updates if it is not already present there.
-
Let device be session’s XR device.
-
Let effective origin be space’s effective origin.
-
Let anchor native origin be a new native origin returned from the device’s call to create a new anchor using pose, interpreted as if expressed relative to effective origin at the frame’s time.
-
Create new anchor object anchor using anchor native origin and session.
-
Add anchor to session’s set of tracked anchors.
-
Add a mapping from anchor to promise to session’s map of new anchors.
-
Return promise.
Note: It is the responsibility of user agents to ensure that the physical origin tracked by the anchor returned by each createAnchor(pose, space)
call aligns as closely as possible with the physical location of pose within space at the time represented by the frame on which the method is called. Specifically, this means that for spaces that are dynamically changing, user agents should attempt to capture the native origin of such spaces at the app’s specified time. This text is non-normative, but expresses the intent of the specification author(s) and contributors and thus it is highly recommended that it is followed by the implementations to ensure consistent behavior across different vendors.
restorePersistentAnchor(uuid)
method, when invoked on an XRSession
session with uuid, MUST run the following steps:
-
Let promise be a new Promise in the relevant realm of this
XRSystem
. -
If session’s map of persistent anchors does not contain a mapping, reject promise with
InvalidStateError
, return promise, and abort these steps. -
If session’s ended value is `true`, reject promise with
InvalidStateError
, return promise, and abort these steps. -
Let anchor be the value of mapping from uuid on session’s map of persistent anchors.
-
If session’s map of new anchors contains a mapping from anchor to promise, reject the promise with
InvalidStateError
, return promise, and abort these steps. -
Add anchor to session’s set of tracked anchors.
-
Add a mapping from anchor to promise to session’s map of new anchors.
-
Return promise.
deletePersistentAnchor()
method, when invoked on an XRSession
session with uuid, MUST run the following steps:
-
Let promise be a new Promise in the relevant realm of this
XRSystem
. -
Let anchor be the value of mapping from uuid on session’s map of persistent anchors.
-
If session’s map of persistent anchors does not contain a mapping to anchor, reject promise with
InvalidStateError
, return promise, and abort these steps. -
Remove the mapping from session’s map of persistent anchors.
-
Invoke {{XRAnchor/delete()} on anchor.
-
Return promise.
In order to create an anchor from hit test result, the application can call XRHitTestResult
's createAnchor()
method.
createAnchor()
method, when invoked on an XRHitTestResult
hitTestResult, MUST run the following steps:
-
Let promise be a new Promise.
-
Let frame be hitTestResult’s frame.
-
If frame’s active boolean is
false
, reject promise withInvalidStateError
, return promise, and abort these steps. -
Let session be frame’s session.
-
Add update anchors algorithm to session’s list of frame updates if it is not already present there.
-
Let device be session’s XR device.
-
Let nativeEntity be the hitTestResult’s native entity.
-
Let anchor native origin be a new native origin returned from the device’s call to create a new anchor located at hitTestResult’s native origin and attached to nativeEntity, at the frame’s time.
-
Create new anchor object anchor using anchor native origin and session.
-
Add anchor to session’s set of tracked anchors.
-
Add a mapping from anchor to promise to session’s map of new anchors.
-
Return promise.
Note: The same remark that is present on createAnchor(pose, space)
method applies here as well.
Session’s "list of frame updates" might need to have a way of specifying ordering - some algorithms may depend on others.
5. Anchor updates
In only one current engine.
OperaNoneEdge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone
In only one current engine.
OperaNoneEdge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone
[Exposed =Window ]interface {
XRAnchorSet readonly setlike <XRAnchor >; };partial interface XRFrame { [SameObject ]readonly attribute XRAnchorSet ; };
trackedAnchors
An XRAnchorSet
interface is introduced as a way to expose a collection of anchors.
An XRFrame
is extended to contain a trackedAnchors
attribute which contains all anchors still tracked in the frame. At XRFrame
creation, the set is initially empty and will be populated by the update anchors algorithm.
-
Let session be a frame’s session.
-
Let device be a session’s XR device.
-
For each anchor in session’s set of tracked anchors, run:
-
Query the device’s tracking system for the anchor’s native origin information.
-
If the device’s tracking system no longer tracks the anchor, run the following steps:
-
Remove anchor from the session’s set of tracked anchors.
-
If session’s map of new anchors contains a mapping from anchor to promise, reject the promise and remove the mapping.
-
Continue to the next entry in session’s set of tracked anchors.
-
-
Add anchor to frame’s
trackedAnchors
set. -
If session’s map of new anchors contains a mapping from anchor to promise, resolve the promise with anchor and remove the mapping.
-
6. Anchor removal
When an application is no longer interested in receiving updates to an anchor, it can delete an anchor by calling delete()
.
delete()
method, when invoked on an XRAnchor
anchor, MUST delete an anchor by running the following steps:
-
If anchor’s deleted is
true
, abort these steps. -
Set anchor’s
anchorSpace
tonull
. -
Set anchor’s deleted to
true
. -
Let session be an anchor’s session.
-
Let device be a session’s XR device.
-
Let native origin be an anchor’s native origin.
-
Inform the device’s tracking system that the native origin is no longer to be tracked.
-
Remove anchor from session’s set of tracked anchors.
7. Native device concepts
In order for the user agents to be able to implement the anchors API, the underlying XR device should provide native support of this feature. This section describes requirements placed on the underlying XR system, and is by necessity under-specified to allow the implementation of anchors API on top of various frameworks / devices.
7.1. Native anchor
The underlying XR device is capable of supporting the anchors feature if it supports the following capabilities related to anchors:
-
Native anchor creation is possible, with the following requirements:
-
The native anchors API attempts to maintain the pose of the anchor as if it were fixed relative to the real world.
-
It accepts pose of the newly created anchor at some specific time
t
. -
It optionally accepts a native entity information in order to express the intent of attaching newly created anchor to the given entity. If the underlying XR system does not support attaching anchors to a native entity (i.e. does not accept a native entity), the newly created anchor will be free-floating.
-
It returns a result that can be treated as a native origin by the user agents.
-
-
Native anchors are continuously tracked by the underlying XR system and can be queried for their most up-to-date state. When the underlying system deems that the native anchor’s location is never going to be known, it SHOULD report that the native anchor is no longer tracked.
-
Optionally, native anchors can be attached to native entities. A native anchor that is attached to a native entity attempts to maintain its position fixed relative to the entity to which it is attached (as opposed to the real world in case of free-floating anchors). When the device detects that the pose of the object to which the anchor is attached changes, the anchor will be updated accordingly. This does not imply that the object itself moved - it may be that the system’s understanding of its location changed. If the underlying system is capable of tracking moving objects, the native anchors attached to moving objects should be updated as well.
In case the underlying device does not support native anchors, the user agents MAY decide to implement the anchors API through emulated native anchors. This approach assumes that anchors, once created, never change their pose, and their pose is the pose passed in by the application to the anchor creation methods such as XRFrame
's createAnchor(pose, space)
or XRHitTestResult
's createAnchor()
.
Note: The emulated native anchors approach is equivalent to the applications emulating the anchors feature themselves and can help reduce the number of different cases that the applications need to handle. It might also allow the applications to re-use the same code for "immersive-ar"
and "immersive-vr"
sessions.
8. Privacy & Security Considerations
The anchors API does not directly expose access to the information about the user environment. In case the session was created with hit-test support enabled and the device supports tracking moving objects, it may be possible for the application to infer the layout of the user’s environment by observing changes to anchor poses of objects that are, for example, carried around. This offers similar level of information about user’s environment as hit-testing API. Anchor feature has to be declared when creating an XR session, which will allow the user agents to notify the users about potential privacy implications of allowing the anchors API to be used by the website.
I’m not aware of devices that support tracking general objects that move - should they be considered by the spec at all? Are there any examples of such devices?
9. Acknowledgements
The following individuals have contributed to the design of the WebXR Anchors specification: