WebXR Anchors Module

Editor’s Draft,

More details about this document
This version:
https://immersive-web.github.io/anchors/
Issue Tracking:
GitHub
Inline In Spec
Editor:
(Google)
Participate:
File an issue (open issues)
Mailing list archive
W3C’s #immersive-web IRC

Abstract

Describes a method to create anchors tracked by underlying system.

Status of this document

This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document was published by the Immersive Web Working Group as an Editors' Draft. This document is intended to become a W3C Recommendation. Feedback and comments on this specification are welcome. Please use Github issues. Discussions may also be found in the public-immersive-web-wg@w3.org archives.

Publication as an Editors' Draft does not imply endorsement by W3C and its Members. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by a group operating under the 1 August 2017 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 2 November 2021 W3C Process Document.

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

XRAnchor

In only one current engine.

FirefoxNoneSafariNoneChrome85+
OperaNoneEdge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone

XRAnchor/anchorSpace

In only one current engine.

FirefoxNoneSafariNoneChrome85+
OperaNoneEdge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone

XRAnchor/delete

In only one current engine.

FirefoxNoneSafariNoneChrome85+
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.

In order to create new anchor object from native origin and session, the user agent MUST run the following steps:
  1. Let anchor be a new XRAnchor.

  2. Set anchor’s native origin to native origin.

  3. Set anchor’s session to session.

  4. Set anchor’s deleted to false.

  5. Set anchor’s anchorSpace to a new XRSpace object created with session set to anchor’s session and native origin set to native origin.

  6. Return anchor.

The requestPersistentHandle() method, when invoked on an XRAnchor anchor, MUST run the following steps:
  1. Let promise be a new Promise in the relevant realm of this XRSystem.

  2. If anchor’s deleted is true, reject promise with InvalidStateError, return promise, and abort these steps.

  3. Let session be anchor’s session.

  4. If session’s map of persistent anchors contains the value anchor, run the following steps:

    1. Let uuid be the key of the mapping of the anchor value on session’s map of persistent anchors.

    2. Resolve promise with uuid.

    3. Return promise.

    4. Abort these steps.

  5. Let uuid be the empty string.

  6. Generate a UUID [RFC4122] as a string and append it to uuid.

  7. Add uuid and anchor to session’s map of persistent anchors.

  8. Resolve promise with uuid.

  9. 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 Promise<XRAnchor> object.

XRFrame/createAnchor

In only one current engine.

FirefoxNoneSafariNoneChrome85+
OperaNoneEdge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone

XRHitTestResult/createAnchor

In only one current engine.

FirefoxNoneSafariNoneChrome85+
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:

In order to create an anchor from frame, the application can call XRFrame's createAnchor(pose, space) method.

The createAnchor(pose, space) method, when invoked on an XRFrame frame with pose and space, MUST run the following steps:
  1. Let promise be a new Promise.

  2. If frame’s active boolean is false, reject promise with InvalidStateError, return promise, and abort these steps.

  3. Let session be frame’s session.

  4. Add update anchors algorithm to session’s list of frame updates if it is not already present there.

  5. Let device be session’s XR device.

  6. Let effective origin be space’s effective origin.

  7. 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.

  8. Create new anchor object anchor using anchor native origin and session.

  9. Add anchor to session’s set of tracked anchors.

  10. Add a mapping from anchor to promise to session’s map of new anchors.

  11. 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.

The restorePersistentAnchor(uuid) method, when invoked on an XRSession session with uuid, MUST run the following steps:
  1. Let promise be a new Promise in the relevant realm of this XRSystem.

  2. If session’s map of persistent anchors does not contain a mapping, reject promise with InvalidStateError, return promise, and abort these steps.

  3. If session’s ended value is `true`, reject promise with InvalidStateError, return promise, and abort these steps.

  4. Let anchor be the value of mapping from uuid on session’s map of persistent anchors.

  5. 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.

  6. Add anchor to session’s set of tracked anchors.

  7. Add a mapping from anchor to promise to session’s map of new anchors.

  8. Return promise.

