# Maths - Conversion Matrix to Axis Angle - Forum discussion

 By: David Brown - dabhome Matrix-AngleAxis cannot handle 180 deg rot   2005-04-17 17:14 I noticed your matrix to AngleAxis cannot handle matrices that represent a rotation of 180 degrees (or at least some of them).    For example, the matrix     1 0 0  0 -1 0  0 0 -1    Is a rotation 180 degrees around 1, 0, 0. The formula gives you a vector of 0, 0, 0.    Another example is    .7071 0 .7071  0 -1 0  .7071 0 -.7071    This is a rotation 180 degrees around  0.92388 0 0.382683    This always occurs then T=T transpose.    Any thoughts?    David
 By: Martin Baker RE: Matrix-AngleAxis cannot handle 180 deg ro   2005-04-18 09:00 David,    Thanks for letting me know about this, I suspect we will have to treat rotation by 180 degrees as a special case in axis-angle (like the singularities in euler angles).    So how can we find this case? When I looked at the formula for AxisAngle to Matrix I found that the asymmetrical component about the leading diagonal is due to the sin(angle) component. So, as you say in your message, when sin(0)=sin(180) = 0  Then [m]t = [m]  (thanks for the hint!)    So if we test for symmetry:  Abs(m01-m10)<0.001 and Abs(m02-m20)<0.001 and Abs(m12-m21)<0.001  Then  Angle = 0 or 180 degrees  These are both special cases where the axis is not important.  The angle = 0 case should be easy to find because the matrix will be:  1 0 0  0 1 0  0 0 1    I will think about the best way to do this and update the page.    Martin
 By: Martin Baker RE: Matrix-AngleAxis cannot handle 180 deg ro   2005-04-18 10:03 Correction, I just said "These are both special cases where the axis is not important" which is wrong of course.    At 180 degrees,  c = cos(180) = -1  s = sin (180) = 0  t = 1-c = 2    so the matrix is:  2*x*x-1 2*x*y 2*x*z  2*x*y 2*y*y -1 2*y*z  2*x*z 2*y*z 2*z*z*-1    so,  x = sqrt((m00+1)/2)  y = sqrt((m11+1)/2)  z = sqrt((m22+1)/2)    so in the first example you give:  1 0 0   0 -1 0   0 0 -1     x = sqrt((m00+1)/2) = sqrt(1) = 1  y = sqrt((m11+1)/2) = sqrt(0) = 0  z = sqrt((m22+1)/2) = sqrt(0) = 0    which agrees with your result .    In your second example :     .7071 0 .7071   0 -1 0   .7071 0 -.7071     x = sqrt((m00+1)/2) = sqrt((1.7071)/2) = 0.9238  y = sqrt((m11+1)/2) = sqrt(0) = 0  z = sqrt((m22+1)/2) = sqrt((0.2929)/2) = 0.3826    Which also agrees with your result     Martin
 By: Martin Baker - martinbaker RE: Matrix-AngleAxis cannot handle 180 deg ro   2005-04-18 10:34 I've updated the wepage    https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/    Does this look correct to you?    Martin

Subject: RE: Matrix to Axis Angle singularities
Date: Tuesday 19 April 2005 17:40
From: "David Brown" dabhome
To: martinbaker
Cc: dabhome

Message body follows:

Martin,
Thanks for the quick response. It was very helpful. Also,
thanks for the credit. :) The modification looks good.

I would like to point out a couple of minor nits. Let me know
what you think.

When there is a singularity of 180 degrees you use a sqrt
function on a calculation that could be negative. This can
only happen if one of the values m00, m11, or m22 is > -1,
but this could happen within an epsilon (for example, -
1.000000001).

Also, the if statement for s is not necessary. It cannot be <
0.001, since the singularity if statement would be true.
When I coded it I actually calculated s and used that to
determine if there is a singularity.

Thanks,
David

Subject: RE: Matrix to Axis Angle singularities
Date: Friday 22 April 2005 19:54
From: "David Brown"
To: 'Martin Baker'

Martin,
I took a closer look at the singularity algorithm and found a flaw.

For example the matrix

0 -1 0
-1 0 0
0 0 -1

Should produce the axis angle -0.7071 0.7071 0 180. However, using the
algorithm it produces 0.7071 0.7071 0 180. This is because the results
of a
sqrt can be + or -. We therefore have to determine the signs of x, y
and z.

When the angle is 180 there are always two correct answers (x y z 180
and -x
-y -z 180) where x,y and z can be positive or negative. Therefore, you
can
always produce a result where x,y and z are either all positive or only
one
of them is negative. If m01 m02 and m12 are all >= 0 then x,y and z
are all
positive. If any of those numbers are negative then one of x,y or z is
negative.

I think the following code does the trick. What do you think?

if (m01 < -0.001) {
/* x*y is negative */
if (m13 < -0.001) {
/* x*z and y*z is negative, so make y negative */
y = -y;
}
else {
/* x*y and y*z is positive, so make x negative */
x = -x;
)
}
else {
if (m02 < -0.001) {
/* x*y is positive and x*z is negative, so make z negative */
z = -z;
}
}

David

Subject: FW: Matrix to Axis Angle singularities
Date: Friday 22 April 2005 21:28
From: "David Brown"
To: "'Martin Baker'"

