XR_ANDROID_geospatial

Name String

XR_ANDROID_geospatial

Extension Type

Instance extension

Registered Extension Number

790

Revision

1

Ratification Status

Not ratified

Extension and Version Dependencies

XR_EXT_future

Last Modified Date

2025-12-18

IP Status

No known IP claims.

Contributors

John Ullman, Google
Ben King, Google
Nihav Jain, Google
Jared Finder, Google

Overview

This extension provides the Geospatial tracking for Google’s Geospatial API, which provides precise geo-location and orientation, and allows the application to place content with respect to the Earth. It does this using a combination of motion tracking, GPS and other sensors, and Google’s Visual Positioning System (VPS). VPS compares images from a device’s camera to Street View imagery in order to determine a precise location and orientation. The Geospatial API often provides sub-meter positional accuracy (orders of magnitude better than GPS) and sub-degree orientation accuracy.

To successfully use the APIs in this extension (other than checking for extension support), the application must have successfully set authentication credentials via some mechanism, such as XR_ANDROID_google_cloud_auth . See the auth extension’s documentation for more details about setup and error results.

Permissions

Android applications must have the android.permission.ACCESS_FINE_LOCATION permission listed in their manifest to use this extension. The android.permission.ACCESS_FINE_LOCATION permission is considered a dangerous permission. The application must request the permission at runtime to use these functions:

(protection level: dangerous)

Inspect system capability

The XrSystemGeospatialPropertiesANDROID structure is defined as:

typedef struct XrSystemGeospatialPropertiesANDROID {
    XrStructureType    type;
    void*              next;
    XrBool32           supportsGeospatial;
} XrSystemGeospatialPropertiesANDROID;

Member Descriptions

  • type is the XrStructureType of this structure.
  • next is NULL or a pointer to the next structure in a structure chain. No such structures are defined in core OpenXR or this extension.
  • supportsGeospatial is an XrBool32 , indicating if the current system supports geospatial features.

An application can inspect whether the system supports geospatial features by chaining an XrSystemGeospatialPropertiesANDROID structure to the XrSystemProperties when calling xrGetSystemProperties .

If a runtime returns XR_FALSE for supportsGeospatial , the system does not support geospatial features, and therefore must return XR_ERROR_FEATURE_UNSUPPORTED from xrCreateGeospatialTrackerANDROID . The application should avoid using geospatial functionality when supportsGeospatial is XR_FALSE .

Valid Usage (Implicit)

Create a Geospatial Tracker handle

XR_DEFINE_HANDLE(XrGeospatialTrackerANDROID)

The xrCreateGeospatialTrackerANDROID function is defined as:

XrResult xrCreateGeospatialTrackerANDROID(
    XrSession                                   session,
    const XrGeospatialTrackerCreateInfoANDROID* createInfo,
    XrGeospatialTrackerANDROID*                 geospatialTrackerOutput);

Parameter Descriptions

An application can create an XrGeospatialTrackerANDROID handle by calling xrCreateGeospatialTrackerANDROID . The returned XrGeospatialTrackerANDROID handle can be subsequently used in API calls. If the application has not obtained the required permissions, the runtime must return XR_ERROR_PERMISSION_INSUFFICIENT . Only one XrGeospatialTrackerANDROID can exist at a time for a particular XrSession . The application must ensure that any previous XrGeospatialTrackerANDROID objects have been destroyed before calling this function again, otherwise the runtime must return XR_ERROR_LIMIT_REACHED . If the tracker is successfully created, it will initially enter the state XR_GEOSPATIAL_TRACKER_STATE_STOPPED_ANDROID , and the application must wait until the state changes to XR_GEOSPATIAL_TRACKER_STATE_RUNNING_ANDROID before using the tracker. See XrEventDataGeospatialTrackerStateChangedANDROID . If the application passes an XrGeospatialTrackerANDROID which is not in the state XR_GEOSPATIAL_TRACKER_STATE_RUNNING_ANDROID to a function which requires it, the runtime must return XR_ERROR_GEOSPATIAL_TRACKER_NOT_RUNNING_ANDROID .

