Sign in to follow this  
CodeReaver

Removing the roll from a quaternion:

Recommended Posts

I needed a way of lining my camera back up with the Y axis (ie stripping out the roll) when changing between two different modes and the only way I could find was to convert the quat to a yaw, pitch and roll and back to a quat with just the pitch and yaw. I found these two formulas:
//tan(yaw)   =  2*(q0*q3 - q1*q2) / (q0*q0 + q1*q1 - q2*q2 - q3*q3) 
//sin(pitch) =  2*(q0*q2 + q1*q3) 
//tan(roll)  =  2*(q0*q1 - q2*q3) / (q0*q0 - q1*q1 - q2*q2 + q3*q3)

//dx = 2.0 * (x * z - w * y);
//dy = 2.0 * (y * z + w * x);
//dz = 1.0 - 2.0 * (x * x + y * y);
There wasn't an explanation of what dx, dy and dz were in that second one. They said it was equivilant to the first in the discussion and that it worked when they tried it. However they don't seem to work properly. Calling this function just seems to alternate between two or three different positions. Am I doing this right?
    public void RemoveRoll()
    {
        float fQ0 = m_xRotation.X;
        float fQ1 = m_xRotation.Y;
        float fQ2 = m_xRotation.Z;
        float fQ3 = m_xRotation.W;

        float fYaw      = (float)Math.Atan((double)(2.0f*(fQ0*fQ3-fQ1*fQ2)/(fQ0*fQ0+fQ1*fQ1-fQ2*fQ2-fQ3*fQ3)));
        float fPitch    = (float)Math.Asin((double)(2.0f*(fQ0*fQ2+fQ1*fQ3)));
        float fRoll     = (float)Math.Atan((double)(2.0f*(fQ0*fQ1-fQ2*fQ3)/(fQ0*fQ0-fQ1*fQ1-fQ2*fQ2+fQ3*fQ3)));

        m_xRotation     = Quaternion.RotationYawPitchRoll(fYaw, fPitch, 0.0f);
        m_xRotation.Normalize();
    }

I tried making fQ0 = W, fQ1 = X, fQ2 = Y and fQ3 = Z in case that was what was wrong, but I still get the same problem.

Share this post


Link to post
Share on other sites
I built a quat with arbitrary yaw, pitch, roll values. Then I used your method to calculate the yaw, pitch, roll from the quat. They don't come back to the original values. That means the method is wrong. I don't think converting a quat to yaw, pitch, roll angles is a easy and simple thing. If you do want to do that, it is better to convert the quat to a matrix then extract the angles from the matrix.
By the way, if you want to align your camera Y axis to the world's Y axis(I just guess that, because you didn't said the y axis is the one in world space),
I would sugguest you to build a new matrix. the new matrix z axis remain the same as the camera's z axis, by crosing world's y axis with camera's z axis, you get the x axis, then get the y axis by crossing the camera's z axis with the new x axis. I hope that would be the new camera matrix you want.

Share this post


Link to post
Share on other sites
Use the quat to rotate the (1,0,0) vector, use that vector along with the up-vector to produce a new rotation matrix, then convert that matrix to a new quat.

Share this post


Link to post
Share on other sites
Won't I get gimbol lock if I use matrices? Currently I'm calculating all my rotations using quats and only converting to a matrix in my update function right before I render.

Share this post


Link to post
Share on other sites
Gimbal lock is issue related to Euler angles, not to Matrices nor quaternions. In other words - its more of a problem with construction of rotation rather than representation.

Share this post


Link to post
Share on other sites
So, are quaternions just compressed matrices? If so, I might be better off scrapping the rotation quats and just sticking with a matrix.

Also, if any use of eulers to compute a quat or a matrix will cause gimbal lock, does that mean using the RotationYawPitchRoll and RotationAxis methods will cause it as well? How would I get around that? Any angle I try to use to rotate my original matrix or quaternion would be a euler.

Share this post


Link to post
Share on other sites
Although quaternion is another form of matirx, but since you want the aligning in y axix and there is no y axis information can be accessed directly in a quaternion, it may be better to do it in matrix way.

Share this post


Link to post
Share on other sites
And what about those rotation functions (RotationYawPitchRoll and RotationAxis) I mentioned? Can those cause gimbol lock due to them accepting eulers as their arguments? I'm not sure if I mentioned, but even though I want the ability to remove the roll, I still want to be able to change it sometimes.

Share this post


Link to post
Share on other sites
If you try to extract the yaw/pitch/roll angle values from a matrix, a gimbal lock can happen. For example, get two books, place them so they have the same orientation. Get the first book, rotate it clockwise 90 degrees around an axis pointing upward (yaw). Now rotate the book clockwise by 90 degrees around an axis pointing forward(pitch). Now rotate the book counterclockwise 90 degrees around an axis pointing upward (roll). Now the book's matrix's yaw = 90, pitch = 90, roll = -90. But if you just rotate the second book clockwise by 90 degrees around an axis point rightward (pitch), the second book's orientation is the same as the first book, this time the result matrix's yaw = 0, pitch = 90, roll = 0. As you can see, when you try to get the yaw/pitch/roll angle values from the result matrix, you have two sets of answers, which one would you choose? In the case you posted here, you can choose to remove the roll of -90 degrees or the roll of 0 degrees and the results are obviously different.

Share this post


Link to post
Share on other sites
So, then neither RotationYawPitchRoll or RotationAxis can be used without causing gimbal lock? Or are you saying it's ok to construct a quaternion or a matrix using eulers, but you can't get the info back out? I'm using MDX and I think Quaternion and Matrix have both of those functions.

Share this post


Link to post
Share on other sites
I use MDX too. When you extract the RotationYawPitchRoll values from a matrix(or a quaternion) by using the methods in MDX, the values you get may not be the same as the ones you used to build the matrix, it is only one of the possible sets which you can use to built the same matrix.

I couldn't find any method in my MDX version which can get back the YawPitchRoll values. Does it realy exist in other versions?

[Edited by - Einstone on November 23, 2007 2:52:49 AM]

Share this post


Link to post
Share on other sites
That function isn't used to extract the yaw/pitch/roll, it's use to create the quat/matrix. I'm just asking if using euler values in creating/rotating the quat/matrix is safe as long as I don't try to use extracted eulers to compute the new rotation.

Share this post


Link to post
Share on other sites
Yes, it is absolutely safe from theory point of view.
Be carfull if use the Quaternion.ToAxisAngle(Quaternion quat, ref Vector3 axis, ref float angle) method provided in MDX, the return values may be NaN (Not a Number). It occoured in one of my applications and took me ages to track it down.

[Edited by - Einstone on November 23, 2007 9:19:11 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this