Hey guys,
I was wondering if anyone could help me. I'm currently trying to run an ARKitSession() with a WorldTrackingProvider() that makes use of DeviceAnchor. In the simulator everything seems to work fine and the WorldTrackingProvider runs, but if I'm trying to run the app on my AVP, the WorldTrackingProvider pauses after the initialization. I'm new to Apple development and I would be thankful for any helpful input!
Below my current code:
HeadTrackingApp.swift
import SwiftUI
@main
struct HeadTrackingApp: App {
init() {
HeadTrackingSystem.registerSystem()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
ContentView.swift
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Text("Head Tracking Prototype")
.font(.largeTitle)
}
}
}
HeadTrackingSystem.swift
import SwiftUI
import ARKit
import RealityKit
class HeadTrackingSystem: System {
let arKitSession = ARKitSession()
let worldTrackingProvider = WorldTrackingProvider()
var avp: DeviceAnchor?
required public init(scene: RealityKit.Scene) {
setUpSession()
}
func setUpSession() {
Task {
do {
print("Starting ARKit session...")
try await arKitSession.run([worldTrackingProvider])
print("Initial World Tracking Provider State: \(worldTrackingProvider.state)")
self.avp = worldTrackingProvider.queryDeviceAnchor(atTimestamp: CACurrentMediaTime())
if let avp = getAVPPositionOrientation() {
print("AVP data: \(avp)")
} else {
print("No AVP position and orientation available.")
}
} catch {
print("Error: \(error)")
}
}
}
func getAVPPositionOrientation() -> DeviceAnchor? {
return avp
}
}
Hey @XWDev,
WorldTrackingProvider
can only query for the device anchor when an ImmersiveSpace
is open. There is a known bug where this works in the simulator without an immersive space open. Can you try this when in an immersive space?
Additionally, I see you are performing the query in the initialization. Consider moving this to the update function. As outlined in Create a system class, limit the initializer to only performing required initialization and setup. Add any logic needed to run your system in update(context:)
, which RealityKit calls every frame automatically.
You might consider an update(context:)
function that looks like the following:
public func update(context: SceneUpdateContext) {
guard worldTrackingProvider.state == .running else { return }
self.avp = worldTrackingProvider.queryDeviceAnchor(atTimestamp: CACurrentMediaTime())
}
Let me know if you have additional questions,
Michael