Jump to content
  • Advertisement
Sign in to follow this  
Dirk Gregorius

Quaternions, Axis - Angle and ArcCos

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by timw
I 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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Guest Anonymous Poster
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!