The XrGeospatialTrackerANDROID handle must be eventually freed via the xrDestroyGeospatialTrackerANDROID function.

Valid Usage (Implicit)

Return Codes

Success

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Failure

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_LIMIT_REACHED
  • XR_ERROR_OUT_OF_MEMORY
  • XR_ERROR_PERMISSION_INSUFFICIENT
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_VALIDATION_FAILURE

The XrGeospatialTrackerCreateInfoANDROID structure is defined as:

typedef struct XrGeospatialTrackerCreateInfoANDROID {
    XrStructureType    type;
    const void*        next;
} XrGeospatialTrackerCreateInfoANDROID;

Member Descriptions

  • type is the XrStructureType of this structure.
  • next is NULL or a pointer to the next structure in a structure chain.

Valid Usage (Implicit)

The xrDestroyGeospatialTrackerANDROID function is defined as:

XrResult xrDestroyGeospatialTrackerANDROID(
    XrGeospatialTrackerANDROID                  geospatialTracker);

Parameter Descriptions

An application can use xrDestroyGeospatialTrackerANDROID function to release the geospatial tracker and the underlying resources.

Valid Usage (Implicit)

Thread Safety

  • Access to geospatialTracker , and any child handles, must be externally synchronized

Return Codes

Success

  • XR_SUCCESS

Failure

  • XR_ERROR_CALL_ORDER_INVALID
  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID

Geospatial Tracker State

The XrGeospatialTrackerStateANDROID enumeration is defined as:

typedef enum XrGeospatialTrackerStateANDROID {
    XR_GEOSPATIAL_TRACKER_STATE_STOPPED_ANDROID = 0,
    XR_GEOSPATIAL_TRACKER_STATE_RUNNING_ANDROID = 1,
    XR_GEOSPATIAL_TRACKER_STATE_INITIALIZATION_FAILED_ANDROID = 2,
    XR_GEOSPATIAL_TRACKER_STATE_MAX_ENUM_ANDROID = 0x7FFFFFFF
} XrGeospatialTrackerStateANDROID;

The XrGeospatialTrackerStateANDROID enumeration identifies the different states of a geospatial tracker.

The enumerants have the following values:

Enum Description

XR_GEOSPATIAL_TRACKER_STATE_STOPPED_ANDROID

The Geospatial Tracker is not running.

XR_GEOSPATIAL_TRACKER_STATE_RUNNING_ANDROID

The Geospatial tracker is running and usable.

XR_GEOSPATIAL_TRACKER_STATE_INITIALIZATION_FAILED_ANDROID

The Geospatial Tracker failed to initialize, and will never be usable.

The XrEventDataGeospatialTrackerStateChangedANDROID structure is defined as:

typedef struct XrEventDataGeospatialTrackerStateChangedANDROID {
    XrStructureType                    type;
    const void*                        next;
    XrGeospatialTrackerANDROID         geospatialTracker;
    XrGeospatialTrackerStateANDROID    state;
    XrResult                           initializationResult;
    XrTime                             time;
} XrEventDataGeospatialTrackerStateChangedANDROID;

Member Descriptions

  • type is the XrStructureType of this structure.
  • next is NULL or a pointer to the next structure in a structure chain.
  • geospatialTracker is the XrGeospatialTrackerANDROID whose state has changed.
  • state is the new XrGeospatialTrackerStateANDROID .
  • initializationResult is the error result if state is XR_GEOSPATIAL_TRACKER_STATE_INITIALIZATION_FAILED_ANDROID , otherwise XR_SUCCESS .
  • time is the XrTime at which the state change occurred.

