Don Hatch (hatch++at++hell)
Mon, 4 Mar 1996 15:23:00 -0800
If you are using pfMatrix::makeQuat() followed by pfMatrix::getOrthoCoord,
to get the Euler angles, note that the implementation of
pfMatrix::getOrthoCoord() in Performer 2.0 is more unstable than necessary
when pitch is near +-90 degrees,
and it's just plain wrong when pitch is exactly +-90 degrees
(i.e. it gives Euler angles which represent a completely different matrix).
You could try compiling in the corrected version (included below)
which will be in future versions of Performer...
it's also more stable and tolerant of small
fluctuations in the matrix,
and it guarantees that roll=0
in the ambiguous case that pitch is +-90 degrees.
However, I am doubtful that this will improve your situation
except when the pitch is near +-90 degrees (in which case
the roll and heading are still going to be extremely
sensitive to very minor changes in the quaternion
no matter what algorithm is used)...
Even with the existing algorithm, you shouldn't be seeing discontinuities
in the roll except in the case of extreme pitch.
If you are, would you try dumping a trace of the quaternions
and Euler angles and catch it when the roll "jumps" unexpectedly?
That should make it easy to tell whether it's a bug in your program
or in one of the Performer functions.
Thanks,
Don
#include <Performer/pr/pfLinMath.h>
//
// Convert coordinate matrix to heading, pitch, roll.
//
void
pfMatrix::getOrthoCoord(pfCoord *coord)
{
float sh, ch, sp, cp, sr, cr;
coord->xyz[0] = mat[3][0];
coord->xyz[1] = mat[3][1];
coord->xyz[2] = mat[3][2];
if (mat[0][2] == 0) // (roll == 0 or 180) or (pitch == +-90)
{
if (mat[2][2] >= 0)
{
coord->hpr[2] = 0; // cr == 1, sr == 0
ch = mat[0][0];
sh = mat[0][1];
cp = mat[2][2];
}
else
{
coord->hpr[2] = 180; // cr == -1, sr = 0
ch = -mat[0][0];
sh = -mat[0][1];
cp = -mat[2][2];
}
}
else
{
//
// The following actually works fine
// in all cases, but special-casing mat[0][2] == 0 above
// often saves two trig functions and some arithmetic...
//
coord->hpr[2] = pfArcTan2(-mat[0][2], mat[2][2]); // returns 0 if both 0
pfSinCos(coord->hpr[2], &sr, &cr);
ch = cr*mat[0][0] + sr*mat[2][0];
sh = cr*mat[0][1] + sr*mat[2][1];
cp = cr*mat[2][2] - sr*mat[0][2]; // >= 0 so pitch is in [-90..90]
}
sp = mat[1][2];
coord->hpr[0] = pfArcTan2(sh, ch);
coord->hpr[1] = pfArcTan2(sp, cp);
}
-- Don Hatch hatch++at++sgi.com (415) 933-5150 Silicon Graphics, Inc.
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:52:31 PDT