Re-orient TrackedPoseDriver

Hi there,

I’m trying to build a AR app using Google ARCore. The idea is to have a maze where the player can walk through (by physically walking). It works so far, the tracking works perfectly.

However, the physical space is sometimes limited. For this reason I would like the user to touch the screen to stop rotational tracking. The user can then rotate themselves in such a way that there is sufficient space in front of them and keep walking. The code I’m using is as such:

for (int i = 0; i < Input.touchCount; ++i){
if (Input.GetTouch(i).phase == TouchPhase.Began){
trackedPoseDriver.trackingType = TrackedPoseDriver.TrackingType.PositionOnly;
}

if (Input.GetTouch(i).phase == TouchPhase.Ended){
InputTracking.Recenter();
trackedPoseDriver.trackingType = TrackedPoseDriver.TrackingType.RotationAndPosition;
}
}

When I touch the screen, the tracker will indeed stop rotating as intended. But when I release the screen it snaps back. How would I solve this?

Woah I asked this question at π local time…

thats an interesting use case, Let me think about that one.

in the meantime, can you do a device space reset in AR Core? EG: In most VR headsets you can ask the device to treat the current position as “0,0,0”.

I’m having this same issue. I tried creating a new class that inherits from TrackedPoseDriver and called CacheLocalPosition and then ResetToCachedLocalPosition but the new rotations aren’t what I’d expect. The only thing I’ve been able to do is pause application and then reopen it does what I want it to do as if resetting the TrackedPoseDriver.

So, whats probably happening is that the “Cached” position is the world position that the camera started at in the scene. that, is then appended to the delta provided by your device.

Hmm, thinking about this now.

So I think I found a solution to both issues.
Essentially, my problem is that if the player had to move, I wanted them to be able to “reset” the positioning of the game but not move the world position of any of the game objects for networking reasons. I took a suggestion from this post – Setting world scale without affecting physics – and moved the parent of my TrackedPoseDriver GameObject instead of the object itself.

// The position I want the camera to be in world space.
Vector3 goalPosition;

// The forward I want the camera to be facing.
Vector3 goalForward;

// Transform of the TrackedPosedDriver.
Transform trackedPoseDriverTransform;

void Reset()
{
     Vector3 pos = trackedPoseDriverTransform.position;
     Vector3 delta = goalPosition - pos;
    
     // Gets the forward of the trackedPoseDriver, but remove the Y value as we just want the heading.
     Vector3 forward = trackedPoseDriverTransform.forward;
     forward.y = 0;
     forward.Normalize();
     Quaternion rotDelta = Quaternion q = Quaternion.FromToRotation(trackedPoseDriverTransform.forward, goalForward);

     trackedPoseDriveTransform.parent.position += delta;
     arTransform.parent.Rotate(0, q.eulerAngles.y, 0);
}

There might be a better way to do the rotation delta part, but this was able to get the results I wanted.

1 Like

Oh and two caveats.

  1. I am NOT doing any kind of plane tracking. This is just a simple game where you face forward and shoot at a target in the air.
  2. I find if I execute this method twice in a row, it’s more accurate, probably due to an error in my math I’m not seeing.

Thank you very much! I’m developing an XR app for Cardboard where I need to change the position but starting with a specific forward view. That worked in Unity with transform.lookAt(target) but doesn’t work in the cardboard device if the c camera gameObject has a TrackedPoseDriver.
Your -3 years old- post has helped me to reset and reorient the device. Thanks!!