The XrEventDataGeospatialTrackerStateChangedANDROID structure is sent when the geospatial tracker state changes. If the application has a valid XrGeospatialTrackerANDROID , it should poll for this event. The first event received for a tracker will have state XR_GEOSPATIAL_TRACKER_STATE_STOPPED_ANDROID . After a runtime-determined amount of time, the state must change to either XR_GEOSPATIAL_TRACKER_STATE_RUNNING_ANDROID or XR_GEOSPATIAL_TRACKER_STATE_INITIALIZATION_FAILED_ANDROID . This transition will take an arbitrary amount of time. If state changes to XR_GEOSPATIAL_TRACKER_STATE_INITIALIZATION_FAILED_ANDROID , it must be the last event received for this tracker, and the initializationResult field will hold the error code. It may take several seconds for an error to occur. The application should destroy the tracker in this case. If state changes to XR_GEOSPATIAL_TRACKER_STATE_STOPPED_ANDROID , all previously created geospatial anchors must permanently stop tracking and should be destroyed by the application. The state may change back and forth between XR_GEOSPATIAL_TRACKER_STATE_RUNNING_ANDROID and XR_GEOSPATIAL_TRACKER_STATE_STOPPED_ANDROID arbitrarily many times.

Valid Usage (Implicit)

Geospatial Pose

The XrGeospatialPoseANDROID structure is defined as:

typedef struct XrGeospatialPoseANDROID {
    XrQuaternionf    eastUpSouthOrientation;
    double           latitude;
    double           longitude;
    double           altitude;
} XrGeospatialPoseANDROID;

Member Descriptions

  • eastUpSouthOrientation is an XrQuaternionf defining the orientation with respect to a coordinate system where +X=East, +Y=Up and +Z=South.
  • latitude is the latitude in degrees, between -90 and +90.
  • longitude is the longitude in degrees, between -180 and +180.
  • altitude is the altitude in meters above the WGS84 ellipsoid.

The XrGeospatialPoseANDROID structure represents a position and orientation relative to the Earth using the WGS84 ellipsoid.

Valid Usage (Implicit)

  • The XR_ANDROID_geospatial extension must be enabled prior to using XrGeospatialPoseANDROID
  • latitude must be a valid double value
  • longitude must be a valid double value
  • altitude must be a valid double value

The XrGeospatialPoseFlagBitsANDROID enumeration is defined as:

// Flag bits for XrGeospatialPoseFlagsANDROID
static const XrGeospatialPoseFlagsANDROID XR_GEOSPATIAL_POSE_ORIENTATION_VALID_BIT_ANDROID = 0x00000001;
static const XrGeospatialPoseFlagsANDROID XR_GEOSPATIAL_POSE_POSITION_VALID_BIT_ANDROID = 0x00000002;

The XrGeospatialPoseFlagBitsANDROID enumeration specifies flags for geospatial poses.

The flag bits have the following meanings:

Flag Descriptions

  • XR_GEOSPATIAL_POSE_ORIENTATION_VALID_BIT_ANDROID — Indicates that the orientation member contains valid data
  • XR_GEOSPATIAL_POSE_POSITION_VALID_BIT_ANDROID — Indicates that the position member contains valid data

The XrGeospatialPoseFlagsANDROID type is a bitmask of XrGeospatialPoseFlagBitsANDROID .

typedef XrFlags64 XrGeospatialPoseFlagsANDROID;

Converting XrPosef to Geospatial Pose

The xrLocateGeospatialPoseFromPoseANDROID function is defined as:

XrResult xrLocateGeospatialPoseFromPoseANDROID(
    XrGeospatialTrackerANDROID                  geospatialTracker,
    const XrGeospatialPoseFromPoseLocateInfoANDROID* locateInfo,
    XrGeospatialPoseResultANDROID*              geospatialPoseResult);

Parameter Descriptions

The xrLocateGeospatialPoseFromPoseANDROID function converts a pose in XrGeospatialPoseFromPoseLocateInfoANDROID :: space to a geospatial pose. If the state of geospatialTracker is not XR_GEOSPATIAL_TRACKER_STATE_RUNNING_ANDROID , the runtime must return XR_ERROR_GEOSPATIAL_TRACKER_NOT_RUNNING_ANDROID . If the function returns XR_SUCCESS , the XrGeospatialPoseResultANDROID :: poseFlags field of geospatialPoseResult determines which output fields are valid. If XR_GEOSPATIAL_POSE_POSITION_VALID_BIT_ANDROID is not set in XrGeospatialPoseResultANDROID :: poseFlags , the application must not read the fields XrGeospatialPoseANDROID :: latitude , XrGeospatialPoseANDROID :: longitude , XrGeospatialPoseANDROID :: altitude , XrGeospatialPoseResultANDROID :: horizontalAccuracy or XrGeospatialPoseResultANDROID :: verticalAccuracy in XrGeospatialPoseResultANDROID . If XR_GEOSPATIAL_POSE_ORIENTATION_VALID_BIT_ANDROID is not set in XrGeospatialPoseResultANDROID :: poseFlags , the application must not read XrGeospatialPoseANDROID :: eastUpSouthOrientation or XrGeospatialPoseResultANDROID :: orientationYawAccuracy . If XR_GEOSPATIAL_POSE_POSITION_VALID_BIT_ANDROID is not set, XR_GEOSPATIAL_POSE_ORIENTATION_VALID_BIT_ANDROID must also not be set.

