rotationconverter icon indicating copy to clipboard operation
rotationconverter copied to clipboard

A question regarding Euler angles from quaternion

Open neilyoung opened this issue 6 years ago • 3 comments

I'm having this quaternion (x,y,z,w):

-0.299166,-0.106895,-0.0551278,0.946591

My (C++ based) conversion gives a rotation matrix, which is pretty much identical to the R given in your page https://www.andre-gaschler.com/rotationconverter/ for the given quaternion:

R: 0.971, 0.168,-0.169,-0.040, 0.815, 0.578, 0.235,-0.555, 0.798

I'm having a doubt regarding the 'yaw' value. The coordinate system, which generates this quaternion, has the following axis convention: X is getting larger towards right, Y is getting larger towards the sky and Z is getting negative, if moving forward. Hence my code adapts to Euler Angles by sorting the values Euler like (NED, x forward/north, y right/east, z down):

float calculateRotation(const rs2_quaternion &quaternion)
{
    // http://www.chrobotics.com/library/understanding-euler-angles
    // The original axis naming is different from Euler. Align
    float w = quaternion.w;
    float x = -quaternion.z;
    float z = -quaternion.y;
    float y = quaternion.x;

    float pitch = -asin(2.0 * (x * z - w * y)) * 180.0 / M_PI;
    float roll = atan2(2.0 * (w * x + y * z), w * w - x * x - y * y + z * z) * 180.0 / M_PI;
    float yaw = atan2(2.0 * (w * z + x * y), w * w + x * x - y * y - z * z) * 180.0 / M_PI;

    return yaw;
}

The values returned for 'yaw' exactly reflect the rotation of my device around the y axis (Euler's z).

I'm now having a little doubt regarding the Euler Angle conversion of your page https://www.andre-gaschler.com/rotationconverter/: Whereas my calculation for the given quaternion gives 11.9819 degrees, which is ok for me, since I rotated right a bit, the only matching value is the Y value, if I choose "YXZ", but the sign is inverted, so -11.9818413 instead.

The same for these two examples:

Q: 0.27421,-0.359027,-0.139633,0.881142
R: 0.703, 0.049,-0.709,-0.443, 0.811,-0.383, 0.556, 0.583, 0.592
Yaw: 50.1589

Your value for yaw: Y=-50.1588726, if YXZ is selected.

Or:

Q: 0.961622,0.00379452,-0.274343,-0.00216471
R: 0.849, 0.006,-0.528, 0.008,-1.000, 0.002,-0.528,-0.006,-0.849
Yaw: 148.153

Your value for yaw: Y=-148.1534521, if YXZ is selected.

In all cases your and my conversion of Q to R or R to Q give identical results. Just the yaw sign is different...

Any idea, why this might be the case?

neilyoung avatar Nov 11 '19 19:11 neilyoung

Hmm. Your sign just makes sense to me, if all rotations are mathematical positive (counter clockwise). Can this be the reason? The I would just need an explanation, why I have to choose "YXZ" in order to find my yaw at y. If I follow the Euler wiki, then there is this equivalency:

y-x'-z'' (intrinsic) is z-x-y (extrinsic)

The last statement reflects my axis configuration... (z is Euler x, x is Euler y, y is Euler z).

Does this make sense?

I would have to change my algorithm to

float calculateRotation(const rs2_quaternion &quaternion)
{
    // http://www.chrobotics.com/library/understanding-euler-angles
    // The original axis naming is different from Euler. Align
    float w = quaternion.w;
    float x = quaternion.z;
    float z = quaternion.y;
    float y = quaternion.x;

    float pitch = -asin(2.0 * (x * z - w * y)) * 180.0 / M_PI;
    float roll = atan2(2.0 * (w * x + y * z), w * w - x * x - y * y + z * z) * 180.0 / M_PI;
    float yaw = atan2(2.0 * (w * z + x * y), w * w + x * x - y * y - z * z) * 180.0 / M_PI;

    return yaw;
}


Note: Only the negation of the quaternion.z and .y values has been removed. I don't really understand this, but it works and aligns yours and mine...

neilyoung avatar Nov 11 '19 19:11 neilyoung

I confirm having the same problem with Y value after conversion to Euler XYZ from quaternion.

Using scipy I get positive Y rotation (0.71383966):

In [6]: R.from_quat([-0.34923958 , 0.01531289 , 0.93682159 , 0.01274906]).as_euler(
   ...: 'xyz')
Out[6]: array([0.02617994, 0.71383966, 3.12413937])

In [7]: R.from_quat([-0.34923958 , 0.01531289 , 0.93682159 , 0.01274906]).as_matrix
   ...: ()
Out[7]: 
array([[-0.75573835, -0.03458292, -0.65395991],
       [ 0.01319145, -0.99920595,  0.03759584],
       [-0.65474081,  0.01978594,  0.75559446]])

Using the online calculator at https://www.andre-gaschler.com/rotationconverter/ I get the same matrix but in the conversion to Euler XYZ the result is: [ x: -0.0482988, y: -0.7129951, z: 3.0979631 ]

emilio-cartoni avatar Feb 02 '23 07:02 emilio-cartoni

I have an issue when converting my quaternion sample to Euler Angle. My quaternion q = [-0.603699,- 0.60275 ,- 0.327831 ,- 0.405948] (w,x,y,z form), and when I use my code (python), I get the result [ 1.51204108, -0.0936848 , 1.09562941] (Matlab function has the same result as me) but your calculator is [ x: 1.4448072, y: 1.0868569, z: 0.2054925 ]. Any idea ?

minhlenhat21 avatar Oct 31 '23 02:10 minhlenhat21