Re: performer's matrix-to-HPR algorithm

New Message Reply Date view Thread view Subject view Author view

Don Hatch (hatch++at++hell.engr.sgi.com)
Tue, 15 Sep 1998 14:16:59 -0700


On Sep 15, 11:11am, I wrote:
>
> I'm having a hard time following your version.
> In the non-degenerate case, you set:
> *xrot (i.e. pitch) = atan2f(mat[1][2], mat[2][2])
> but this doesn't seem right, since mat[1][2] is sin(pitch)
> and mat[2][2] is cos(roll)*cos(pitch).
> So I'm lost right there...

Oh, I see what happened, some rows and signs got mixed up.
I think it's supposed to be something like this:

> > void matrix_get_rot( MATRIX mat, float * xrot, float * yrot, float *
> > zrot )
> > {
> > double cp;
> >
> > cp = sqrt( mat[1][0]*mat[1][0] + mat[1][1]*mat[1][1] );
> >
> > if( cp > 16 * FLT_EPSILON ) {
> >
> > *yrot = atan2f( -mat[0][2], mat[2][2] ); // roll
> > *xrot = atan2f( mat[1][2], cp ); // pitch
> > *zrot = atan2f( -mat[1][0], mat[1][1] ); // heading
> > }
> > else
> > ...

This seems correct, but it is unstable near pitch = 90 degrees--
unstable in the sense that converting mat -> HPR -> mat can give
a drastically different matrix from the one you started with,
due to small errors/non-orthogonalities
in the matrix entries; this should NEVER happen.

Example:
    Say you start with a matrix expressing pitch=90 degrees:
        [1 0 0]
        [0 0 1]
        [0 -1 0]
    Now introduce a small error E (bigger than 16*FLT_EPSILON, whatever
    that means):
        [1 0 0]
        [E 0 1]
        [0 -1 0]
    Then your algorithm will do this:
        cp = sqrt(E*E + 0*0)
           = E;
        *yrot = atan2f(0, 0) // roll
              = 0; // somewhat arbitrarily
        *xrot = atan2f(1, E) // pitch
              = 90 degrees (give or take E radians)
        *zrot = atan2f(-E, 0) // heading
              = -90 degrees // !! BAD !!
    Converting back to matrix form, this gives:
        [ 0 -1 0]
        [-E 0 1]
        [-1 0 0]
    which is very severely wrong!

What's happening here is, if you have a matrix in which
the pitch is near 90 degrees, then the heading and roll
become ambiguous/unstable, but *not* independently so.
I.e. given such a matrix, you can pick either roll or heading arbitrarily,
but once you do that, the other of these two variables is then
completely determined in terms of the one you picked.

Performer's algorithm works this way-- it chooses roll,
and then it calculates heading robustly in terms of it.
In contrast, any algorithm that calculates heading and roll
independently, directly from the matrix,
is going to be unstable (as in the above example).

Don

-- 
Don Hatch  hatch++at++sgi.com  (650) 933-5150  Silicon Graphics, Inc.

New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Tue Sep 15 1998 - 14:17:03 PDT

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.