The deletePersistentAnchor() method, when invoked on an XRSession session with uuid, MUST run the following steps:
  1. Let promise be a new Promise in the relevant realm of this XRSystem.

  2. Let anchor be the value of mapping from uuid on session’s map of persistent anchors.

  3. If session’s map of persistent anchors does not contain a mapping to anchor, reject promise with InvalidStateError, return promise, and abort these steps.

  4. Remove the mapping from session’s map of persistent anchors.

  5. Invoke {{XRAnchor/delete()} on anchor.

  6. Return promise.

In order to create an anchor from hit test result, the application can call XRHitTestResult's createAnchor() method.

The createAnchor() method, when invoked on an XRHitTestResult hitTestResult, MUST run the following steps:
  1. Let promise be a new Promise.

  2. Let frame be hitTestResult’s frame.

  3. If frame’s active boolean is false, reject promise with InvalidStateError, return promise, and abort these steps.

  4. Let session be frame’s session.

  5. Add update anchors algorithm to session’s list of frame updates if it is not already present there.

  6. Let device be session’s XR device.

  7. Let nativeEntity be the hitTestResult’s native entity.

  8. 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.

  9. Create new anchor object anchor using anchor native origin and session.

  10. Add anchor to session’s set of tracked anchors.

  11. Add a mapping from anchor to promise to session’s map of new anchors.

  12. 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

XRAnchorSet

In only one current engine.

FirefoxNoneSafariNoneChrome85+
OperaNoneEdge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone

XRFrame/trackedAnchors

In only one current engine.

FirefoxNoneSafariNoneChrome85+
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.

In order to update anchors for frame, the user agent MUST run the following steps:
  1. Let session be a frame’s session.

  2. Let device be a session’s XR device.

  3. For each anchor in session’s set of tracked anchors, run:

    1. Query the device’s tracking system for the anchor’s native origin information.

    2. If the device’s tracking system no longer tracks the anchor, run the following steps:

      1. Remove anchor from the session’s set of tracked anchors.

      2. If session’s map of new anchors contains a mapping from anchor to promise, reject the promise and remove the mapping.

      3. Continue to the next entry in session’s set of tracked anchors.

    3. Add anchor to frame’s trackedAnchors set.

    4. 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().

The delete() method, when invoked on an XRAnchor anchor, MUST delete an anchor by running the following steps:
  1. If anchor’s deleted is true, abort these steps.

  2. Set anchor’s anchorSpace to null.

  3. Set anchor’s deleted to true.

  4. Let session be an anchor’s session.

  5. Let device be a session’s XR device.

  6. Let native origin be an anchor’s native origin.

  7. Inform the device’s tracking system that the native origin is no longer to be tracked.

  8. 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:

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:

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Conformant Algorithms

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[MEDIACAPTURE-STREAMS]
Cullen Jennings; et al. Media Capture and Streams. 16 June 2022. CR. URL: https://www.w3.org/TR/mediacapture-streams/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC4122]
P. Leach; M. Mealling; R. Salz. A Universally Unique IDentifier (UUID) URN Namespace. July 2005. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc4122
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/
[WEBXR]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR Device API. 1 June 2022. CR. URL: https://www.w3.org/TR/webxr/
[WEBXR-AR-MODULE-1]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR Augmented Reality Module - Level 1. 26 April 2022. WD. URL: https://www.w3.org/TR/webxr-ar-module-1/

IDL Index

[SecureContext, Exposed=Window]
interface XRAnchor {
  readonly attribute XRSpace anchorSpace;

  [NewObject] Promise<DOMString> requestPersistentHandle();

  undefined delete();
};

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();
};

[Exposed=Window]
interface XRAnchorSet {
  readonly setlike<XRAnchor>;
};

partial interface XRFrame {
  [SameObject] readonly attribute XRAnchorSet trackedAnchors;
};

Issues Index

Session’s "list of frame updates" might need to have a way of specifying ordering - some algorithms may depend on others.
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?