Skip to content

Commit 48adb11

Browse files
authored
Add in Glasses ArCore snippets (#818)
* add in arCore glasses snippets * add in arCore glasses snippets * update depecreated naming for DeviceTrackingMode and GeospatialMode * fix: use explicit Config constructor to avoid restricted API
1 parent 3b5e147 commit 48adb11

2 files changed

Lines changed: 210 additions & 0 deletions

File tree

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.xr.arcore
18+
19+
import androidx.xr.arcore.ArDevice
20+
import androidx.xr.runtime.DeviceTrackingMode
21+
import androidx.xr.runtime.Session
22+
import androidx.xr.runtime.SessionConfigureSuccess
23+
import androidx.xr.runtime.math.Pose
24+
25+
private fun configureDevicePose(session: Session) {
26+
// [START androidxr_arcore_device_pose_configure]
27+
// Define the configuration object to enable tracking device pose.
28+
val newConfig = session.config.copy(
29+
deviceTracking = DeviceTrackingMode.LAST_KNOWN
30+
)
31+
// Apply the configuration to the session.
32+
try {
33+
when (val configResult = session.configure(newConfig)) {
34+
is SessionConfigureSuccess -> {
35+
// The session is now configured to track the device's pose.
36+
}
37+
else -> {
38+
// Catch-all for other configuration errors returned using the result class.
39+
}
40+
}
41+
} catch (e: UnsupportedOperationException) {
42+
// Handle configuration failure. For example, if the specific mode is not supported on the current device or API version.
43+
}
44+
// [END androidxr_arcore_device_pose_configure]
45+
}
46+
47+
private suspend fun obtainDevicePose(session: Session) {
48+
// [START androidxr_arcore_device_pose_get]
49+
// Get the ArDevice instance
50+
val arDevice = ArDevice.getInstance(session)
51+
// There are two ways to get the device pose.
52+
53+
// 1. Get the current device pose once.
54+
// This is the device's position and orientation relative to the tracking origin.
55+
val devicePose = arDevice.state.value.devicePose
56+
processDevicePose(devicePose)
57+
58+
// 2. Continuously receive updates for the device pose.
59+
// `collect` is a suspending function that will run indefinitely and process new poses.
60+
arDevice.state.collect { state ->
61+
processDevicePose(state.devicePose)
62+
}
63+
// [END androidxr_arcore_device_pose_get]
64+
}
65+
66+
// [START androidxr_arcore_device_pose_process]
67+
fun processDevicePose(pose: Pose) {
68+
// Extract Translation and Rotation
69+
val translation = pose.translation // Vector3(x, y, z)
70+
val rotation = pose.rotation // Quaternion (x, y, z, w)
71+
TODO(/* Use the translation and rotation in your app. */)
72+
}
73+
// [END androidxr_arcore_device_pose_process]
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.xr.arcore
18+
19+
import androidx.xr.arcore.ArDevice
20+
import androidx.xr.arcore.CreateGeospatialPoseFromPoseNotTracking
21+
import androidx.xr.arcore.CreateGeospatialPoseFromPoseSuccess
22+
import androidx.xr.arcore.CreatePoseFromGeospatialPoseNotTracking
23+
import androidx.xr.arcore.CreatePoseFromGeospatialPoseSuccess
24+
import androidx.xr.arcore.Geospatial
25+
import androidx.xr.runtime.Config
26+
import androidx.xr.runtime.DeviceTrackingMode
27+
import androidx.xr.runtime.GeospatialMode
28+
import androidx.xr.runtime.Session
29+
import androidx.xr.runtime.SessionConfigureSuccess
30+
import androidx.xr.runtime.VpsAvailabilityAvailable
31+
import androidx.xr.runtime.VpsAvailabilityErrorInternal
32+
import androidx.xr.runtime.VpsAvailabilityNetworkError
33+
import androidx.xr.runtime.VpsAvailabilityNotAuthorized
34+
import androidx.xr.runtime.VpsAvailabilityResourceExhausted
35+
import androidx.xr.runtime.VpsAvailabilityUnavailable
36+
import androidx.xr.runtime.math.GeospatialPose
37+
import androidx.xr.runtime.math.Pose
38+
39+
private fun configureGeospatialSession(session: Session) {
40+
// [START androidxr_arcore_geospatial_configure]
41+
// Define the configuration object to enable Geospatial features.
42+
val newConfig = Config(
43+
// Set the GeospatialMode to VPS_AND_GPS.
44+
geospatial = GeospatialMode.VPS_AND_GPS,
45+
// Set the DeviceTrackingMode to LAST_KNOWN.
46+
deviceTracking = DeviceTrackingMode.LAST_KNOWN
47+
)
48+
// Apply the configuration to the session.
49+
try {
50+
when (val configResult = session.configure(newConfig)) {
51+
is SessionConfigureSuccess -> {
52+
// The session is now configured to use the Geospatial API.
53+
}
54+
else -> {
55+
// Handle other configuration errors (e.g., missing library dependencies).
56+
}
57+
}
58+
} catch (e: UnsupportedOperationException) {
59+
// Handle configuration failure if the mode is not supported.
60+
}
61+
// [END androidxr_arcore_geospatial_configure]
62+
}
63+
64+
private fun obtainGeospatial(session: Session) {
65+
// [START androidxr_arcore_geospatial_get_instance]
66+
// Get the Geospatial instance for the current session.
67+
val geospatial = Geospatial.getInstance(session)
68+
// [END androidxr_arcore_geospatial_get_instance]
69+
}
70+
71+
private suspend fun checkVpsAvailability(geospatial: Geospatial) {
72+
// [START androidxr_arcore_geospatial_check_vps]
73+
// You can query the GPS to get the current device's location.
74+
val latitude = 37.422
75+
val longitude = -122.084
76+
77+
// Use the geospatial instance to check VPS availability for a specific location.
78+
val result = geospatial.checkVpsAvailability(latitude, longitude)
79+
when (result) {
80+
is VpsAvailabilityAvailable -> {
81+
// VPS is available at this location.
82+
}
83+
is VpsAvailabilityErrorInternal -> {
84+
// VPS availability check failed with an internal error.
85+
}
86+
is VpsAvailabilityNetworkError -> {
87+
// VPS availability check failed due to a network error.
88+
}
89+
is VpsAvailabilityNotAuthorized -> {
90+
// VPS availability check failed due to an authorization error.
91+
}
92+
is VpsAvailabilityResourceExhausted -> {
93+
// VPS availability check failed due to resource exhaustion.
94+
}
95+
is VpsAvailabilityUnavailable -> {
96+
// VPS is not available at this location.
97+
}
98+
}
99+
// [END androidxr_arcore_geospatial_check_vps]
100+
}
101+
102+
private fun convertDeviceToGeospatial(session: Session, geospatial: Geospatial) {
103+
// [START androidxr_arcore_geospatial_device_to_geospatial]
104+
// Get the current device Pose from the AR Session's state.
105+
val devicePose = ArDevice.getInstance(session).state.value.devicePose
106+
107+
// Convert the device Pose into a GeospatialPose.
108+
when (val result = geospatial.createGeospatialPoseFromPose(devicePose)) {
109+
is CreateGeospatialPoseFromPoseSuccess -> {
110+
val geoPose = result.pose
111+
val lat = geoPose.latitude
112+
val lon = geoPose.longitude
113+
val alt = geoPose.altitude
114+
// Orientation is in the EUS (East-Up-South) coordinate system.
115+
val orientation = geoPose.eastUpSouthQuaternion
116+
}
117+
is CreateGeospatialPoseFromPoseNotTracking -> {
118+
// Geospatial is not currently tracking.
119+
}
120+
}
121+
// [END androidxr_arcore_geospatial_device_to_geospatial]
122+
}
123+
124+
private fun convertGeospatialToDevice(geospatial: Geospatial, geoPose: GeospatialPose) {
125+
// [START androidxr_arcore_geospatial_pose_to_device]
126+
// Convert a GeospatialPose (lat/long/alt) back to a device-space Pose.
127+
when (val result = geospatial.createPoseFromGeospatialPose(geoPose)) {
128+
is CreatePoseFromGeospatialPoseSuccess -> {
129+
val devicePose: Pose = result.pose
130+
// devicePose is now ready to be used relative to the tracking origin.
131+
}
132+
is CreatePoseFromGeospatialPoseNotTracking -> {
133+
// Geospatial is not currently tracking.
134+
}
135+
}
136+
// [END androidxr_arcore_geospatial_pose_to_device]
137+
}

0 commit comments

Comments
 (0)