XRRigidTransform invalid position error

Hello!

I have been working on a WebXR experience, which made easy thanks to you!

When I test the WebXR scene with a Meta Quest 3S device, I inconsistently have a TypeError at XRRigidTransform constructor “invalid position”, at WebXRCamera’s _updateReferenceSpacemethod. To guard against this issue, I am setting the reference space after entering XR as follows:

xrExperience.baseExperience.enterXRAsync('immersive-vr', 'local-floor').then((sessionManager) => {
      sessionManager.referenceSpace = sessionManager.referenceSpace.getOffsetReferenceSpace(new XRRigidTransform(
        XR_INIT_QUATERNION, // 0, 0, 0, 1; it gives error if w !== 1 
        XR_INIT_QUATERNION, // 0, 0, 0, 1
      ));

This seemed to be helping a little, but still I have the same error sometimes. It freezes the front frame and everything around becomes black. Unfortunately I am not able to debug or reproduce the issue in a PG. It is either occurring randomly or some specific headset transformation causes the calculations to throw the error.

I tried to reproduce with WebXR Emulator by Meta, but it works fine. A side note is I am using webxr-polyfill if navigator.xr is not present.

Thank you very much!

// @babylonjs/core/XR/webXRCamera.js
...

_updateReferenceSpace() {
    // were position & rotation updated OUTSIDE of the xr update loop
    ...
        transformMat.decompose(undefined, this._referenceQuaternion, this._referencedPosition);
        const transform = new XRRigidTransform({
            x: this._referencedPosition.x / this._xrSessionManager.worldScalingFactor,
            y: this._referencedPosition.y / this._xrSessionManager.worldScalingFactor,
            z: this._referencedPosition.z / this._xrSessionManager.worldScalingFactor,
        }, {
            x: this._referenceQuaternion.x,
            y: this._referenceQuaternion.y,
            z: this._referenceQuaternion.z,
            w: this._referenceQuaternion.w,
        });
        this._xrSessionManager.referenceSpace = this._xrSessionManager.referenceSpace.getOffsetReferenceSpace(transform);
    }
}

cc @docEdub who loves XR

Is this only happening on the 3S?

That’s the only device I have :slight_smile:

oh, ok. it’s the only one I don’t have :slight_smile:

I’ve never run into this issue before. Do you have any hints on how to reproduce the error? Does this happen with any of the WebXR playgrounds in the docs? Or maybe you can share some code that reproduces it?

Unfortunately cannot share the code, but it is not much about XR, except for I am setting the WebXRCamera quaternion in Scene.onBeforeRenderObservable callback*. The error is happening on a call by onXRFrameObservable, which calls WebXRCamera._updateReferenceSpace down the line.

I tried to figure out the reproduction steps, but I couldn’t find a pattern. It’s happening quite randomly. It may or may not happen when quickly looking towards a side; when putting the headset off, placing down for a couple seconds, moving around and putting on again; or putting out and randomly tilting by hand. But none of these cases always cause the error.

Since the comment at the first line in the _updateReferenceSpace method hints a recalculation of position and rotation, maybe there is a division error (unlikely) or calculated quaternion could be mathematically invalid?

One detail I missed is that I am using the right-handed system.

Part of code that manipulates xrCamera before each render is below. I am using the same snippet for controls in regular (non-XR) scenes.

// Limiting pitch to up and down vectors and
// changing yaw with dy which is calculated from thumbsticks
// and setting position
...
orientation = xrCamera.rotationQuaternion.toEulerAngles();
orientation.x = Math.min(Math.max(orientation.x, -Math.PI / 2 + 0.001), Math.PI / 2 - 0.001);
orientation.y += dy;
xrCamera.rotationQuaternion = orientation.toQuaternion();
checkpoint.moveWithCollisions(movementVector);
xrCamera.position.copyFrom(checkpoint.position);
...

Here’s what I see after the error. In the image the front frame is frozen, and I am looking a little to the right and downwards. After the error, glitches also appear (bottom right corner of the image which are barely visible in this image). The glitches are short lines in different colors, shaping out a hollow frame at headset position parallel to the front frame (just details).

Ok, thanks, I will try to reproduce this next week when I’m back home.

2 Likes

I have not been able to reproduce this, yet, but according to the docs we should always be setting w to 1. This does not strictly enforced, apparently, but since you are seeing this, and setting it to 1 as required does not cause regressions, I have created PR 17159 to address this.

1 Like

Thank you. The issue still persists “Failed to construct ‘XRRigidTransform’: Invalid position”

Could it be because of the calculation of the position values between XR frames, or because of somehow skipped XR frames? Can you give me a hint on how I can debug the issue further?

You can connect the headset to a computer with a USB cable and do remote debugging in Chrome dev tools. When connecting the headset, you should see a permissions request in the headset to allow the connection. Allow it, and then on the computer go to chrome://inspect/ in Chrome. You should see the headset listed in the “Remote Targets” section. Click “inspect” there to start remote debugging.

1 Like

Thanks, I was able to debug further and realized that _referencedPosition and _referenceQuaternion reads NaN values in all dimensions, then that causes the error. I tried to debug the issue further by setting a conditional breakpoint at setter of Quaternion.x, to track where the miscalulation is done, but it somehow did not work.

The call stack is:

  1. WebXRSessionManager.runXRRenderLoop
  2. onXRFrameObservable.notifyObservers
  3. onXRFrameObservable callback in WebXRCamera constructor
  4. WebXRCamera._updateReferenceSpace()
  5. Position and quaternion values are all NaN and XRRigidTransform constructor throws error

Hello again!

I was able to debug further and realized that WebXRControllerComponent.onAxisValueChangedObservable may emit NaN values for x or y. Therefore, my program used such values which calculates an intermediate vector/quaternion with at least one NaN dimension, then the rest of calculations were all NaN. I added a simple isNaN check in the observer callback to avoid the issue.

Long story short, the issue was the NaN event data, just for keeping in mind. I will update if the issue persists.

Thank you for the tips @docEdub!

1 Like