Unity google cardboard drift

1.2k views Asked by At

I'm using the latest googleVr SDK(1.10) but I tested some example scenes from unity like castle defence and I notice the view began to drift when I put the phone on the table. is there a way to prevent this drift programatically?

I saw some videos to correct the gyroscope on samsung but I want some code to prevent this

1

There are 1 answers

0
Gregoire Cattan On

It's still a non solved issue, as explained in this post:

GvrViewerMain rotates the camera yourself. Unity3D + Google VR

But according to your needs, you may find usefull the following workaround.

The idea is to find the delta rotation and ignore it if too small.

using UnityEngine;

public class GyroCorrector  {

    public enum Correction
    {
        NONE,
        BEST
    }

    private Correction m_correction;

    public GyroCorrector(Correction a_correction)
    {
        m_correction = a_correction;
    }

    private void CorrectValueByThreshold(ref Vector3 a_vDeltaRotation, float a_fXThreshold = 1e-1f, float a_fYThreshold = 1e-2f, float a_fZThreshold = 0.0f)
    {

      //  Debug.Log(a_quatDelta.x + " " + a_quatDelta.y + " " + a_quatDelta.z );

        a_vDeltaRotation.x = Mathf.Abs(a_vDeltaRotation.x) < a_fXThreshold ? 0.0f : a_vDeltaRotation.x + a_fXThreshold;
        a_vDeltaRotation.y = Mathf.Abs(a_vDeltaRotation.y) < a_fYThreshold ? 0.0f : a_vDeltaRotation.y + a_fYThreshold;
        a_vDeltaRotation.z = Mathf.Abs(a_vDeltaRotation.z) < a_fZThreshold ? 0.0f : 0.0f;//We just ignore the z rotation
    }

    public Vector3 Reset()
    {
        return m_v3Init;
    }

    public Vector3 Get(Vector3 a_v3Init)
    {
        if (!m_bInit)
        {
            m_bInit = true;
            m_v3Init = a_v3Init;
        }

        Vector3 v = Input.gyro.rotationRateUnbiased;
        if (m_correction == Correction.NONE)
            return a_v3Init + v;


        CorrectValueByThreshold(ref v);

        return a_v3Init - v;
    }

}

... And then use something like this in the "UpdateHead" method from "GvrHead":

GvrViewer.Instance.UpdateState();

if (trackRotation)
{
    var rot = Input.gyro.attitude;//GvrViewer.Instance.HeadPose.Orientation;

    if(Input.GetMouseButtonDown(0))
    {
        transform.eulerAngles = m_gyroCorrector.Reset();
    }
    else
    {
        transform.eulerAngles = m_gyroCorrector.Get(transform.eulerAngles);//where m_gyroCorrector is an instance of the previous class
    }

}

You may find some problems. Mainly but not exclusive:

  • There will be a latence problem when moving the head as there is an offset to detect the movement

  • You are dealing with relative positions that come with imprecisions. So you are not 100% sure to find the same position when doing the opposite movement.

  • You are using euler representation instead of quaternion, and it seems to be less accurate.

You may also be interested in these links speaking about the field:

http://scholarworks.uvm.edu/cgi/viewcontent.cgi?article=1449&context=graddis

Gyroscope drift on mobile phones

and this piece of code : https://github.com/asus4/UnityIMU

Hope it can help,