Solving gimbal lock

Started by
13 comments, last by altra4u 14 years, 9 months ago
Hey guys, So I need to do the solve the following and I am confused if someone can please help me. Issue:Solve gimbal lock for a Left hand coordinate system with first y, then x and then z order of rotation.So I want the rotations to be always around the global axis.i.e not the local axis of the object. Steps taken: -form a quaternion with with rotation order multiplied Q = Qz.Qx.Qy.This order of rotation as the reference axis is the global world axis.I have pictures of the math I did too but don't find a place to attach them. -multiply the new quaternion(based on key input) with the current quat.So we have newQuat = newQuat*Q -convert the final quat to euler angles. This quat to euler conversion gives me rotation in the local axes.I wonder why is the case as I am pre-multiplying both the quats and the rotation matrices(at the time of quat to euler conversion) as I am using the world axis as the absolute reference. -Since quattoeuler LH z.x.y did not work.I tried doing quattoeulerLHy.x.z which did not work too.Attaching math file quattoeulerLHy.x.z.This did not work too Can someone point out what I am doing wrong? Questions: -Although I don't see how but would the handedness of a system affect the quaternion derivation? The only thing I could think of now is creating the quaternion in Qy.Qx.Qz(although I feel this is wrong) and trying the z.x.y and y.x.z order of quat to euler. LH:left hand z.x.y:order in which multiplied Thanks, chit
Advertisement
I suggest you to do this:

keep a quaternion for every object you want to avoid gimbal lock

for each step:
multiply that quaternion by a quaternion representing the rotation change (usually a quaternion built with very small angle degrees)
renormalize the quaternion
convert the quaternion to euler angles or a matrix for rendering.

Notice the quaternion is kept all the time, you only multiply it by other quaternions and renormalize it, but you don't rebuild it fron scratch every frame.


I didn't quite follow all that, but maybe it's a multiplication order problem - did you try 'newQuat = Q*newQuat' instead of 'newQuat = newQuat*Q'?

Coordinate system handedness should not matter for what you're doing. Beyond that I can't give much in the way of advice, as I'm not quite clear on what sort of motion you're trying to achieve. If the multiplication order suggestion doesn't help, maybe you could provide some more details (such as what the object represents, how the user interface works, and exactly what sort of motion you want the object to undergo).
I am doing what you are saying.I am not creating the quat from scratch every time.Its saved.Only the quat based on key input is created new every time.I am converting the final quat to euler angles to give the angles to my engine which only accepts euler angles for rotation.This is the part that I feel is going wrong.
Also posting the code

Euler to Quat(Can I post pics here?I have the full math derivation)
thetaxHalf as Float = x/2.0
thetayHalf as Float = y/2.0
thetazHalf as Float = z/2.0
cx as Float = Cosine(thetaxHalf)
cy as Float = Cosine(thetayHalf)
cz as Float = Cosine(thetazHalf)
sx as Float = Sine(thetaxHalf)
sy as Float = Sine(thetayHalf)
sz as Float = Sine(thetazHalf)

me.kz_w = cz*cx*cy - sz*sx*sy
me.kz_x = cz*sx*cy - sz*cx*sy
me.kz_y = cz*cx*sy + sz*sx*cy
me.kz_z = cz*sx*sy + sz*cx*cy
me.NormalizeQuat()

Quat to Euler(yaw-y axis,pitch-x axis,roll-z axis)
//Order:Rz.Rx.Ry.Matrices for left hand coordinate system.Rotates in the local axes.

pitch as Float = ArcSine(2.0*(me.kz_y*me.kz_z + me.kz_w*me.kz_x))
yaw as Float = ArcCosine( (1.0 - 2.0*Power(me.kz_x,2) - 2.0*Power(me.kz_y,2))/Cosine(pitch) )
roll as Float = ArcCosine( (1.0 - 2.0*Power(me.kz_x,2) - 2.0*Power(me.kz_z,2))/Cosine(pitch) )

//Order:Ry.Rx.Rz.Matrices for left hand coordinate sytem.weird result
pitch as Float = ArcSine(-2.0*me.kz_y*me.kz_z + 2.0*me.kz_w*me.kz_x)
yaw as Float = ArcSine( 2.0*me.kz_x*me.kz_z + 2.0*me.kz_w*me.kz_y/Cosine(pitch) )
roll as Float = ArcSine( 2.0*me.kz_x*me.kz_y + 2.0*me.kz_w*me.kz_z/Cosine(pitch) )
Quote:Original post by jyk
I didn't quite follow all that, but maybe it's a multiplication order problem - did you try 'newQuat = Q*newQuat' instead of 'newQuat = newQuat*Q'?

Coordinate system handedness should not matter for what you're doing. Beyond that I can't give much in the way of advice, as I'm not quite clear on what sort of motion you're trying to achieve. If the multiplication order suggestion doesn't help, maybe you could provide some more details (such as what the object represents, how the user interface works, and exactly what sort of motion you want the object to undergo).


Well in very simple terms assume I have a cube and when I use the up,down,left,right keys it should move around the global x and y axis irrespective of the orientation of its local axis.
Here is what I am doing with the quats.
quat = retrieve the saved value which tells of the current rotation.
keyQuat = create quat based on key input
quat = quat*keyQuat.
I believe this is the right way as I downloaded a gimbal lock code sample from gamedev itself which does it like this.

Thanks,
chit

Question: if it's your engine, why not just revise the interface so that it accepts orientations in quaternion or matrix form? Then you could bypass the Euler-angle conversion(s) entirely.
Quote:Original post by jyk
Question: if it's your engine, why not just revise the interface so that it accepts orientations in quaternion or matrix form? Then you could bypass the Euler-angle conversion(s) entirely.


