views:

2052

answers:

7

Is there an existing algorithm for converting a quaternion representation of a rotation to an Euler angle representation? The rotation order for the Euler representation is known and can be any of the six permutations (i.e. xyz, xzy, yxz, yzx, zxy, zyx). I've seen algorithms for a fixed rotation order (usually the NASA heading, bank, roll convention) but not for arbitrary rotation order.

Furthermore, because there are multiple Euler angle representations of a single orientation, this result is going to be ambiguous. This is acceptable (because the orientation is still valid, it just may not be the one the user is expecting to see), however it would be even better if there was an algorithm which took rotation limits (i.e. the number of degrees of freedom and the limits on each degree of freedom) into account and yielded the 'most sensible' Euler representation given those constraints.

I have a feeling this problem (or something similar) may exist in the IK or rigid body dynamics domains.


Solved: I just realised that it might not be clear that I solved this problem by following Ken Shoemake's algorithms from Graphics Gems. I did answer my own question at the time, but it occurs to me it may not be clear that I did so. See the answer, below, for more detail.


Just to clarify - I know how to convert from a quaternion to the so-called 'Tait-Bryan' representation - what I was calling the 'NASA' convention. This is a rotation order (assuming the convention that the 'Z' axis is up) of zxy. I need an algorithm for all rotation orders.

Possibly the solution, then, is to take the zxy order conversion and derive from it five other conversions for the other rotation orders. I guess I was hoping there was a more 'overarching' solution. In any case, I am surprised that I haven't been able to find existing solutions out there.

In addition, and this perhaps should be a separate question altogether, any conversion (assuming a known rotation order, of course) is going to select one Euler representation, but there are in fact many. For example, given a rotation order of yxz, the two representations (0,0,180) and (180,180,0) are equivalent (and would yield the same quaternion). Is there a way to constrain the solution using limits on the degrees of freedom? Like you do in IK and rigid body dynamics? i.e. in the example above if there were only one degree of freedom about the Z axis then the second representation can be disregarded.


I have tracked down one paper which could be an algorithm in this pdf but I must confess I find the logic and math a little hard to follow. Surely there are other solutions out there? Is arbitrary rotation order really so rare? Surely every major 3D package that allows skeletal animation together with quaternion interpolation (i.e. Maya, Max, Blender, etc) must have solved exactly this problem?

A: 

There is a code snippet that might be of use here:

http://forums.xna.com/forums/p/4574/23988.aspx#23988

