In my app, I need to be aware of the device rotation. I am trying to pull the y-axis value from the gyroscope using the following:
var y = Input.gyro.attitude.eulerAngles.y;
If I simply output that to the screen and turn in a circle (holding my phone straight up and down...as if you were looking at the screen), I get the following:
270, 270, 270, 270, etc...270, 290, 310, 20, 40, 60, 80 (very quickly)...90, 90, 90, 90, etc...blah...
Is there any way to account for this jump in numbers?
What you're seeing is something called the gimbal lock more info here. It happens with Euler angles cross the 360 plane or more specifically (two of the three axis's are driven into a parallel configuration), and that is why people use Quaternions.
You shouldn't be pulling the euler angles directly. I would recommend something like this:
Quaternion q = Input.gyro.attitude.rotation;
By using the Quaternion rather than the euler angles we will avoid the gimbal lock and therefore avoid the 360, 0 issue.
If you simply want to show the angle they are facing in the y direction I might recommend something like this, this wraps the y angle to 0 to 180 degrees:
/// <summary>
/// This method normalizes the y euler angle between 0 and 180. When the y euler
/// angle crosses the 180 degree threshold if then starts to count back down to zero
/// </summary>
/// <param name="q">Some Quaternion</param>
/// <returns>normalized Y euler angle</returns>
private float normalizedYAngle(Quaternion q)
{
Vector3 eulers = q.eulerAngles;
float yAngle = eulers.y;
if(yAngle >= 180f)
{
//ex: 182 = 182 - 360 = -178
yAngle -= 360;
}
return Mathf.Abs(yAngle);
}
You could set a maximum rotation to prevent fast jumps.
y_diff = new_y - last_y;
y = y + Mathf.Clamp(y_diff, -limit, limit);
You could use linear interpolation to achieve this effect. The only thing you need to consider is how fast you will do it, since the phone will be constantly rotating and you don't want your values to be lagging.
An example using Mathf.Lerp
:
// Your values
var y = 0;
// speed for the Lerp
static float t = 1.0f;
void Update()
{
float old = y
float new = Input.gyro.attitude.eulerAngles.y;
// Interpolate
y = Mathf.Lerp(old, new, t * Time.deltaTime);
}
Referenced from here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With