[ACCEPTED]-Is there an algorithm for converting quaternion rotations to Euler angle rotations?-euler-angles
This looks like a classic case of old technology 17 being overlooked - I managed to dig out 16 a copy of Graphics Gems IV from the garage and it looks 15 like Ken Shoemake has not only an algorithm 14 for converting from Euler angles of arbitrary rotation 13 order, but also answers most of my other 12 questions on the subject. Hooray for books. If 11 only I could vote up Mr. Shoemake's answer 10 and reward him with reputation points.
I 9 guess a recommendation that anybody working 8 with Euler angles should get a copy of Graphics 7 Gems IV from their local library and read 6 the section starting page 222 will have 5 to do. It has to be the clearest and most 4 concise explanation of the problem I have 3 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.
To old link provided seems to be 2 broken here is another copy of "Computing 1 Euler angles from a rotation matrix ".
In a right-handed Cartesian coordinate system 1 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));
}
}
I've been looking for several days for a 5 similar solution, and I finally ran across 4 this website that has an algorithm for converting 3 quaternions to arbitrary Euler and Tait-Bryan 2 rotations!
Here's the link: http://bediyap.com/programming/convert-quaternion-to-euler-rotations/
And here's the 1 code:
///////////////////////////////
// Quaternion to Euler
///////////////////////////////
enum RotSeq{zyx, zyz, zxy, zxz, yxz, yxy, yzx, yzy, xyz, xyx, xzy,xzx};
void twoaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
res[0] = atan2( r11, r12 );
res[1] = acos ( r21 );
res[2] = atan2( r31, r32 );
}
void threeaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
res[0] = atan2( r31, r32 );
res[1] = asin ( r21 );
res[2] = atan2( r11, r12 );
}
void quaternion2Euler(const Quaternion& q, double res[], RotSeq rotSeq)
{
switch(rotSeq){
case zyx:
threeaxisrot( 2*(q.x*q.y + q.w*q.z),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
-2*(q.x*q.z - q.w*q.y),
2*(q.y*q.z + q.w*q.x),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
res);
break;
case zyz:
twoaxisrot( 2*(q.y*q.z - q.w*q.x),
2*(q.x*q.z + q.w*q.y),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
2*(q.y*q.z + q.w*q.x),
-2*(q.x*q.z - q.w*q.y),
res);
break;
case zxy:
threeaxisrot( -2*(q.x*q.y - q.w*q.z),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
2*(q.y*q.z + q.w*q.x),
-2*(q.x*q.z - q.w*q.y),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
res);
break;
case zxz:
twoaxisrot( 2*(q.x*q.z + q.w*q.y),
-2*(q.y*q.z - q.w*q.x),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
2*(q.x*q.z - q.w*q.y),
2*(q.y*q.z + q.w*q.x),
res);
break;
case yxz:
threeaxisrot( 2*(q.x*q.z + q.w*q.y),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
-2*(q.y*q.z - q.w*q.x),
2*(q.x*q.y + q.w*q.z),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
res);
break;
case yxy:
twoaxisrot( 2*(q.x*q.y - q.w*q.z),
2*(q.y*q.z + q.w*q.x),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
2*(q.x*q.y + q.w*q.z),
-2*(q.y*q.z - q.w*q.x),
res);
break;
case yzx:
threeaxisrot( -2*(q.x*q.z - q.w*q.y),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
2*(q.x*q.y + q.w*q.z),
-2*(q.y*q.z - q.w*q.x),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
res);
break;
case yzy:
twoaxisrot( 2*(q.y*q.z + q.w*q.x),
-2*(q.x*q.y - q.w*q.z),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
2*(q.y*q.z - q.w*q.x),
2*(q.x*q.y + q.w*q.z),
res);
break;
case xyz:
threeaxisrot( -2*(q.y*q.z - q.w*q.x),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
2*(q.x*q.z + q.w*q.y),
-2*(q.x*q.y - q.w*q.z),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
res);
break;
case xyx:
twoaxisrot( 2*(q.x*q.y + q.w*q.z),
-2*(q.x*q.z - q.w*q.y),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
2*(q.x*q.y - q.w*q.z),
2*(q.x*q.z + q.w*q.y),
res);
break;
case xzy:
threeaxisrot( 2*(q.y*q.z + q.w*q.x),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
-2*(q.x*q.y - q.w*q.z),
2*(q.x*q.z + q.w*q.y),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
res);
break;
case xzx:
twoaxisrot( 2*(q.x*q.z - q.w*q.y),
2*(q.x*q.y + q.w*q.z),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
2*(q.x*q.z + q.w*q.y),
-2*(q.x*q.y - q.w*q.z),
res);
break;
default:
std::cout << "Unknown rotation sequence" << std::endl;
break;
}
}
Here is a paper I wrote on converting a 4 quaternion to Euler angles.
I have also put 3 a number of documents at this location discussing 2 various aspects of quaternions, Euler angles 1 and rotation matrices (DCM).
I have posted my paper titled "Quaternion 10 to Euler Angle Conversion for Arbitrary 9 Rotation Sequence Using Geometric Methods" on 8 my website at noelhughes.net. I also have 7 algorithms for converting any set of Euler 6 angles to a quaternion and quaternion to/from 5 direction cosine matrix which I will post 4 this weekend. These are also on Martin 3 Bakers website, though a little difficult 2 to find. Google my name, Noel Hughes, and 1 quaternions and you should find it.
I solve it this way:
step 1: Make sure which convention 10 for Euler rotation you want, say, zyx.
step 2: Compute 9 the analytical rotation matrix for the rotation. For 8 example, if you want R(zyx),
**R***zyx* = **R***x*( phi ) * **R***y*( theta ) * **R***z*( psi ), where 7 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 6 can find the sin or tan for the three angles 5 using the elements above. In this example,
tan(phi) = -R23/R33
sin(theta) = -R13
tan(psi) = -R12/R11
step 4: Compute 4 the rotation matrix from your quaternion 3 (see wikipedia), for the elements you need to compute 2 the angles as in 3) above.
Other conventions 1 can be computed using the same procedure.
For those that stumble upon this page while 5 Googling, I recently found derivations for 4 these conversions for all 12 intrinsic Tait-Bryan 3 (1-2-3, 3-2-1, etc.) and Proper Euler (1-2-1, 3-1-3, etc.) rotation 2 sequences in the following two references:
- NASA Paper, July 1977: Euler > DCM, Euler > Quaternion, DCM > Euler
- Birdy's Notebook, Oct 2013: Quaternion > Euler
Thanks 1 to frodo2975 for the second link.
Wikipedia shows how you can use the parts of the 1 quaternion and calculate the euler angles.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.