# Maths - Conversion Matrix to Quaternion - Open forum discussion

 By: nobody ( Nobody/Anonymous ) 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 ) 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 ) 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 ) 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 ) 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 ) 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 ) RE: Matrix to Quaternion error.   2003-10-24 05:57 But ! Sorry i didn't check , possible it not compartible with your matrix.