- Home /
Quaternion.ToAngleAxis is Unprecise?
In the code below, I create a quaternion with a rotation of 0.02 degrees and print the quaternion's angle to the 5th decimal place.
Quaternion q = Quaternion.Euler(0.02f, 0f, 0f);
q.ToAngleAxis( out float qAngle, out Vector3 qAxis);
print(qAngle.ToString("F5"));
But according to Unity, the angle of the quaternion is:
0.00000
What's causing this lack of precision? I'm so lost :(
Answer by Bunny83 · Aug 21, 2021 at 07:32 AM
Because the angle is below the precision of 32 floating point numbers. The issue here is the way how rotations are represented as a quaternion. The quaternion that is created has the 4 values:
float halfRadians = angleInDegree * Mathf.Deg2Rad / 2;
x = 1 * Mathf.Sin(halfRadians);
y = 0 * Mathf.Sin(halfRadians);
z = 0 * Mathf.Sin(halfRadians);
w = Mathf.Cos(halfRadians);
As you may know a quaternion is always represented as a "vector" (x,y,z) and the cosine of half the angle around that vector. The issue here is that 0.02 degree yields a cosine value of 0.99999998476912...
. However this is beyond the precision that a float can represent, so the value is rounded to 1. Though 1 represents an angle of 0°. The vector part itself is scaled down by sine of half the angle and results in 0.0001745329 which can be represented with a float. That means the quaternion may still work within some error margin, but the "normal" way of retrieving the the axis / angle just doesn't work. Usually you would use "Acos" on the w value to retrieve half the angle which we would double. Though since that would yield a value of 0 that doesn't really help.
You can still recover the angle to a higher precision by manually recovering the angle from the vector part instead of the scaler part. However you have to handle the sign manually. Something like this should work:
Vector3 axis = new Vector3(q.x, q.y, q.z);
float len = axis.magnitude;
float angle = Mathf.Asin(len) * Mathf.Rad2Deg * 2f * Mathf.Sign(q.w);
axis *= 1f / len;
Note that this solution will have similar issues when the half the angle gets closer to 90° (so angle is close to 180°).
So you may want to use this solution only if the absolute value of "w" is very close to "1".
Your answer
Follow this Question
Related Questions
Convert Quaternion to Eulerangles 2 Answers
Weird rotation precision 2 Answers
How can I rotate at a constant speed to look at a point? 2 Answers
how to combine 2 quaternion components? 2 Answers
Change the roll of the rotation 0 Answers