Difference between angle2dcm and eul2rotm (same angle sequence, different result)

Hello everyone, I tried to use both functions angle2dcm and eul2rotm with the same angle sequence, but the results are different. Why?
I noticed that the two matrices are one the transpose of the other one, but what is the reason?
R=angle2dcm(-0.9277, -0.0553, -0.1741,'ZYX')
R=eul2rotm([-0.9277, -0.0553, -0.1741],'ZYX')
Thank you for your time.

1 Comment

angle2dcm( ) comes from the Aerospace Toolbox, which treats rotations as passive coordinate system transformations ('frame' in the doc). eul2rotm( ) comes from the Robotics Toolbox which treats rotations as active vector rotations ('point' in the doc). These two different conventions are essentially the inverse of each other. More discussion on these different toolbox conventions can be found here:

Sign in to comment.

Answers (2)

I check and the eul2rotm command returns the rotation matrix according to Wikipedia definition of euler z-y'-x" intrinsic to rotation matrix
thetaz = -0.9277; % yaw, psi
thetay = -0.0553; % pitch, theta
thetax = -0.1741; % roll, phi
Rx = makehgtform('xrotate',thetax); Rx = Rx(1:3,1:3);
Ry = makehgtform('yrotate',thetay); Ry = Ry(1:3,1:3);
Rz = makehgtform('zrotate',thetaz); Rz = Rz(1:3,1:3);
R = Rz*Ry*Rx
which is
R =
0.5988 0.7939 0.1060
-0.7990 0.5829 0.1474
0.0553 -0.1730 0.9834
This matrix is a Rotation matrix, that can be interpreted in 2 ways:
  1. Assuming you have a unrotate body (airplane) in the global (outside world) coordinates xyz := [x;y;z], when you apply R*xyz you'll fine the coordinates ot the rotated airplane yaw-pitch-roll with the right hand rule.
  2. Assuming you have a point/vector P in a local coordinates L = [lx;ly;lz] attached to the rotated-airplane, when you apply R, you'll find the global (outside world) coordinates G=[gx;gy;gz] of this point R*L = G.
For the same euler-angles, the angle2dcm command returns (as Jan pointed out) the transposed matrix T := R', which is also the inverse of R.
So the matrix T can be interpreted as the matrix when apply on a gobal coordinates G of a point P, you'll get the local coordinates L.
There are possibly different interpretation depending on the context. The best is to write down the mathematical formula instead of writing non-sense bla-bla as often with TMW document page.
R1 = angle2dcm(-0.9277, -0.0553, -0.1741, 'ZYX')
R2 = eul2rotm([-0.9277, -0.0553, -0.1741], 'ZYX')
Do you see that R1 is the transpose of R2? This means, that both matrices create the "same" rotation, while one is applied to the vector and the other to the coordinate system. Or in other words, if the operation of rotating is applied to convert the original coordinate system to the transformed one, or the other way around.
There is no unique definition and each field of science uses other standards. So in biomechanics another convention is used than in aeronautics. This means that both R1 and R2 are correct, but it would be fine, if the documentation of both commands explain explicitly, what is replied.

12 Comments

