logo back up home forward   further reading more topics »

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.

cover Mathematics for 3D Game Programming. - Second edition provides new information on illumination, collision detection, polygonal techniques. New chapters cover rendering pipeline, shadows, numerical methods, and curves and surfaces.

Commercial Software Shop

Where I can, I have put links to Amazon for commercial software, not directly related to the software project, but related to the subject being discussed, click on the appropriate country flag to get more details of the software or to buy it from them.

 

cover Dark Basic Professional Edition - It is better to get this professional edition

cover This is a version of basic designed for building games, for example to rotate a cube you might do the following:
make object cube 1,100
for x=1 to 360
rotate object 1,x,x,0
next x

cover Game Programming with Darkbasic - book for above software

Can you help?

Please send me any improvements to here. I would appreciate ideas to make the pages more useful including error correction, ideas for new pages, improvements to wording. It helps if you quote the full URL of the page.

 

progam

I am working on a project which uses these principles, if you would like to help me with this you are welcome to join in, here:

http://sourceforge.net/projects/mjbworld/

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

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