If the accuracy is lower than expected, this may be an indication that the device is not utilizing VPS localization. The application can instruct the user to point their device at signs and buildings to improve localization.

Valid Usage (Implicit)

Return Codes

Success

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Failure

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_GEOSPATIAL_TRACKER_NOT_RUNNING_ANDROID
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_POSE_INVALID
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_TIME_INVALID
  • XR_ERROR_VALIDATION_FAILURE

The XrGeospatialPoseFromPoseLocateInfoANDROID structure is defined as:

typedef struct XrGeospatialPoseFromPoseLocateInfoANDROID {
    XrStructureType    type;
    const void*        next;
    XrSpace            space;
    XrTime             time;
    XrPosef            pose;
} XrGeospatialPoseFromPoseLocateInfoANDROID;

Member Descriptions

  • type is the XrStructureType of this structure.
  • next is NULL or a pointer to the next structure in a structure chain.
  • space is the XrSpace in which pose is defined.
  • time is the XrTime at which to evaluate pose .
  • pose is the XrPosef in space to convert to a geospatial pose.

Valid Usage (Implicit)

The XrGeospatialPoseResultANDROID structure is defined as:

typedef struct XrGeospatialPoseResultANDROID {
    XrStructureType                 type;
    void*                           next;
    XrGeospatialPoseFlagsANDROID    poseFlags;
    XrGeospatialPoseANDROID         geospatialPose;
    double                          horizontalAccuracy;
    double                          verticalAccuracy;
    double                          orientationYawAccuracy;
} XrGeospatialPoseResultANDROID;

Member Descriptions

  • type is the XrStructureType of this structure.
  • next is NULL or a pointer to the next structure in a structure chain.
  • poseFlags is a bitmask of XrGeospatialPoseFlagsANDROID indicating validity of pose components.
  • geospatialPose is the resulting XrGeospatialPoseANDROID .
  • horizontalAccuracy is the estimated horizontal accuracy of the Geospatial pose position, defined as the radius in meters of the circle of 68% confidence level around the given latitude and longitude.
  • verticalAccuracy is the estimated vertical accuracy of the Geospatial pose position, defined as the distance in meters of 68% confidence level around the given altitude. In other words, there is a 68% chance that the true altitude is in the range [ XrGeospatialPoseANDROID :: altitude - verticalAccuracy , XrGeospatialPoseANDROID :: altitude \+ verticalAccuracy ].
  • orientationYawAccuracy is the estimated yaw accuracy of the Geospatial pose orientation, defined as the radius in degrees of 68% confidence level around the given orientation.

Valid Usage (Implicit)

Converting a Geospatial Pose to an XrPosef

The xrLocateGeospatialPoseANDROID function is defined as:

XrResult xrLocateGeospatialPoseANDROID(
    XrGeospatialTrackerANDROID                  geospatialTracker,
    const XrGeospatialPoseLocateInfoANDROID*    locateInfo,
    XrSpaceLocation*                            location);

Parameter Descriptions

The xrLocateGeospatialPoseANDROID function converts a geospatial pose to an XrSpaceLocation . If the XrGeospatialTrackerANDROID is not running, the runtime must return XR_ERROR_GEOSPATIAL_TRACKER_NOT_RUNNING_ANDROID . If the function returns XR_SUCCESS , the XrSpaceLocation :: locationFlags field of location determines which output fields are valid.