Hello @Jan, thank you for your reply. For me it's very difficult to understand the difference between the two functions (also after I studied the theory). Can you suggest me any good references about these Matlab functions please?
A reference for the Matlab functions? I do not have one also, because I did not write them. But you find a lot of references for the creation of the rotation matrix using Euler angles. So what exactly is the problem you have?
Hello @Jan, from the mathematical point of view, the rotation matrix relative to the sequence z-y'-x'' is (I call:
alpha = -0.1741 the rotation angle around the x'' axis;
beta = -0.0553 around y';
gamma = -0.9277 around z.
I am considering elementary rotations relative to the current reference frame. E.g. I have the initial reference frame A, after the first elementary rotation around the z axis of A, I get a second reference frame B, I do the second elementary around y' which is the axis of B. Now I have a third reference frame C; the last elementary rotation takes place around the x'' axis of C. This is the robotics nomenclature.):
R_{C-->A} = Rz(alpha) * Ry'(beta) * Rx''(alpha) =
0.jpg
Thus, if I know alpha, beta and gamma, I can get the above rotation matrix which is the following (I did it by hand and by software):
0.jpg
Now the problem is: Matlab gives me the above rotation matrix only when I use the function:
eul2rotm([-0.9277, -0.0553, -0.1741],'ZYX')
I don't understand why eul2rotm gives me the right matrix R_{C-->A}, instead angle2dcm gives me the matrix transpose(R_{C-->A}) = R_{A-->C}.
@Gennaro Arguzzi: The difference between "you do not understand why" and "you do understand why" is only the tiny step to accept, that these two functions reply different results according to different standards. Both matrices are mathematically correct, but they use different definitions. "I am rotating clockwise" or "the reference system is rotating counter-clockwise" is equivalent and both are valid descriptions of the same motion.
I agree that the different answers of angle2dcm and eul2rotm are not clearly explained in the documentation. But it is not hard to find out, what is the usual convention in your field of science and to stay at it. A "rotation matrix" alone is ambiguous as long as it is not accompanied by the defintion of the applied convention.
I have a similar question.
If I code the angle to DCM conversion myself as per Wikipedia, the result is the same as that from angle2dcm() only when I negate input angles.
aa = [-1.04719755119660 -1.04719755119660 -0.785398163397448];
m1 = angle2dcm(aa(1),aa(2),aa(3), 'XYZ');
m2 = eul2rotm(aa, 'xyz');
alpha = -aa(1);
beta = -aa(2);
gamma = -aa(3);
rotZ = [cos(gamma), -sin(gamma), 0; sin(gamma), cos(gamma), 0; 0, 0, 1];
rotY = [cos(beta), 0, sin(beta); 0, 1, 0; -sin(beta), 0, cos(beta)];
rotX = [1, 0, 0; 0, cos(alpha), -sin(alpha); 0, sin(alpha), cos(alpha)];
mm = rotZ * rotY * rotX;
The above produces the following:
m1=[0.353553390593274 0.176776695296637 0.918558653543692
0.353553390593274 0.883883476483184 -0.306186217847897
-0.866025403784439 0.433012701892219 0.250000000000000];
m2=[0.353553390593274 0.353553390593274 -0.866025403784439
0.176776695296637 0.883883476483184 0.433012701892219
0.918558653543692 -0.306186217847897 0.250000000000000];
mm=[0.353553390593274 0.176776695296637 0.918558653543692
0.353553390593274 0.883883476483184 -0.306186217847897
-0.866025403784439 0.433012701892219 0.250000000000000];
Should not the signs of angles be negated?
If a simple test is taken to calculate new position of a vector after a 3D rotation:
pt0 = [1, -1, 0];
curXYZAngle = [90, 0, 0];
alpha = curXYZAngle(1);
beta = curXYZAngle(2);
gamma = curXYZAngle(3);
rotZ = [cosd(gamma), -sind(gamma), 0; sind(gamma), cosd(gamma), 0; 0, 0, 1];
rotY = [cosd(beta), 0, sind(beta); 0, 1, 0; -sind(beta), 0, cosd(beta)];
rotX = [1, 0, 0; 0, cosd(alpha), -sind(alpha); 0, sind(alpha), cosd(alpha)];
mm = rotZ * rotY * rotX;
pt1 = mm * pt0';
which is correct without negating the sign.
When you reverse the sign of angles
  • you compute the inverse of the rotation matrix with original angle
  • Or the transpose of it, because rotation matrix is orthogonal matrix, i.e., inv(R) = R'
