Maths - Conversion Matrix to Quaternion - Open forum discussion

By: nobody ( Nobody/Anonymous )
file Matrix to Quaternion error.  
2003-03-27 12:28

Hi there,

First of all congratulations for your great page!

Second I may have found some errors in the Matrix to Quaternion conversion code.

http://www.martinb.com/maths/geometry/rotations/conversions/matrixToQuaternion/

The corrected version would be as follows:

if (m00 > m11)&(m00 > m22)) {
S = sqrt( 1.0 + m00 - m11 - m22 ) * 2;
Qx = 0.25 / S; <----Correction
Qy = (m01 + m10 ) / S;
Qz = (m02 + m20 ) / S;
Qw = (m12 - m21 ) / S; <----Correction

} else if (m11 > m22)) {
S = sqrt( 1.0 + m11 - m00 - m22 ) * 2;
Qx = (m01 + m10 ) / S;
Qy = 0.25 / S; <----Correction
Qz = (m12 + m21 ) / S;
Qw = (m02 - m20 ) / S; <----Correction

} else {
S = sqrt( 1.0 + m22 - m00 - m11 ) * 2;
Qx = (m02 + m20 ) / S;
Qy = (m12 + m21 ) / S;
Qz = 0.25 / S; <----Correction
Qw = (m01 - m10 ) / S; <----Correction
}

By: martinbaker ( Martin Baker )
file RE: Matrix to Quaternion error.  
2003-03-28 02:47

Thank you very much for this, I have updated the web page.

I have tried to derive this from first principles and the equations that I derived seem to be different from both the original and your corrections, I would appreciate any further help that you could give.

I have marked up the issue on the web page.

Cheers,

Martin

By: nobody ( Nobody/Anonymous )
file RE: Matrix to Quaternion error.  
2003-03-28 14:55

Sorry, my mistake. It seems that I copied wrongly my own version. I think the following is the right version finally:

if (m00 > m11)&(m00 > m22)) {
S = sqrt( 1.0 + m00 - m11 - m22 ) * 2;
Qx = 0.25 * S; <----Correction
Qy = (m01 + m10 ) / S;
Qz = (m02 + m20 ) / S;
Qw = (m12 - m21 ) / S; <----Correction

} else if (m11 > m22)) {
S = sqrt( 1.0 + m11 - m00 - m22 ) * 2;
Qx = (m01 + m10 ) / S;
Qy = 0.25 * S; <----Correction
Qz = (m12 + m21 ) / S;
Qw = (m02 - m20 ) / S; <----Correction

} else {
S = sqrt( 1.0 + m22 - m00 - m11 ) * 2;
Qx = (m02 + m20 ) / S;
Qy = (m12 + m21 ) / S;
Qz = 0.25 * S; <----Correction
Qw = (m01 - m10 ) / S; <----Correction
}

Just in case I send you the actual (C++) version than I'm using (based in yours and tested):

inline void CalculateRotation( Quaternion& q ) const
{
float trace = a[0][0] + a[1][1] + a[2][2] + 1.0f;

if( trace > M_EPSILON )
{
float s = 0.5f / sqrtf(trace);
q.w = 0.25f / s;
q.x = ( a[2][1] - a[1][2] ) * s;
q.y = ( a[0][2] - a[2][0] ) * s;
q.z = ( a[1][0] - a[0][1] ) * s;
}
else
{
if ( a[0][0] > a[1][1] && a[0][0] > a[2][2] )
{
float s = 2.0f * sqrtf( 1.0f + a[0][0] - a[1][1] - a[2][2] );
q.x = 0.25f * s;
q.y = (a[0][1] + a[1][0] ) / s;
q.z = (a[0][2] + a[2][0] ) / s;
q.w = (a[1][2] - a[2][1] ) / s;

}
else if (a[1][1] > a[2][2])
{
float s = 2.0f * sqrtf( 1.0f + a[1][1] - a[0][0] - a[2][2] );
q.x = (a[0][1] + a[1][0] ) / s;
q.y = 0.25f * s;
q.z = (a[1][2] + a[2][1] ) / s;
q.w = (a[0][2] - a[2][0] ) / s;

}
else
{
float s = 2.0f * sqrtf( 1.0f + a[2][2] - a[0][0] - a[1][1] );
q.x = (a[0][2] + a[2][0] ) / s;
q.y = (a[1][2] + a[2][1] ) / s;
q.z = 0.25f * s;
q.w = (a[0][1] - a[1][0] ) / s;
}
}
}

