Tom Tetlaw
Tom Tetlaw

Reputation: 113

Find angle from 3x3 matrix components

I have a 3x3 rotation matrix:

[  cos( angle ) sin( angle ) 0 ]
[ -sin( angle ) cos( angle ) 0 ]
[  0            0            1 ]

How do I work out angle?

The methods I'm using now to do this is:

void Mat3::SetAngle( const float angle ) {
    m[ 0 + 0 * 3 ] = cos( angle );
    m[ 1 + 0 * 3 ] = sin( angle );
    m[ 0 + 1 * 3 ] = -sin( angle );
    m[ 1 + 1 * 3 ] = cos( angle );
}

And to retreive it I'm using:

float Mat3::GetAngle( void ) {
    return atan2( m[ 1 + 0 * 3], m[ 0 + 0 * 3] );
}

I'm testing it like this:

Mat3 m;
m.SetAngle( 179.0f );
float a = m.GetAngle();

And a ends up being 3.0708115 which is not correct.

Upvotes: 0

Views: 613

Answers (2)

Mark Vrabel
Mark Vrabel

Reputation: 85

sin and cos take arguments in radians, while atan2 returns an angle in radians.

179 rad = 3.070811 + 14 * 2 * pi rad

which is the same angle as 3.070811 rad.

You could either pass in the required angle as radians and convert the GetAngle result

m.SetAngle( 179.0f * M_PI / 180.0f );
float a = m.GetAngle() * 180.0f / M_PI;

or modify the class to take degrees

void Mat3::SetAngle( const float angleDeg ) {
    angleRad = angleDeg / 180.0f * M_PI;
    m[ 0 + 0 * 3 ] = cos( angleRad );
    // etc
}

float Mat3::GetAngle( void ) {
    return atan2( m[ 1 + 0 * 3], m[ 0 + 0 * 3] ) * 180.0f / M_PI;
}

Either way I'd suggest documenting which unit your class expects.

Upvotes: 1

Thomas W
Thomas W

Reputation: 14164

Use an atan( sin/ cos) function, or atan2( sin, cos) if it's available.

The simple single-argument atan( s/c) is the basic method. That answers angles from nearly -PI to +PI (approaching -90 degrees to approaching +90 degrees), but you will need to special-case a divide-by-0 at +/- 90 degrees exactly.

You also need to modify the result angle for "cosine(X) < 0", that is for the other 180 degrees of the circle.

See:

Upvotes: 0

Related Questions