In my code below it should be m12 not m13.

Subject: Another minor glitch in singularity case
Date: Friday 22 April 2005 19:58
From: "David Brown"
To: "'Martin Baker'"

Martin,
I almost forgot. I ran into a problem where my test for singularity was
true within epsilon but my test for angle 0 was not. I therefore
accidentally made it 180 when it really was 0. Since once a singularity
has been determined the angle can only be 0 or 180 the test for 0 should be
broadened to make sure a 0 angle does not get treated as 180.

Another case where epsilon is not epsilon is not epsilon. :)

David

Subject: Re: Matrix to Axis Angle singularities
Date: Saturday 23 April 2005 14:43
From: Martin Baker
To: "David Brown"

David,

Its starting to get quite complicated isn't it! I have been trying to
convince myself that your code handles all possibilities correctly,
what I'm
not sure about is; can we deal with all 6 combinations where the axis
is at
45 degrees to two axies (since this produces x,y or z =0).
So I have added a table to show these combinations on the webpage:
https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/

Can we work out an algorithm from this table like this:

if (matrix symmetrical) {
if (identity matrix) return zero angle
// this is 180 deg rotation
calculate axis with positive values
if (x*y = x*z = y*z = 0) return positive values
// rotation about x, y or z axis only
if (two of x*y , x*z and y*z are zero)
if (non-zero one is negative) invert corresponding value
if (x*y , x*z and y*z are all positive) return positive values
if (y*z is positive) invert x
if (x*z is positive) invert y
if (x*y is positive) invert z
}

I have not changed the full code yet, I thought I would see what you think first.

Martin

Subject: RE: Matrix to Axis Angle singularities
Date: Sunday 24 April 2005 10:30
From: "DAB Consulting"
To: "'Martin Baker'"

Yes it is getting complicated! :-) You inspired me to really check the whole thing over. I hope this is useful.

The cases you pointed out where two of the three matrix values are zero are not restricted to 45 degrees. All that is required is one of the x, y or z is 0. But, your algorithm still works. My algorithm had a flaw (see below after the chart).

Both of our algorithms have a problem with epsilons. Instead of checking the matrix numbers we should be checking the x, y and z numbers or using a tighter epsilon. I have included a discussion below (after the chart) with modified algorithms (yours and mine).

I created a different chart for the possible x*y, x*z, and y*z permutations.
For most of the permutations you get two x, y, and z results. For all zeros there are 6 results. For the permutations with one minus and two pluses there are no solutions. And for the permutations with only one zero there are no solutions (note: the one zero permutations are not shown in the chart; also see my discussion about epsilons at the bottom of my email).

The results are color coded based on which negative I use. I picked negative values that matched my modified algorithm (listed after the chart).
Your algorithm didn't specify which value to make negative in the case of two zeros.

 x y z x*y x*z y*z Notes + - + - + - + + + Use positive + + - Not possible + - + Not possible - + + Not possible + - + - - + + - - Use -z + - - + + - - + - Use -y - + + - + - - - + Use -x - - - Not possible 0 +- 1 0 0 0 0 +- 1 0 0 0 0 +- 1 0 0 0 Rotation around an axis. Use positive 1 0 + - + - 0 0 + Use positive + - 0 + - 0 + 0 Use positive + - + - 0 + 0 0 Use positive 0 + - - + 0 0 - Use -z (can be -y or -z) + - 0 - + 0 - 0 Use -z (can be -x or -z) - + + - 0 - 0 0 Use -x (can be -x or -y)

My original algorithm failed to handle the case where x*y and x*z = 0 and
y*z is negative. I modified it to account for this case. I also modified
the epsilons (see discussion after the program). The modifications are in
red.

```if (m01 < -0.000001) {
/* x*y is negative */
if (m12 < -0.000001) {
/* x*z and y*z is negative, so make y negative */
y = -y;
}
else {
/* x*y and y*z is positive, so make x negative */
x = -x;
)
} else {
if ((m02 < -0.000001) || (m12 < -0.000001)) {
/* x*y is positive and x*z or y*z is negative, so make z negative*/
z = -z;
}
}```

Finally, there is a small problem with dealing with epsilons. For example,
if you have an axis {0.01, -0.01, 0.99989999} then the matrix is:

 -0.9998 -0.0002 0.019998 -0.0002 -0.9998 -0.019998 0.019998 -0.019998 0.9996

If you use the epsilon of 0.001 then M01 is zero, but M02 and M12 are not.
This is not a legal case. I therefore think you have to use a tighter
epsilon (epsilon*epsilon?) for checking for zero. Either that or check the
values of x, y and z instead.

Using your algorithm but checking x, y and z for zero the algorithm with
some cleanup becomes:

```if (matrix symmetrical) {
if (identity matrix) return zero angle
// this is 180 deg rotation
calculate axis with positive values
if (x is zero and y,z are not zero) invert y or z
else if (y is zero and z is not zero) invert x or z
else if (z is zero) invert x or y
else if (x*y , x*z and y*z are all positive) return positive values
else if (y*z is positive) invert x
else if (x*z is positive) invert y
else if (x*y is positive) invert z
}```

What do you think?

David