Valid Usage (Implicit)

Return Codes

Success

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Failure

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_GEOSPATIAL_COORDINATES_INVALID_ANDROID
  • XR_ERROR_GEOSPATIAL_TRACKER_NOT_RUNNING_ANDROID
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_TIME_INVALID
  • XR_ERROR_VALIDATION_FAILURE

The XrGeospatialPoseLocateInfoANDROID structure is defined as:

typedef struct XrGeospatialPoseLocateInfoANDROID {
    XrStructureType            type;
    const void*                next;
    XrSpace                    space;
    XrTime                     time;
    XrGeospatialPoseANDROID    geospatialPose;
} XrGeospatialPoseLocateInfoANDROID;

Member Descriptions

  • type is the XrStructureType of this structure.
  • next is NULL or a pointer to the next structure in a structure chain.
  • space is the XrSpace in which the resulting pose will be represented.
  • time is the XrTime at which to locate the pose.
  • geospatialPose is the XrGeospatialPoseANDROID to convert.

Valid Usage (Implicit)

VPS Availability

The XrVPSAvailabilityANDROID enumeration is defined as:

typedef enum XrVPSAvailabilityANDROID {
    XR_VPS_AVAILABILITY_UNAVAILABLE_ANDROID = 1,
    XR_VPS_AVAILABILITY_AVAILABLE_ANDROID = 2,
    XR_VPSAVAILABILITY_MAX_ENUM_ANDROID = 0x7FFFFFFF
} XrVPSAvailabilityANDROID;

The XrVPSAvailabilityANDROID enumeration indicates VPS availability.

The enumerants have the following values:

Enum Description

XR_VPS_AVAILABILITY_UNAVAILABLE_ANDROID

VPS is not available near the given location.

XR_VPS_AVAILABILITY_AVAILABLE_ANDROID

VPS is available near the given location.

The xrCheckVpsAvailabilityAsyncANDROID function is defined as:

XrResult xrCheckVpsAvailabilityAsyncANDROID(
    XrSession                                   session,
    double                                      latitude,
    double                                      longitude,
    XrFutureEXT*                                future);

Parameter Descriptions

  • session is the XrSession to use for the check.
  • latitude is the latitude in degrees.
  • longitude is the longitude in degrees.
  • future is a pointer to XrFutureEXT that will hold the result of the asynchronous operation.

Visual Positioning Service (VPS) availability indicates whether VPS can be used to improve geospatial accuracy at a given location.

The xrCheckVpsAvailabilityAsyncANDROID function begins an asynchronous check for VPS availability at a given location. The application does not need an XrGeospatialTrackerANDROID to call this function, and can use the result of this operation to decide whether to create one. If the application has not obtained the required permissions, the runtime must return XR_ERROR_PERMISSION_INSUFFICIENT .

Valid Usage (Implicit)

  • The XR_ANDROID_geospatial extension must be enabled prior to calling xrCheckVpsAvailabilityAsyncANDROID
  • session must be a valid XrSession handle
  • latitude must be a valid double value
  • longitude must be a valid double value
  • future must be a pointer to an XrFutureEXT value

Return Codes

Success

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Failure

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_GEOSPATIAL_COORDINATES_INVALID_ANDROID
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_VALIDATION_FAILURE

The xrCheckVpsAvailabilityCompleteANDROID function is defined as:

XrResult xrCheckVpsAvailabilityCompleteANDROID(
    XrSession                                   session,
    XrFutureEXT                                 future,
    XrVPSAvailabilityCheckCompletionANDROID*    completion);

Parameter Descriptions

Valid Usage (Implicit)

Return Codes

Success

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Failure

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_FUTURE_INVALID_EXT
  • XR_ERROR_FUTURE_PENDING_EXT
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_VALIDATION_FAILURE

The XrVPSAvailabilityCheckCompletionANDROID structure is defined as:

typedef struct XrVPSAvailabilityCheckCompletionANDROID {
    XrStructureType             type;
    void*                       next;
    XrResult                    futureResult;
    XrVPSAvailabilityANDROID    availability;
} XrVPSAvailabilityCheckCompletionANDROID;