Its not my engine as in I made it.Its just an engine I have to use and it accepts only euler angles :(.
Some general questions that have been bugging me.
-if I am doing my rotations with respect to the global axis then I need to pre-multipy right.
So if I was doing y first then x then z then I need to do
Q = Qz.Qx.Qy

-I also get confused about quaternion multiplication.
So if I had a rotation q1 and if I wanted to apply another rotation q2 then should
the final quat be q2*q1 or should it be q1*q2?But then this would mean that my first question would have only one
valid solution irrespective of what axis(global or local)we choose.

-When I am converting the quat to euler
I need to compare the quaternion matrix form to the composite rotation matrix form.
So the question is should this composite rotation matrix be derived as
R = Rz.Rx.Ry or should it be R = Ry.Rx.Rz as we want the angles with respect to the local axis?
Thanks,
chit
Quote:Original post by altra4u
Issue:Solve gimbal lock for a Left hand coordinate system with first y, then x and then z order of rotation.So I want the rotations to be always around the global axis.i.e not the local axis of the object.


What you're describing is not possible without changing the logic of how you do rotations. Gimbal lock is a problem about logic of combining several rotations, and not about the way you represent those rotations. So, your question is effectively "How can I use Euler's method for expressing and combining rotations that suffers from gimbal locking so that it doesn't exhibit gimbal locking?"

You ask to use the method v'=R*v, where R=Rz(a)*Rx(b)*Ry(c) and Rx, Ry and Rz rotate around the three world coordinate axes. Unfortunately you cannot escape gimbal locking if you just use three fixed world axes, no matter whether Rx, Ry and Rz are rotation matrices or quaternions. You can see this for example by setting b=pi/2 and computing R. It always happens (no matter whether you use Euler xyz, zyz, xyx, etc.) that in the resulting transformation matrix R, the scalars a and c adjust the rotation about the same axis, i.e. you have lost that one degree of freedom (see Euler Rotations Explained, or Wikipedia derivation of the R matrix during gimbal lock).

One solution that allows you to combine three successive rotations is to use the local object axes. I.e. do R=Ry(yaw)*Rp(pitch)*Rr(roll). This requires that you change the axis around which Ry and Rp rotate according to pitch and roll (i.e. the axis around which Ry rotates depends on pitch and roll, and the axis around which Rp rotates depends on roll). This maps nicely for example to keyboard/mouse input from player: mouse horizontal alters yaw, mouse vertical alters pitch and so on. Note that here the problem was solved by changing the logic of how you combine rotations, not by changing the representation of these rotations.

I know you mentioned you did not want to use local axes, but that's really the only way I know of that allows you to do this kind of simplistic R=R1*R2*R3 scheme.

Hope that was helpful,
Quote:Original post by clb
Quote:Original post by altra4u
Issue:Solve gimbal lock for a Left hand coordinate system with first y, then x and then z order of rotation.So I want the rotations to be always around the global axis.i.e not the local axis of the object.


What you're describing is not possible without changing the logic of how you do rotations. Gimbal lock is a problem about logic of combining several rotations, and not about the way you represent those rotations. So, your question is effectively "How can I use Euler's method for expressing and combining rotations that suffers from gimbal locking so that it doesn't exhibit gimbal locking?"

You ask to use the method v'=R*v, where R=Rz(a)*Rx(b)*Ry(c) and Rx, Ry and Rz rotate around the three world coordinate axes. Unfortunately you cannot escape gimbal locking if you just use three fixed world axes, no matter whether Rx, Ry and Rz are rotation matrices or quaternions. You can see this for example by setting b=pi/2 and computing R. It always happens (no matter whether you use Euler xyz, zyz, xyx, etc.) that in the resulting transformation matrix R, the scalars a and c adjust the rotation about the same axis, i.e. you have lost that one degree of freedom (see Euler Rotations Explained, or Wikipedia derivation of the R matrix during gimbal lock).

One solution that allows you to combine three successive rotations is to use the local object axes. I.e. do R=Ry(yaw)*Rp(pitch)*Rr(roll). This requires that you change the axis around which Ry and Rp rotate according to pitch and roll (i.e. the axis around which Ry rotates depends on pitch and roll, and the axis around which Rp rotates depends on roll). This maps nicely for example to keyboard/mouse input from player: mouse horizontal alters yaw, mouse vertical alters pitch and so on. Note that here the problem was solved by changing the logic of how you combine rotations, not by changing the representation of these rotations.

I know you mentioned you did not want to use local axes, but that's really the only way I know of that allows you to do this kind of simplistic R=R1*R2*R3 scheme.

Hope that was helpful,



I agree to that Gimbal lock is a problem about logic of combining several rotations, and not about the way you represent those rotations.
I believed that multiplication of two quaternions would solve the gimbal lock problem as they lie on sphere.At least that is what the explanation goes on this tutorial http://www.gamedev.net/reference/articles/article1095.asp

My whole math involves using quaternions so rotation matrices are not involved except at the very end where I try to extract euler angles from the quaternion to give to the Rotate function of my engine.
So the steps would be

-retrieve the quaternion representing the rotation
-create a new quaternion based on the key input
-multiply them(This should solve the gimbal lock cause of quat multiplication)
-fetch euler angles from this quat.

If we are talking about different things I would like to know more about this local axis approach of yours.I don't mind using local axis as long as it solves my problem.

This topic is closed to new replies.

Advertisement