WorldTrackingProvider's queryDeviceAnchor is not giving correct deviceAnchor

I'm constructing a RealityView where I'd like to display content in front of user's face. When testing, I found that the deviceAnchor I initially get was wrong, so I implement following code to wait until the deviceAnchor I get from worldTrackingProvider has the correct value:

private let arkitSession = ARKitSession()
private let worldTrackingProvider = WorldTrackingProvider()

var body: some View {
        RealityView { content, attachments in

            Task {
                do {
// init worldTrackingProvider
                    try await arkitSession.run([worldTrackingProvider])

// wait until deviceAnchor returns correct info
                    var deviceAnchor : DeviceAnchor?
// continuously get deviceAnchor and check until it's valid
                   while (deviceAnchor == nil || !checkDeviceAnchorValid(Transform(matrix: deviceAnchor!.originFromAnchorTransform).translation)) {
                       deviceAnchor = worldTrackingProvider.queryDeviceAnchor(atTimestamp: CACurrentMediaTime())
                    }
                    let cameraTransform = Transform(matrix: deviceAnchor!.originFromAnchorTransform)

                  // ...codes that update my entity's translation

                } catch {
                    print("Error: \(error)")
                }
            }
        } 
    }
    
    private func checkDeviceAnchorValid(_ translation: SIMD3<Float>) -> Bool {
      // codes that check if the `deviceAnchor` has a valid translation.
    }

However, I found that sometimes I can't get out from the while loop defined above. Not because my rules inside checkDeviceAnchorValid func are too strict, but because the translation I get from deviceAnchor is always invalid(it is [0,0,0] and never changed)

Why is this happening? Is this a known issue? I wonder if I can get recalled when the worldTrackingProvider returns the correct deviceAnchor,

Replies

Hello,

Could you provide a focused sample project that reproduces the issue?

  • Hi, Thank you for the reply.

    because of the word count limit of comment, I've added a new comment to this question with some detailed information provided. Please take a look. Thanks!

Add a Comment

Hello gchiste, Thanks for the reply!

Please create a new visionOS app from xcode, replace the code in ImmersiveView with the following code, and change the preferred Default Scene Session Role to Immersive Space Application Session Role.


//

//  ImmersiveView.swift

//  deviceAnchorSample


//



import SwiftUI

import RealityKit

import ARKit



struct ImmersiveView: View {

    var body: some View {

        RealityView { content in

            Task {

                do {

                    try await arkitSession.run([worldTrackingProvider])

                    var deviceAnchor : DeviceAnchor?

                    while (deviceAnchor == nil || !checkDeviceAnchorValid(Transform(matrix: deviceAnchor!.originFromAnchorTransform).translation)) {

                        deviceAnchor = worldTrackingProvider.queryDeviceAnchor(atTimestamp: CACurrentMediaTime())

                    }

                    let cameraTransform = Transform(matrix: deviceAnchor!.originFromAnchorTransform)

//                    attachmentEntity.transform.translation = cameraTransform.translation + [0, 0.05, -1]

                } catch {

                    print("Error: \(error)")

                }

            }

        }

    }

    

    private func checkDeviceAnchorValid(_ translation: SIMD3<Float>) -> Bool {

        // device anchor's x and z should be almost zero, with y in the valid range of a human being's height

        print("deviceAnchor's translation:\(translation)")

        return abs(translation.x) < 0.1 && abs(translation.z) < 0.1 && translation.y > 0.2 && translation.y < 3

    }

    

    // MARK: Private



    private let arkitSession = ARKitSession()

    private let worldTrackingProvider = WorldTrackingProvider()

}



#Preview {

    ImmersiveView()

        .previewLayout(.sizeThatFits)

}//

When running, look for logs that start with deviceAnchor's translation:.The dead loop problem cannot be reproduced stably, But it did happen more than once.

Notice the jump change of the translation value, I think the main issue is that there are no callbacks or flags indicating the worldTrackingProvider is initiated.

I'm on Xcode 15.2(15C500b), and visionOS 1.0 (21N305) simulator