# Quaternions, Axis - Angle and ArcCos

This topic is 4879 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Given a unit quaternion q. This quaternion encodes a rotation around an axis by an angle alpha. The following holds: q.x = sin( alpha / 2 ) * axis.x q.y = sin( alpha / 2 ) * axis.y q.z = sin( alpha / 2 ) * axis.z q.w = cos( alpha / 2 ) In order to get the angle alpha I could simply do: alpha = 2.0f * arccosf( q.w ) This does work as long as -1.0f <= q.w <= 1.0. In my application q.w might become 1.000001 for example and my whole physic system gets srewed up. Also it is possible to clamp I wonder if there is a more stable alternative using trigeometric identities? I thought of the folollowing: Vector3 vec( q.x, q.y, q.z ); float sina_2 = vec.Length(); float cosa_2 = q.w; float tana_2 = sin_a2 / cos_a2; Now I could use atanf() or atan2f() - is any of these functions superior over arccosf() or arcsinf()? Any other recommendations? -Dirk

##### Share on other sites
Unless I'm overlooking something obvious, 2*atan2(length(v),w) should give you the same results as 2*acos(clamp(w,-1,1)), but with greater accuracy and stability.

##### Share on other sites
i dont think the w component will go above 1.0 if you use the D3DXQuaternionNormalize...
it hasnt messed up anything for me... yet

##### Share on other sites
Quote:
 i dont think the w component will go above 1.0 if you use the D3DXQuaternionNormalize...
I wouldn't count on that. Unless D3DXQuaternionNormalize() does something weird like clamp the results itself, I doubt there's any guarantee on the value of w.

In general it's best not to leave these sorts of things to chance. You should always clamp the argument to acos() or asin() unless (as is sometimes the case) you are absolutely certain of the range of the input.

##### Share on other sites
I have wrapper functions for all trigeometric functions. I think I will clamp the values there and output a warning in the DebugBuild if an argument goes over 1 + Eps or below -1 - Eps.

-Dirk

##### Share on other sites
I don't think this problem will cause you much headache, I mean we use unit quaternions, the last compoent has range -1,1 the closest you could get to one is cos when theta is 0 degrees, try calling the cos function with 0, 0+delta, 0 - delta I think in each case it'll be below one by nature of the algorithm, but I'm not sure tho, try it.

Tim

[Edited by - timw on September 12, 2005 5:30:03 PM]

##### Share on other sites
Quote:
 Original post by timwI don't think this problem will cause you much headache, ...

The problem is that an operation (such as multiplying by another quaternion) could cause the w term to go outside the range [-1,1]. If it does, it won't be by much, but even 1.000001 will cause acos() to blow up.

BTW, the same problem exists for getting the angle between two unit vectors by finding the arccosine of the dot product:
    angle = acos( dot( v0, v1 ) );  // <-- ouch
In a perfect world there would be no problems, but in these cases floating-point precision comes into play.

##### Share on other sites
I didn't know acos was that sensitive, I wrote some quaternion code a while back, but never needed to extract the angle.

##### Share on other sites
Quote:
 BTW, the same problem exists for getting the angle between two unit vectors by finding the arccosine of the dot product: angle = acos( dot( v0, v1 ) ); // <-- ouch

This is exactly where I get blown up. I am writing some kind of physic code and during the constraint satisfaction through relaxation when I try to impose an orientation constraint I get blown up during the iteration when q.w gets slightly over 1.0.

-Dirk

##### Share on other sites
jyk's solution looks like it should work.

For a physics constraint problem in particular it may be possible to improve the situation by turning around the problem. Instead of finding the angle by the arccosine of the dot product and then comparing it to a constraint angle, find the constraint on the dot product by taking the cosine of the constraint angle. This is more robust than acos and can make the calculations simpler.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 13
• 9
• 9
• 34
• 16
• ### Forum Statistics

• Total Topics
634123
• Total Posts
3015658
×