Indeed, I wish to study the change of co-ordinates of any point on a rigid body as it rotates, and the order of operations is a rotation around world reference system axis X, then Y, and finally Z. Hence I suppose the final rotation matrix shall be Rz*Ry*Rx, and the rotated co-ordinates of any point shall be given by Rz*Ry*Rx*pt' as exhibited in my second example above. Yet the code of eul2rotm() is very confusing. My case seems to suit its 'zyx' convention though I intend to rotate the body around X first--see the comment in the code of eul2rotm() below. According to the comment, ct = [cz cy cx] and st = [sy sy sx] (should be [sz, sy, sx], anyway), the input eul shall be rotational angles around Z, Y, and X instead of around X, Y, and Z. And yet note that a so-called 'zyx' convention is normally understood as a serial of rotations in the oder of Z, Y, and X, that is, Rx*Ry*Rz, because any point shall be left-multiplied by Rz first, which also co-incides with what Wikipedia says. I am therefore wondering if this function can be given a second thought of modification and clarification in a future version.
R = zeros(3,3,size(eul,1),'like',eul);
ct = cos(eul);
st = sin(eul);
% The parsed sequence will be in all upper-case letters and validated
switch seq
case 'ZYX'
% The rotation matrix R can be constructed as follows by
% ct = [cz cy cx] and st = [sy sy sx]
%
% R = [ cy*cz sy*sx*cz-sz*cx sy*cx*cz+sz*sx
% cy*sz sy*sx*sz+cz*cx sy*cx*sz-cz*sx
% -sy cy*sx cy*cx]
% = Rz(tz) * Ry(ty) * Rx(tx)
R(1,1,:) = ct(:,2).*ct(:,1);
R(1,2,:) = st(:,3).*st(:,2).*ct(:,1) - ct(:,3).*st(:,1);
R(1,3,:) = ct(:,3).*st(:,2).*ct(:,1) + st(:,3).*st(:,1);
R(2,1,:) = ct(:,2).*st(:,1);
R(2,2,:) = st(:,3).*st(:,2).*st(:,1) + ct(:,3).*ct(:,1);
R(2,3,:) = ct(:,3).*st(:,2).*st(:,1) - st(:,3).*ct(:,1);
R(3,1,:) = -st(:,2);
R(3,2,:) = st(:,3).*ct(:,2);
R(3,3,:) = ct(:,3).*ct(:,2);
"And yet note that a so-called 'zyx' convention is normally understood as a serial of rotations in the oder of Z, Y, and X, that is, Rx*Ry*Rz, because any point shall be left-multiplied by Rz first, which also co-incides with what Wikipedia says."
No you simplify too much the convention, there are on top of that the notion of intrinsic then extrinsic, then some possible reversing because some people might prefer to multiiply rotation matrix by row vector of coordinates from the left side and not column vector on the right side as with MATLAB. Those "convention" naming are really confusing. Only matters is how the roration are buildt in which order. The rest is a matter of interpretation in each context for each person.
I would NOT tell you my interpretation, or comment on YOUR interpretation.
Only formula matters for me.
I agree that the naming is very confusing. So it seems that the best way is to code ourselves, since we can control everything completely.
Or better still just state
eul2rotm([theta1 theta2 theta3],'ZYX')
returns
R = Rz(theta1)*Ry(theta2)*Rx(theta3)
and
angle2dcm([theta1 theta2 theta3],'ZYX')
returns
R = Rx(-theta3)*Ry(-theta2)*Rz(-theta1)
= (Rz(theta1)*Ry(theta2)*Rx(theta3))'
There is no room for interpretation as with TMW doc page
"ZYX" (default) – The order of rotation angles is z-axis, y-axis, x-axis."
What order? left to right (reading order) or right to left (apply order)? intrincic or extrincic? The MATLAB doc is inaccurate or at least confusing.
FWIW, we have at least one data point that suggests Matlab does not use extrinsic rotations in any function in any toolbox: link to comment.
But we do have to worry about pre-muliplly by row vs. post-multiply by column, and frame vs. point rotation, which are also sometimes referred to as passive vs. active rotation.
I agree wholheartedly that the doc pages across the various toolboxes are inconsistent and confusing, as discussed in the entire thread of the linked comment.
For what it's worth, and it may not be much, my understanding is that angle2dcm produces a frame rotation (i.e., given the coordinates of a vector resolved in the "from" frame, find coordinates of the same vector resolved in the "to" frame) that pre-multiplies a column of coordinates and eul2rotm produces a frame rotation that post-multiplies a row of coordinates. For both functions 'ZYX' means the angle inputs to the functions are taken as first angle around Z, second around the subsequent Y, third around the subsequet X (same as the final X).
I've seen flamewars in duscussion about the "right" order of rotations and signs of the angles. The problem is trivial from a mathematical point of view and a drama if persons discuss about it.I'm looking forward to seeing, that this discussion here keeps its focussed on the Matlab part.

Sign in to comment.

Categories

Find more on Linear Algebra in Help Center and File Exchange

Asked:

on 23 Dec 2018

Commented:

Jan
on 9 Jul 2022

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!