XR_ML_spatial_anchors_storage
This API is still an experimental extension not included in the official OpenXR registry and is subject to change.
12.110. XR_ML_spatial_anchors_storage
- Name String
XR_ML_spatial_anchors_storage
- Extension Type
Instance extension
- Registered Extension Number
142
- Revision
1
- Extension and Version Dependencies
- Last Modified Date
2023-08-24
- Contributors
Ron Bessems, Magic Leap
Karthik Kadappan, Magic Leap
12.110.1. Overview
This extension allows spatial anchors created byXR_ML_spatial_anchors
to be persisted beyond the head pose session.
Spatial Anchor management is closely tied to the selected mapping mode on the device. The modes are mutually exclusive and affect the functionality of these APIs. The available mapping modes are:
On-Device Mode A persistent mode in which anchors are persisted locally and will be available across multiple sessions when localized to the same localization map in which they were published.
AR Cloud Mode A persistent mode in which anchors are persisted in the cloud environment and will be available across multiple sessions and across multiple devices that are localized to the same localization map in which they were published.
For more details on mapping modes refer to the XR_ML_localization_map
extension.
Permissions Android applications must have the com.magicleap.permission.SPATIAL_ANCHOR permission listed in their manifest to use this extension. (protection level: normal) |
12.110.2. Storage
The XrSpatialAnchorsStorageML storage handle maintains the connection with the backend service. This can be on device or in cloud depending on the localization map that is active. Use the XR_ML_localization_map
extension to deduce the current mode if the application needs to know this.
The xrCreateSpatialAnchorsStorageML function is defined as:
// Provided by XR_ML_spatial_anchors_storage
XrResult xrCreateSpatialAnchorsStorageML(
XrSession session,
const XrSpatialAnchorsCreateStorageInfoML* createInfo,
XrSpatialAnchorsStorageML* storage);
The XrSpatialAnchorsCreateStorageInfoML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsCreateStorageInfoML {
XrStructureType type;
const void* next;
} XrSpatialAnchorsCreateStorageInfoML;
Currently no extra information is needed to create this structure.
// Provided by XR_ML_spatial_anchors_storage
XR_DEFINE_HANDLE(XrSpatialAnchorsStorageML)
The XrSpatialAnchorsStorageML handle represents the resources for storing spatial anchors.
The xrDestroySpatialAnchorsStorageML function is defined as:
// Provided by XR_ML_spatial_anchors_storage
XrResult xrDestroySpatialAnchorsStorageML(
XrSpatialAnchorsStorageML storage);
12.110.3. Query Stored Anchors
To find out which Spatial Anchors are stored near a certain XrPosefthis extension provides a query system. This function is asynchronous and uses the XR_EXT_future
extension.
The xrQuerySpatialAnchorsAsyncML function is defined as:
// Provided by XR_ML_spatial_anchors_storage
XrResult xrQuerySpatialAnchorsAsyncML(
XrSpatialAnchorsStorageML storage,
const XrSpatialAnchorsQueryInfoBaseHeaderML* queryInfo,
XrFutureEXT* future);
If the space was not locatable during the query the runtime must returnXR_ERROR_SPACE_NOT_LOCATABLE_EXT
in futureResult
ofXrSpatialAnchorsQueryCompletionML.
The XrSpatialAnchorsQueryInfoRadiusML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsQueryInfoRadiusML {
XrStructureType type;
const void* next;
XrSpace baseSpace;
XrVector3f center;
XrTime time;
float radius;
} XrSpatialAnchorsQueryInfoRadiusML;
The XrSpatialAnchorsQueryInfoBaseHeaderML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsQueryInfoBaseHeaderML {
XrStructureType type;
const void* next;
} XrSpatialAnchorsQueryInfoBaseHeaderML;
The xrQuerySpatialAnchorsCompleteML function is defined as:
// Provided by XR_ML_spatial_anchors_storage
XrResult xrQuerySpatialAnchorsCompleteML(
XrSpatialAnchorsStorageML storage,
XrFutureEXT future,
XrSpatialAnchorsQueryCompletionML* completion);
Once the XrFutureEXT
has completedxrQuerySpatialAnchorsCompleteML must be called to retrieve theXrUuidEXT values of the found anchors.
The XrSpatialAnchorsQueryCompletionML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsQueryCompletionML {
XrStructureType type;
void* next;
XrResult futureResult;
uint32_t uuidCapacityInput;
uint32_t uuidCountOutput;
XrUuidEXT* uuids;
} XrSpatialAnchorsQueryCompletionML;
12.110.4. Publish Anchors
If the application needs to persist an anchor beyond the current head pose session it should publish the anchor. Publishing is an asynchronous operation and can publish multiple anchors at the same time.
The xrPublishSpatialAnchorsAsyncML function is defined as:
// Provided by XR_ML_spatial_anchors_storage
XrResult xrPublishSpatialAnchorsAsyncML(
XrSpatialAnchorsStorageML storage,
const XrSpatialAnchorsPublishInfoML* publishInfo,
XrFutureEXT* future);
The XrSpatialAnchorsPublishInfoML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsPublishInfoML {
XrStructureType type;
const void* next;
uint32_t anchorCount;
const XrSpace* anchors;
uint64_t expiration;
} XrSpatialAnchorsPublishInfoML;
Once the XrFutureEXT
has completedxrPublishSpatialAnchorsCompleteML must be called to retrieve theXrUuidEXT values of the published anchors.
The xrPublishSpatialAnchorsCompleteML function is defined as:
// Provided by XR_ML_spatial_anchors_storage
XrResult xrPublishSpatialAnchorsCompleteML(
XrSpatialAnchorsStorageML storage,
XrFutureEXT future,
XrSpatialAnchorsPublishCompletionML* completion);
The XrSpatialAnchorsPublishCompletionML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsPublishCompletionML {
XrStructureType type;
void* next;
XrResult futureResult;
uint32_t uuidCount;
XrUuidEXT* uuids;
} XrSpatialAnchorsPublishCompletionML;
The XrSpatialAnchorsPublishCompletionDetailsML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsPublishCompletionDetailsML {
XrStructureType type;
void* next;
uint32_t resultCount;
XrSpatialAnchorCompletionResultML* results;
} XrSpatialAnchorsPublishCompletionDetailsML;
The XrSpatialAnchorCompletionResultML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorCompletionResultML {
XrUuidEXT uuid;
XrResult result;
} XrSpatialAnchorCompletionResultML;
12.110.5. Delete Published Anchors
To delete anchors from the storage, xrDeleteSpatialAnchorsAsyncML canbe used.
The xrDeleteSpatialAnchorsAsyncML function is defined as:
// Provided by XR_ML_spatial_anchors_storage
XrResult xrDeleteSpatialAnchorsAsyncML(
XrSpatialAnchorsStorageML storage,
const XrSpatialAnchorsDeleteInfoML* deleteInfo,
XrFutureEXT* future);
The XrSpatialAnchorsDeleteInfoML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsDeleteInfoML {
XrStructureType type;
const void* next;
uint32_t uuidCount;
const XrUuidEXT* uuids;
} XrSpatialAnchorsDeleteInfoML;
Once the XrFutureEXT
has completedxrPublishSpatialAnchorsCompleteML must be called to retrieve the status of the delete operation.
The xrDeleteSpatialAnchorsCompleteML function is defined as:
// Provided by XR_ML_spatial_anchors_storage
XrResult xrDeleteSpatialAnchorsCompleteML(
XrSpatialAnchorsStorageML storage,
XrFutureEXT future,
XrSpatialAnchorsDeleteCompletionML* completion);
The XrSpatialAnchorsDeleteCompletionML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsDeleteCompletionML {
XrStructureType type;
void* next;
XrResult futureResult;
} XrSpatialAnchorsDeleteCompletionML;
The XrSpatialAnchorsDeleteCompletionDetailsML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsDeleteCompletionDetailsML {
XrStructureType type;
void* next;
uint32_t resultCount;
XrSpatialAnchorCompletionResultML* results;
} XrSpatialAnchorsDeleteCompletionDetailsML;
12.110.6. Update published Anchors expiration
To update the expiration time on anchorsxrUpdateSpatialAnchorsExpirationAsyncML can be used.
The xrUpdateSpatialAnchorsExpirationAsyncML function is defined as:
// Provided by XR_ML_spatial_anchors_storage
XrResult xrUpdateSpatialAnchorsExpirationAsyncML(
XrSpatialAnchorsStorageML storage,
const XrSpatialAnchorsUpdateExpirationInfoML* updateInfo,
XrFutureEXT* future);
The XrSpatialAnchorsUpdateExpirationInfoML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsUpdateExpirationInfoML {
XrStructureType type;
const void* next;
uint32_t uuidCount;
const XrUuidEXT* uuids;
uint64_t expiration;
} XrSpatialAnchorsUpdateExpirationInfoML;
Once the XrFutureEXT
has completedxrUpdateSpatialAnchorsExpirationCompleteML must be called to retrieve the status of the publish operation.
The xrUpdateSpatialAnchorsExpirationCompleteML function is defined as:
// Provided by XR_ML_spatial_anchors_storage
XrResult xrUpdateSpatialAnchorsExpirationCompleteML(
XrSpatialAnchorsStorageML storage,
XrFutureEXT future,
XrSpatialAnchorsUpdateExpirationCompletionML* completion);
The XrSpatialAnchorsUpdateExpirationCompletionML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsUpdateExpirationCompletionML {
XrStructureType type;
void* next;
XrResult futureResult;
} XrSpatialAnchorsUpdateExpirationCompletionML;
The XrSpatialAnchorsUpdateExpirationCompletionDetailsML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsUpdateExpirationCompletionDetailsML {
XrStructureType type;
void* next;
uint32_t resultCount;
XrSpatialAnchorCompletionResultML* results;
} XrSpatialAnchorsUpdateExpirationCompletionDetailsML;
12.110.7. Create Spatial Anchors from Storage
Spatial Anchors can be created from the storage XrUuidEXT by passing the XrSpatialAnchorsCreateInfoFromUuidsML structure toxrCreateSpatialAnchorsAsyncML.
The XrSpatialAnchorsCreateInfoFromUuidsML structure is defined as:
// Provided by XR_ML_spatial_anchors_storage
typedef struct XrSpatialAnchorsCreateInfoFromUuidsML {
XrStructureType type;
const void* next;
XrSpatialAnchorsStorageML storage;
uint32_t uuidCount;
const XrUuidEXT* uuids;
} XrSpatialAnchorsCreateInfoFromUuidsML;
The XrSpace handle or handles returned viaXrCreateSpatialAnchorsCompletionML::spaces
must be in the same order as uuids
.
The XrCreateSpatialAnchorsCompletionML::spaceCount
field mustmatch uuidCount
. If not the runtime must return XR_ERROR_VALIDATION_FAILURE
inXrCreateSpatialAnchorsCompletionML::futureResult
.
If an anchor with a given UUID is not found, the runtime must returnXR_NULL_HANDLE for the corresponding XrSpace handle(s) and return XR_SUCCESS
inXrCreateSpatialAnchorsCompletionML::futureResult
.
12.110.8. Examples
This example shows how to persist a list of anchors.
XrInstance instance; // previously initialized
XrSession session; // previously initialized
XrSpace anchor1; // previously initialized
XrSpace anchor2; // previously initialized
std::vector<XrSpace> anchors{anchor1, anchor2};
XrSpatialAnchorsCreateStorageInfoML storageCreateInfo{XR_TYPE_SPATIAL_ANCHORS_CREATE_STORAGE_INFO_ML};
XrSpatialAnchorsStorageML storage;
CHK_XR(xrCreateSpatialAnchorsStorageML(session, &storageCreateInfo, &storage));
XrSpatialAnchorsPublishInfoML publishInfo{XR_TYPE_SPATIAL_ANCHORS_PUBLISH_INFO_ML};
publishInfo.anchorCount = static_cast<uint32_t>(anchors.size());
publishInfo.anchors = anchors.data();
publishInfo.expiration = 0;
XrFutureEXT future;
CHK_XR(xrPublishSpatialAnchorsAsyncML(storage, &publishInfo, &future));
XrFuturePollInfoEXT pollInfo{XR_TYPE_FUTURE_POLL_INFO_EXT};
XrFuturePollResultEXT pollResult{XR_TYPE_FUTURE_POLL_RESULT_EXT};
pollInfo.future = future;
pollResult.state = XR_FUTURE_STATE_PENDING_EXT;
// Ideally this should be done once in your
// game loop instead of a busy wait.
while(pollResult.state==XR_FUTURE_STATE_PENDING_EXT) {
CHK_XR(xrPollFutureEXT(instance, &pollInfo, &pollResult));
}
XrSpatialAnchorsPublishCompletionML completion{XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_ML};
std::vector<XrUuidEXT> uuids(anchors.size());
completion.uuidCount = static_cast<uint32_t>(uuids.size());
completion.uuids = uuids.data();
CHK_XR(xrPublishSpatialAnchorsCompleteML(storage, future, &completion));
CHK_XR(completion.futureResult);
// completion.uuid will now contain the UUID of the corresponding Spatial Anchors.
CHK_XR(xrDestroySpatialAnchorsStorageML(storage));
This example shows how to query for anchors.
XrTime currentTime; // previously initialized
XrVector3f center; // previously initialized
XrSpatialAnchorsCreateStorageInfoML storageCreateInfo{XR_TYPE_SPATIAL_ANCHORS_CREATE_STORAGE_INFO_ML};
XrSpatialAnchorsStorageML storage;
CHK_XR(xrCreateSpatialAnchorsStorageML(session, &storageCreateInfo, &storage));
// set up a query around a previously initialized center position with a radius of 10 meters.
XrSpatialAnchorsQueryInfoRadiusML queryInfo{XR_TYPE_SPATIAL_ANCHORS_QUERY_INFO_RADIUS_ML};
queryInfo.baseSpace = viewSpace; // using viewspace, but can: be any space.
queryInfo.center = center;
queryInfo.time = currentTime;
queryInfo.radius = 10.0f;
XrFutureEXT future;
CHK_XR(xrQuerySpatialAnchorsAsyncML(storage, reinterpret_cast<XrSpatialAnchorsQueryInfoBaseHeaderML*>(&queryInfo), &future));
XrFuturePollInfoEXT pollInfo{XR_TYPE_FUTURE_POLL_INFO_EXT};
XrFuturePollResultEXT pollResult{XR_TYPE_FUTURE_POLL_RESULT_EXT};
pollInfo.future = future;
pollResult.state = XR_FUTURE_STATE_PENDING_EXT;
// Ideally this should be done once in your
// frame loop instead of a busy wait.
while(pollResult.state==XR_FUTURE_STATE_PENDING_EXT) {
CHK_XR(xrPollFutureEXT(instance, &pollInfo, &pollResult));
}
XrSpatialAnchorsQueryCompletionML completion{XR_TYPE_SPATIAL_ANCHORS_QUERY_COMPLETION_ML};
CHK_XR(xrQuerySpatialAnchorsCompleteML(storage, future, &completion));
CHK_XR(completion.futureResult);
std::vector<XrUuidEXT> uuids(completion.uuidCountOutput);
completion.uuidCapacityInput = static_cast<uint32_t>(uuids.size());
completion.uuids = uuids.data();
CHK_XR(xrQuerySpatialAnchorsCompleteML(storage, future, &completion));
// completion.uuid will now contain the UUID of the corresponding Spatial Anchors.
CHK_XR(xrDestroySpatialAnchorsStorageML(storage));
12.110.11. New Structures
Extending XrSpatialAnchorsDeleteCompletionML:
Extending XrSpatialAnchorsPublishCompletionML:
Extending XrSpatialAnchorsUpdateExpirationCompletionML:
12.110.12. New Enum Constants
XR_ML_SPATIAL_ANCHORS_STORAGE_EXTENSION_NAME
XR_ML_spatial_anchors_storage_SPEC_VERSION
Extending XrObjectType:
XR_OBJECT_TYPE_SPATIAL_ANCHORS_STORAGE_ML
Extending XrResult:
XR_ERROR_SPATIAL_ANCHORS_ANCHOR_NOT_FOUND_ML
Extending XrStructureType:
XR_TYPE_SPATIAL_ANCHORS_CREATE_INFO_FROM_UUIDS_ML
XR_TYPE_SPATIAL_ANCHORS_CREATE_STORAGE_INFO_ML
XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_DETAILS_ML
XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_ML
XR_TYPE_SPATIAL_ANCHORS_DELETE_INFO_ML
XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_DETAILS_ML
XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_ML
XR_TYPE_SPATIAL_ANCHORS_PUBLISH_INFO_ML
XR_TYPE_SPATIAL_ANCHORS_QUERY_COMPLETION_ML
XR_TYPE_SPATIAL_ANCHORS_QUERY_INFO_RADIUS_ML
XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_DETAILS_ML
XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_ML
XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_INFO_ML
Version History
Revision 1, 2023-06-22 (Ron Bessems)
Initial extension description