Euler angle calculation

Recommended Posts

matches81    474
Hi there! That´s my first post here in the math forums, so please be gentle ;) Okay, now right to the point, I´ll first post the problem and after that the solution I got right now and the problems I have. The problem: I have a path along some faces of a 3-dimensional object. This path is chopped into keyframes, consisting of position, normal (to face), tangent(to path) and bitangent (perpendicular to tangent and normal). That works fine so far. Now the real problem is: I need the three angles (let´s call them a,b and c) for a Euler rotation, rotating around Z-axis, then new X-axis and finally around the new Z-axis again (I think this is commonly referred to as ZX'Z''). The Euler rotation should line up the standard coordinate system (X, Y and Z axis) with the target coordinate system (bitangent, normal and tangent). I really need _the angles_, not a matrix that does the complete transformation for me or anything like that, just the angles. I´m emphasizing that to prevent misunderstandings. Okay, that´s the problem. Now to my solution so far: - I project the normal onto the XY plane. Let this projection be called nXY. Then I calculate the angle between nXY and the Y-axis ( c = asin(nXY.x)). According to some drawings I made I negate c in some cases. After rotating around the Z-axis by this angle, the X'-axis is perpendicular to the normal. This step seems to work all the time. - Let´s call the set of vectors that result from rotating the standard coordinate system XYZ around the Z-axis by c X'Y'Z'. Now I calculate the angle b between the normal and Z' (which still is pointing upwards): b = acos(normal.z), because normal.DotProduct(Z') = normal.z. After those two rotations the resulting vector Z'' should be parallel to the normal, yet in some cases it isn´t, which I don´t understand. - The last step would be to calculate the angle c between X'' and the bitangent as: c = acos(bitangent.DotProduct(X'')). After those three rotations X''' should be parallel to the bitangent, Y''' to the tangent and Z''' to the normal, yet there seems to be an error in step 2, which I just can´t figure out, so it would be really kind of you to help me out with that. Perhaps a link to an understandable kind of tutorial for that or something like that would help, or you can find the error out of your head. Any way, thx in advance!

Share on other sites
matches81    474
thx, sounds like a good idea to me. If I understand you correctly, bitangent, normal and tangent could be used as column vectors to build a matrix according to which of them I want to align with which axis, right? So if I want to align bitangent with the X-axis, normal with the Y-axis and tangent with the Z-axis, I would use the BNT-matrix for that, right? And for aligning X with bitangent, tangent with Y and normal with Z I would use the BTN-matrix, correct?

But (I guess you thought this was coming): I don´t understand that article fully. I guess I understand the basic idea of decomposing the rotation matrix in order to get the required angles. But after that the problems start:

- How does this "Givens plane rotation" work?
- What are the results of it and how are they used to "undo" the last rotation?

- After undoing the last rotation successfully, I would end up with a matrix like that shown in the article, from which I can directly extract the remaining two angles, correct?

- As far as I understand the naming convention used in the article Xr stands for rotated X-axis, and Xs for static X-axis. Therefore I would need the angles for ZsXrZr, but in the article there is no further specification whether the first two axes are rotated or not. While I agree that the first axis would always be static and therefore there is no need to further specify that, I think that it matters whether the second axis is rotated or static?

Okay, after all those questions: Thx for linking me to that article! Any help regarding that would be appreciated as it seems to be a solution to my problem.

But because I really want to know why my "solution" doesn´t work, I would also appreciate any ideas as to why it doesn´t ;)

Share on other sites
jyk    2094
Quote:
 Original post by matches81thx, sounds like a good idea to me. If I understand you correctly, bitangent, normal and tangent could be used as column vectors to build a matrix according to which of them I want to align with which axis, right? So if I want to align bitangent with the X-axis, normal with the Y-axis and tangent with the Z-axis, I would use the BNT-matrix for that, right? And for aligning X with bitangent, tangent with Y and normal with Z I would use the BTN-matrix, correct?
You can assign the BNT vectors to the columns (x, y and z axes) any way you like, provided that the assignment is a forward permutation; this is to ensure a (mathematically) right-handed basis with a determinant of 1. BNT and BTN, for example, have opposite determinants, so they're not freely interchangable.
Quote:
 But (I guess you thought this was coming): I don´t understand that article fully. I guess I understand the basic idea of decomposing the rotation matrix in order to get the required angles. But after that the problems start:- How does this "Givens plane rotation" work?- What are the results of it and how are they used to "undo" the last rotation?- After undoing the last rotation successfully, I would end up with a matrix like that shown in the article, from which I can directly extract the remaining two angles, correct?- As far as I understand the naming convention used in the article Xr stands for rotated X-axis, and Xs for static X-axis. Therefore I would need the angles for ZsXrZr, but in the article there is no further specification whether the first two axes are rotated or not. While I agree that the first axis would always be static and therefore there is no need to further specify that, I think that it matters whether the second axis is rotated or static?Okay, after all those questions: Thx for linking me to that article! Any help regarding that would be appreciated as it seems to be a solution to my problem.But because I really want to know why my "solution" doesn´t work, I would also appreciate any ideas as to why it doesn´t ;)