Member Descriptions

  • type is the XrStructureType of this structure.
  • next is NULL or a pointer to the next structure in a structure chain.
  • futureResult is the XrResult of the check operation. If futureResult is XR_ERROR_GEOSPATIAL_CLOUD_AUTH_FAILED_ANDROID , a structure in the next chain may provide more information about the failure.
  • availability is the resulting XrVPSAvailabilityANDROID . The application must not read this field unless futureResult is XR_SUCCESS .

Future Return Codes

futureResult values:

Success

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Failure

  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_GEOSPATIAL_CLOUD_AUTH_FAILED_ANDROID

Valid Usage (Implicit)

Example

Setup Geospatial Tracker

PFN_xrCheckVpsAvailabilityAsyncANDROID xrCheckVpsAvailabilityAsyncANDROID;
PFN_xrPollFutureEXT xrPollFutureEXT;
PFN_xrCheckVpsAvailabilityCompleteANDROID xrCheckVpsAvailabilityCompleteANDROID;
PFN_xrCreateGeospatialTrackerANDROID xrCreateGeospatialTrackerANDROID;
XrInstance instance = XR_NULL_HANDLE;
XrSystemId systemId = XR_NULL_SYSTEM_ID;
XrSession session = XR_NULL_HANDLE;
double lat = 37.422, lng = -122.084;

// Check for support.
XrSystemGeospatialPropertiesANDROID geospatialSystemProperties{
    XR_TYPE_SYSTEM_GEOSPATIAL_PROPERTIES_ANDROID};
XrSystemProperties systemProperties{XR_TYPE_SYSTEM_PROPERTIES,
                                    &geospatialSystemProperties};
CHK_XR(xrGetSystemProperties(instance, systemId, &systemProperties));
if (!geospatialSystemProperties.supportsGeospatial) {
  return;
}

