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.
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.