Just thought I'd mention that Shoemake's original Graphic Gems article (if you can get a hold of it) is a little easier going than the wiki article. The code, however, is the same as that linked at the bottom of the wiki page.

You were very clear about needing the ZXZ Euler angles, but I can't help but ask, why? :-) Is it to interface with a third-party API? Some other reason?

Share on other sites
matches81    474
Yup, I need those because I have to interface a 3rd party program and a real-life toy that uses those axes with this stuff afterwards.

I really do think my solution should work, because the principle idea was the following:
If I have two vectors A and B that I want to get parallel only through _one_ rotation, I find a vector X perpendicular to both of them and calculate the angle v between A and B with a simple dotproduct (both are normalized).
After rotating for example B around X by the angle v, B should now be parallel to A, and if it isn´t, I have rotated in the wrong direction and should negate v.
Because my rotation axis X is perpendicular to both A and B, the rotation should "move" the vectors parallel to the plane they form and therefore B should "sooner or later" be parallel to A, right?

Getting hold of Shoemake´s original article? Sure, I would, and I will most probably as I was going to order the Graphics Gems and perhaps the GPU Gems, too, anyways. But it would be great if somebody could help me before that, because I´m a student and getting the money together for all those books I want / would like to have can take some time.... ;)

I have found some scans of the article on the internet so far, including code. But the article doesn´t seem to bother with anything like "Givens plane rotation".
I don´t like the idea to simply copy & paste the code, I would really like to understand what I´m doing.

Share on other sites
matches81    474
Okay, there seems to be an error with my function to rotate a vector around an arbitrary axis. All the cases where my results are wrong, the following is the case:
After doing the first two rotations (see my previous post with the description of my solution) some components of the Z'' vector have the wrong sign, otherwise it would be fine. So perhaps someone knows how to help me there?

http://astronomy.swin.edu.au/~pbourke/geometry/rotate/

and the code for that is
CVector3 RotateVectorAroundAxis(CVector3 vector, CVector3 axis, double angle){	CVector3 normAxis = axis.Normalize();		CMatrix RotX = CMatrix::Identity();	double d = sqrt(normAxis.y*normAxis.y + normAxis.z*normAxis.z);	if(abs(d)> 0.001)	{		double invD = 1.0 / d;		RotX._22 = normAxis.z * invD;		RotX._33 = RotX._22;		RotX._23 = -normAxis.y * invD;		RotX._32 = -RotX._23;	}	CMatrix invRotX = RotX.Transpose();	CMatrix RotY = CMatrix::Identity();	RotY._11 = d;	RotY._33 = d;	RotY._13 = -normAxis.x;	RotY._31 = normAxis.x;	CMatrix invRotY = RotY.Transpose();	double s = sin(angle);	double c = cos(angle);	CMatrix RotZ = CMatrix::Identity();	RotZ._11 = c;	RotZ._12 = s;	RotZ._21 = -s;	RotZ._22 = c;	CMatrix trafoMatrix = RotX * RotY * RotZ * invRotY * invRotX;	CVector3 ret = vector * trafoMatrix;	return ret;}

CMatrix is a class for a 4x4 row-major matrix, CVector3 is a 3-dimensional vector. Just in case you wonder how I can multiply a 3-dimensional vector with 4x4 matrix: I temporarily create a 4-dimensional vector from the 3-dimensional by "appending" 1.0 as the w coordinate. The value of that coordinate shouldn´t matter, I believe, as there is no translation involved in this.

Okay, now to the test results I get:
Vector A is the axis of rotaion, vector B the vector to rotate, angle the angle I want to rotate and vector R the result I get:

Test A:
A = (1.0, 0.0, 0.0); B = (1.0, 1.0, 1.0); angle = PI / 2 or 90°
R = (1.0, 1.0, -1.0)
I think R should be (1.0, -1.0, 1.0), as positive angles should be counter-clockwise rotation.

Test B:
A = (1.0, 0.0, 1.0); B = (0.0, 0.0, 1.0); angle = PI / 2 or 90°
R = (-0.5, 0.707, 0.5)
R should be (0.5, -0.707, 0.5). The resulting R from this test really surprised me, because it´s not just rotating in the wrong direction as test A did, but rotating around a different axis. I would expect that result from:
A = (-1.0, 0.0, 1.0); B = (0.0, 0.0, 1.0); angle = PI / 2 or 90°