Matrix to Axis Angle Fix By: Dominik Ries (hzdgopher) - 2008-09-23 11:11 |
Well first of all, thanks for that great site :) I've been using the matrix to axis angle code snippet for creating vrml exports of a scenegraph. It worked really well until a few days ago when i apparently encoutered a case which is not handled correctly in the code. My matrix looks like this: -0.141 0.111 0.983 0.111 -0.985 0.127 0.983 0.127 0.126 The result I get with the code from this site is: axis(0.655, 0.084, 0.750), angle(PI) but should rather be: axis(-0.655, 0.084, 0.750), angle(PI) So the conversion somehow didnt flip the sign of the axis x component. Since the matrix is symmetrical and is no identity matrix, its the code branch for the 180deg rotation which seems to produce that error. To determine the sign of the axis components there is a permutation table given from which the code was derieved, but the comment in the code snippet confuses me a bit: if (xZero && !yZero && !zZero) { // implements last 6 rows of above table If I look at the permutation table and go through my matrix values by hand I come to the case in the table row 7 (- - + Use -x) which is not in the last 6 rows of the table but needs to be considered as well (as well as the cases in row 5 and 6) imho. I added this in my code and it works fine. My sign adjustment code in the 180deg rotation case reads now (sorry for vb code) : Dim xy As Double Dim xz As Double Dim yz As Double If (Math.Abs(x) < epsilon1) Then x = 0 If (Math.Abs(y) < epsilon1) Then y = 0 If (Math.Abs(z) < epsilon1) Then z = 0 xy = m(3) xz = m(6) yz = m(7) ' table rows 5-7 If ((x <> 0) And (y <> 0) And (z <> 0)) Then If ((xy > 0) And (xz < 0) And (yz < 0)) Then: z = -z If ((xy < 0) And (xz > 0) And (yz < 0)) Then: y = -y If ((xy < 0) And (xz < 0) And (yz > 0)) Then: x = -x ' table row 12 ElseIf ((xy = 0) And (xz = 0) And (yz = 0)) Then x = 0 y = 1 z = 0 ' table rows 13 and 16 ElseIf ((x = 0) And (y <> 0) And (z <> 0)) Then If (yz < 0) Then: y = -y ' table rows 14 and 17 ElseIf ((x <> 0) And (y = 0) And (z <> 0)) Then If (xz < 0) Then: z = -z ' table rows 15 and 18 ElseIf ((x <> 0) And (y <> 0) And (z = 0)) Then If (xy < 0) Then: x = -x End If Maybe someone can confirm this. I'm not too deep into maths, but at least it seems to work now for my matrix. Regards, Dominik Ries |
RE: Matrix to Axis Angle Fix By: Dominik Ries (hzdgopher) - 2008-09-23 11:21 |
Uhm, maybe I should provide the correct matrix ... sorry My matrix looks like this: -0.141 -0.111 -0.983 -0.111 -0.985 0.127 -0.983 0.127 0.126 |
RE: Matrix to Axis Angle Fix By: rquey (rquey) - 2008-09-23 12:19 |
Hi, The general conversion from rotation matrix g to axis angle of rotation (r, theta) is, theta = acos [(g_11+g_22+g_33-1)/2] if theta != 0 and theta != 180 then r_1 = (g_23 - g_32) / (2*sin(theta)) r_2 = (g_31 - g_13) / (2*sin(theta)) r_3 = (g_12 - g_21) / (2*sin(theta)) else if theta = 180 then r_1 = +- sqrt((g_11+1)/2) r_2 = +- sqrt((g_22+1)/2) r_3 = +- sqrt((g_33+1)/2) with { m | for all i in {1, 2, 3}, |r_m| >= |r_i| // looking for the max., which is the only one which cannot be zero r_m > 0 by convention for all i != m, sgn (r_i) = sgn (g_im) } else (i.e. theta = 0) then r_1 = 1 by convention r_2 = 0 r_3 = 0 See http://sourceforge.net/projects/orilib. Best regards, |
RE: Matrix to Axis Angle Fix By: Martin Baker (martinbaker) - 2008-09-24 08:06 |
Hi Dominik, Thank you very much for pointing this out, I think you are correct. In order to investigate this I have added a javascript calculator to the end of the web page, this shows the intermediate results as well as the final results. When I put in your matrix I get: xy < 0 xz < 0 yz > 0 which means that x must be negative. I will alter the code in a similar way to your vb code, this may take me a while. Hi Rquey, Thanks for the information about the orilib algorithm, I might include this on the web page as an alternative. I am a bit wary of saying "The general conversion ..." because there are many equivalent algorithms that will work. What I would really like to do is analyse the various options for resilience to de-normalised or de-orthogonal matrices and for values around the singularities and also for performance. I must admit I haven't done a proper analysis of these issues, do you know of such an analysis on these algorithms? It concerns me when this algorithm calculates theta from acos and then takes the following results from sin(theta). This double trig function sequence seems like it might be unstable at the extreme values, I feel happier using Pythagoras, but I haven't analysed it properly so I might be wrong. Martin |
RE: Matrix to Axis Angle Fix (New) By: rquey (rquey) - 2008-09-24 09:14 |
Hi Martin, You are right, there are several possibilities -- I'm not aware of any formulation for that particular case. However, it seems to me that the algorithm to choose the sign of the r_i that I propose is unique, because one have to detect a non-zero r_i and, up to me, there is only one way to do this. As for the acos then sin stuff, maybe there is an alternative solution, in which case I would be very interested in it... Best regards, |
RE: Matrix to Axis Angle Fix (New) By: Martin Baker (martinbaker) - 2008-09-24 15:37 |
Rquey, The algorithm that we were discussing is on this page: https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/ I can't see an alternative to the acos but the algorithm that I worked out does not use sin. It seems to me that what we are doing is calculating a unit circle in the plane of the rotation, that is, the plane that is perpendicular to the axis of rotation. The coordinates form a right angled triangle, you are using: sin(theta) = opposite cos(theta) = adjacent whereas I am using: opposite^2 + adjacent^2 = 1 This expresses the same thing, at least in the first quadrant, but yours will give a negative value for negative angles but mine always returns positive (because square root always returns positive). This accounts for the differences in the other parts of the algorithm. Martin |
I have just updated the web page, sorry it took so long, thank you very much for the the correction and the comments. As I think this thread may be useful to others I have linked to it from the webpage assuming that's OK with you. Cheers, Martin |