Cheers,

Angel

By: nobody ( Nobody/Anonymous )
file RE: Matrix to Quaternion error.  
2003-03-28 15:04


Just one point more. This alternative code should be always use in place of the 1st and more simple version.

Even with orthogonal matrix the value of qw could be very small (or just 0) and produce big numerical errors when dividing.

Thanks a lot for your web and sorry again for the error in the correction ;)

Angel

By: martinbaker ( Martin Baker )
file RE: Matrix to Quaternion error.  
2003-03-28 23:37

Angel,

Thanks again, I have updated the page you have helped me to improve it a lot.

I have included your C++ code, I hope this is OK.

By the way, what is the definition of M_EPSILON?

Martin

By: minorlogic ( Michaele Norel )
file RE: Matrix to Quaternion error.  
2003-10-24 05:55

Hi Martin! 
         May be this version look more clear.
         
// create a unit quaternion
void mat_to_quat( const matrix33& mtx, quaternion& q ) {
    typedef float mtx_elm[3][3];
    const mtx_elm& m = mtx.m;
    float n4; // the norm of quaternion multiplied by 4 
    float tr = m[0][0] + m[1][1] + m[2][2]; // trace of martix
    if (tr > 0.0f){
        q.set( m[1][2] - m[2][1], m[2][0] - m[0][2], m[0][1] - m[1][0], tr+1.0f          );
        n4 = q.w;
    } else if( (m[0][0] > m[1][1] ) && ( m[0][0] > m[2][2]) ) {
        q.set( 1.0f + m[0][0] - m[1][1] - m[2][2], m[1][0] + m[0][1],
        m[2][0] + m[0][2], m[1][2] - m[2][1] );
        n4 = q.x;
    }else if ( m[1][1] > m[2][2] ){
        q.set( m[1][0] + m[0][1], 1.0f + m[1][1] - m[0][0] - m[2][2],
        m[2][1] + m[1][2], m[2][0] - m[0][2] ); 
        n4 = q.y;
    }else {
        q.set( m[2][0] + m[0][2], m[2][1] + m[1][2],
        1.0f + m[2][2] - m[0][0] - m[1][1], m[0][1] - m[1][0] );
        n4 = q.z;
    }
    q.scale( 0.5f/(float)sqrt(n4) );
}
         
         
// create a nonunit quaternion !!!
void mat_to_quat( const matrix33& mtx, quaternion& q ) {
    typedef float mtx_elm[3][3];
    const mtx_elm& m = mtx.m;
    multiplied by 4 
    float tr = m[0][0] + m[1][1] + m[2][2]; // trace of martix
    if (tr > 0.0f){
        q.set( m[1][2] - m[2][1], m[2][0] - m[0][2], m[0][1] - m[1][0], tr+1.0f          );
    } else if( (m[0][0] > m[1][1] ) && ( m[0][0] > m[2][2]) ) {
        q.set( 1.0f + m[0][0] - m[1][1] - m[2][2], m[1][0] + m[0][1],
        m[2][0] + m[0][2], m[1][2] - m[2][1] );
    }else if ( m[1][1] > m[2][2] ){
        q.set( m[1][0] + m[0][1], 1.0f + m[1][1] - m[0][0] - m[2][2],
        m[2][1] + m[1][2], m[2][0] - m[0][2] ); 
    }else {
        q.set( m[2][0] + m[0][2], m[2][1] + m[1][2],
        1.0f + m[2][2] - m[0][0] - m[1][1], m[0][1] - m[1][0] );
    }
}
 

By: minorlogic ( Michaele Norel )
file RE: Matrix to Quaternion error.  
2003-10-24 05:57

But ! Sorry i didn't check , possible it not compartible with your matrix.


metadata block
see also:

 

Correspondence about this page

Book Shop - Further reading.

Where I can, I have put links to Amazon for books that are relevant to the subject, click on the appropriate country flag to get more details of the book or to buy it from them.

 

This site may have errors. Don't use for critical systems.

Copyright (c) 1998-2023 Martin John Baker - All rights reserved - privacy policy.