Brandon E Taylor
Yep, looks like [Tait-Bryan](http://en.wikipedia.org/wiki/Tait-Bryan_angles) angles again. It is looking like the only solution is to derive conversions for the other five rotation orders from this algorithm.
Will Baker
+2  A: 

Wikipedia shows how you can use the parts of the quaternion and calculate the euler angles.

Magnus Skog
It does for so-called Tait-Bryan angles [http://en.wikipedia.org/wiki/Tait-Bryan_angles] but there isn't really any mention of the fact that Euler angles can have other rotation orders.
Will Baker
Merely posting a link isn't a significant contribution
bobobobo
+3  A: 

In a right-handed Cartesian coordinate system with Z axis pointing up, do this:

struct Quaternion
{
    double w, x, y, z;
};

void GetEulerAngles(Quaternion q, double& yaw, double& pitch, double& roll)
{
    const double w2 = q.w*q.w;
    const double x2 = q.x*q.x;
    const double y2 = q.y*q.y;
    const double z2 = q.z*q.z;
    const double unitLength = w2 + x2 + y2 + z2;    // Normalised == 1, otherwise correction divisor.
    const double abcd = q.w*q.x + q.y*q.z;
    const double eps = 1e-7;    // TODO: pick from your math lib instead of hardcoding.
    const double pi = 3.14159265358979323846;   // TODO: pick from your math lib instead of hardcoding.
    if (abcd > (0.5-eps)*unitLength)
    {
        yaw = 2 * atan2(q.y, q.w);
        pitch = pi;
        roll = 0;
    }
    else if (abcd < (-0.5+eps)*unitLength)
    {
        yaw = -2 * ::atan2(q.y, q.w);
        pitch = -pi;
        roll = 0;
    }
    else
    {
        const double adbc = q.w*q.z - q.x*q.y;
        const double acbd = q.w*q.y - q.x*q.z;
        yaw = ::atan2(2*adbc, 1 - 2*(z2+x2));
        pitch = ::asin(2*abcd/unitLength);
        roll = ::atan2(2*acbd, 1 - 2*(y2+x2));
    }
}
Jonas Byström
Yep, this uses the NASA convention - yaw, pitch and roll (or heading, pitch and roll if you like). This would be (assuming your right-handed cartesian with Z up) a rotation order of zxy. I'm after an algorithm which handles xyz, xzy, yxz, yzx, zxy and zyx. Perhaps the only option is to provide essentially six different conversions, derived from the one you have given?And would there be a way to extend this approach so that joint limits and degrees of freedom can be used to get a non-ambiguous Euler representation?
Will Baker
Using my interpretation of "non-ambigous" the short answer is "no". :)
Jonas Byström
What about if you take joint limits into account? For example, if you end up with two possible Euler representations one of them may be able to be eliminated because it is outside the range of motion of a particular joint. Wouldn't you have to solve this problem when generating skeletal animation from motion capture data?
Will Baker
You are assuming that you compare the result - "two possible Euler representations" - with something similar. Possibly another Euler representation? The only resolution is using a non-ambigous system.
Jonas Byström
+2  A: 

This looks like a classic case of old technology being overlooked - I managed to dig out a copy of Graphics Gems IV from the garage and it looks like Ken Shoemake has not only an algorithm for converting from Euler angles of arbitrary rotation order, but also answers most of my other questions on the subject. Hooray for books. If only I could vote up Mr. Shoemake's answer and reward him with reputation points.

I guess a recommendation that anybody working with Euler angles should get a copy of Graphics Gems IV from their local library and read the section starting page 222 will have to do. It has to be the clearest and most concise explanation of the problem I have read yet.


Here's a useful link I have found since - http://www.cgafaq.info/wiki/Euler_angles_from_matrix - This follows the same system as Shoemake; the 24 different permutations of rotation order are encoded as four separate parameters - inner axis, parity, repetition and frame - which then allows you to reduce the algorithm from 24 cases to 2. Could be a useful wiki in general - I hadn't come across it before.

Will Baker
+2  A: 

I have posted my paper titled "Quaternion to Euler Angle Conversion for Arbitrary Rotation Sequence Using Geometric Methods" on my website at noelhughes.net. I also have algorithms for converting any set of Euler angles to a quaternion and quaternion to/from direction cosine matrix which I will post this weekend. These are also on Martin Bakers website, though a little difficult to find. Google my name, Noel Hughes, and quaternions and you should find it.

noel hughes
A: 

I solve it this way:

step 1: Make sure which convention for Euler rotation you want, say, zyx.

step 2: Compute the analytical rotation matrix for the rotation. For example, if you want R(zyx),

Rzyx = Rx( phi ) * Ry( theta ) * Rz( psi ), where the elements become

R11 =  cos(theta)*cos(psi)
R12 = -cos(theta)*sin(psi)
R13 =  sin(theta)
R21 =  sin(psi)*cos(phi) + sin(theta)*cos(psi)*sin(phi)
R22 =  cos(psi)*cos(phi) - sin(theta)*sin(psi)*sin(phi)
R23 = -cos(theta)*sin(phi)
R31 =  sin(psi)*sin(phi) - sin(theta)*cos(psi)*cos(phi)
R32 =  cos(psi)sin(phi) + sin(theta)*sin(psi)*cos(phi)
R33 =  cos(theta)*cos(phi) 

step 3: By inspection, you can find the sin or tan for the three angles using the elements above. In this example,

tan(phi) = -R23/R33

sin(theta) = -R13

tan(psi) = -R12/R11

step 4: Compute the rotation matrix from your quaternion (see wikipedia), for the elements you need to compute the angles as in 3) above.

Other conventions can be computed using the same procedure.

Fredriku73
+1  A: 

Here is a paper I wrote on converting a quaternion to Euler angles. If you have any questions, contact me at [email protected] http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf

I have also put a number of documents at this location discussing various aspects of quaternions, Euler angles and rotation matrices (DCM). www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm

noel hughes