Quaternions and the toEuler function
Posted: Thu Feb 14, 2008 8:06 am
I'm attempting to maintain a quaternion rotation and use it to set the rotation on a scene node
All seems fine right up until toEuler populates my vector with an undefined number.
Example quat values that cause this:
X 0.00000000
Y 0.70710683
Z 0.00000000
W 0.70710683
This code:
uses asin obviously which has certain acceptable range.
looking into this more i see that 1.4 uses the above, i'm on 1.3.1 currently.
i wonder if this is enough to handle the issues and give you good results, researching it more i've seen implimentations like:
Would someone more mathematically savvy then me enlighten me at to whether or not the clamp is a good solution?
Thanks in advance,
LG
PS: ignore the types i'm using in the first code example assume they are what your used to cause they are exactly that ( typedef'd )
Code: Select all
Rotate( const quaternion4f& vRot )
{
vector3f v;
vRot .toEuler( v );
v *= RADTODEG;
pSceneNode->setRotation( v );
}
Example quat values that cause this:
X 0.00000000
Y 0.70710683
Z 0.00000000
W 0.70710683
This code:
Code: Select all
// attitude = rotation about y-axis
euler.Y = (f32) (asin(-2.0 * (X*Z - Y*W)));
Code: Select all
// attitude = rotation about y-axis
euler.Y = (f32) (asin( clamp(-2.0 * (X*Z - Y*W), -1.0, 1.0) ));
i wonder if this is enough to handle the issues and give you good results, researching it more i've seen implimentations like:
Code: Select all
public void set(Quat4d q1) {
double sqw = q1.w*q1.w;
double sqx = q1.x*q1.x;
double sqy = q1.y*q1.y;
double sqz = q1.z*q1.z;
double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
double test = q1.x*q1.y + q1.z*q1.w;
if (test > 0.499*unit) { // singularity at north pole
heading = 2 * atan2(q1.x,q1.w);
attitude = Math.PI/2;
bank = 0;
return;
}
if (test < -0.499*unit) { // singularity at south pole
heading = -2 * atan2(q1.x,q1.w);
attitude = -Math.PI/2;
bank = 0;
return;
}
heading = atan2(2*q1.y*q1.w-2*q1.x*q1.z , sqx - sqy - sqz + sqw);
attitude = asin(2*test/unit);
bank = atan2(2*q1.x*q1.w-2*q1.y*q1.z , -sqx + sqy - sqz + sqw)
}
Thanks in advance,
LG
PS: ignore the types i'm using in the first code example assume they are what your used to cause they are exactly that ( typedef'd )