// Check VPS Availability.
XrFutureEXT future = XR_NULL_FUTURE_EXT;
CHK_XR(xrCheckVpsAvailabilityAsyncANDROID(session, lat, lng, &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;
while (pollResult.state == XR_FUTURE_STATE_PENDING_EXT) {
  // Do in render loop/state loop.
  CHK_XR(xrPollFutureEXT(instance, &pollInfo, &pollResult));
}

XrVPSAvailabilityCheckCompletionANDROID vpsCompletion{
    XR_TYPE_VPS_AVAILABILITY_CHECK_COMPLETION_ANDROID};
CHK_XR(xrCheckVpsAvailabilityCompleteANDROID(session, future, &vpsCompletion));
if (vpsCompletion.futureResult == XR_SUCCESS) {
  if (vpsCompletion.availability == XR_VPS_AVAILABILITY_UNAVAILABLE_ANDROID) {
    // Visual Positioning Service is not available. Accuracy of positions and
    // orientations from Geospatial APIs are expected to be lower at this location.
  } else {
    // Visual Positioning Service is available. Higher accuracy of position and
    // orientation is achievable at this location.
  }
}

// Create Geospatial Tracker.
XrGeospatialTrackerCreateInfoANDROID createInfo{
    XR_TYPE_GEOSPATIAL_TRACKER_CREATE_INFO_ANDROID};
XrGeospatialTrackerANDROID geospatialTracker = XR_NULL_HANDLE;
CHK_XR(xrCreateGeospatialTrackerANDROID(session, &createInfo, &geospatialTracker));

// In application main event loop:
while (true) {
  XrEventDataBuffer event = {XR_TYPE_EVENT_DATA_BUFFER};
  if (xrPollEvent(instance, &event) != XR_SUCCESS) {
    continue;
  }
  switch (event.type) {
    case XR_TYPE_EVENT_DATA_GEOSPATIAL_TRACKER_STATE_CHANGED_ANDROID:
      const XrEventDataGeospatialTrackerStateChangedANDROID& eventData =
          *reinterpret_cast<XrEventDataGeospatialTrackerStateChangedANDROID*>(&event);
      switch (eventData.state) {
        case XR_GEOSPATIAL_TRACKER_STATE_STOPPED_ANDROID:
          // Destroy existing anchors, if any.
          break;
        case XR_GEOSPATIAL_TRACKER_STATE_RUNNING_ANDROID:
          // Start adding content.
          break;
        case XR_GEOSPATIAL_TRACKER_STATE_INITIALIZATION_FAILED_ANDROID:
          // Handle eventData.initializationResult error result.
          break;
      }
  }
}

Call Geospatial Pose APIs

PFN_xrLocateGeospatialPoseFromPoseANDROID xrLocateGeospatialPoseFromPoseANDROID;
PFN_xrLocateGeospatialPoseANDROID xrLocateGeospatialPoseANDROID;

XrGeospatialTrackerANDROID geospatialTracker;

// Get pose from view space.
XrSpace viewSpace;
XrPosef identityPose = {{0,0,0,1},{0,0,0}};
XrGeospatialPoseFromPoseLocateInfoANDROID poseGetInfo{
    XR_TYPE_GEOSPATIAL_POSE_FROM_POSE_LOCATE_INFO_ANDROID};
XrGeospatialPoseResultANDROID poseResult{
    XR_TYPE_GEOSPATIAL_POSE_RESULT_ANDROID};
poseGetInfo.space = viewSpace;
poseGetInfo.pose = identityPose;
poseGetInfo.time = 0;  // Next frame timestamp.
CHK_XR(xrLocateGeospatialPoseFromPoseANDROID(geospatialTracker, &poseGetInfo, &poseResult));
if ((poseResult.poseFlags & XR_GEOSPATIAL_POSE_ORIENTATION_VALID_BIT_ANDROID) &&
    (poseResult.poseFlags & XR_GEOSPATIAL_POSE_POSITION_VALID_BIT_ANDROID)) {
  // poseResult.geospatialPose is valid.
}

// Convert Geospatial pose to an XrSpaceLocation.
XrGeospatialPoseLocateInfoANDROID poseLocateInfo{
    XR_TYPE_GEOSPATIAL_POSE_LOCATE_INFO_ANDROID};
XrSpaceLocation location{XR_TYPE_SPACE_LOCATION};
poseLocateInfo.space = viewSpace;
poseLocateInfo.geospatialPose = poseResult.geospatialPose;
poseLocateInfo.time = 0; // Next frame timestamp.
CHK_XR(xrLocateGeospatialPoseANDROID(geospatialTracker, &poseLocateInfo, &location));
if ((location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) &&
    (location.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT)) {
  // location.pose is valid.
}

New Object Types

New Commands

New Structures

New Enums

New Bitmasks

New Enum Constants

  • XR_ANDROID_GEOSPATIAL_EXTENSION_NAME
  • XR_ANDROID_geospatial_SPEC_VERSION
  • Extending XrObjectType :

    • XR_OBJECT_TYPE_GEOSPATIAL_TRACKER_ANDROID
  • Extending XrResult :

    • XR_ERROR_GEOSPATIAL_CLOUD_AUTH_FAILED_ANDROID
    • XR_ERROR_GEOSPATIAL_COORDINATES_INVALID_ANDROID
    • XR_ERROR_GEOSPATIAL_TRACKER_NOT_RUNNING_ANDROID
  • Extending XrStructureType :

    • XR_TYPE_EVENT_DATA_GEOSPATIAL_TRACKER_STATE_CHANGED_ANDROID
    • XR_TYPE_GEOSPATIAL_POSE_FROM_POSE_LOCATE_INFO_ANDROID
    • XR_TYPE_GEOSPATIAL_POSE_LOCATE_INFO_ANDROID
    • XR_TYPE_GEOSPATIAL_POSE_RESULT_ANDROID
    • XR_TYPE_GEOSPATIAL_TRACKER_CREATE_INFO_ANDROID
    • XR_TYPE_SYSTEM_GEOSPATIAL_PROPERTIES_ANDROID
    • XR_TYPE_VPS_AVAILABILITY_CHECK_COMPLETION_ANDROID

Issues

Version History

  • Revision 1, 2025-12-18 (Ben King)

    • Initial extension description.