Why do the eul2quat and quaternion functions differ on the calculated results?
Show older comments
The following discussion is all about external rotation, which corresponds to the point rotation in matlab:
I use the built-in functions "eul2quat" and "quaternion" for quaternion conversion of the same set of Euler angles data, but the results are slightly different and the signs are also different? How can I explain this, thanks in advance!
format long
eulars = [-0.001180313 -0.1101197 -3.122032;
-0.001413606 -0.1086281 -3.119092;
-0.001928661 -0.1062565 -3.116415];
a = eul2quat(eulars,'XYZ') % first X, then Y, final Z ?
b = quaternion(eulars,'euler','XYZ','point') % first X, then Y, final Z ?
But I changed the order of eul2quat to "ZYX" and it seems that the differences in values are equal, but the output quaternions are in the opposite order.
a_OK = eul2quat(eulars,'ZYX') % first X, then Y, final Z , but the output order is a bit counter-intuitive, in the form of [w,z,y,x]
Accepted Answer
More Answers (3)
Sam Chak
on 25 May 2022
Hi @cui
I remember that previously we have talked about that Euler angles and quaternion are not unique. You need to check the rotation matrix. See example below:
eul = [-0.001180313 -0.1101197 -3.122032]
qXYZ = angle2quat(eul(1), eul(2), eul(3), 'XYZ')
dcm1 = angle2dcm(eul(1), eul(2), eul(3), 'XYZ')
dcm2 = quat2dcm(qXYZ)
dcm1 - dcm2
2 Comments
xingxingcui
on 25 May 2022
Sam Chak
on 25 May 2022
angle2dcm converts the rotation angles to direction cosine matrix (aka rotation matrix). https://www.mathworks.com/help/aerotbx/ug/angle2dcm.html
angle2quat converts rotation angles to quaternion, and it works similarly like eul2quat.
Hi cui,
I think that both eul2quat and quaternion('frame') are using, right-handed, intrinsic rotations and the sequence of rotations is in the order of the sequence argument to those functions. Furthermore, eul2quat is doing a frame rotation.
Define three Euler angles
rng(100);
theta = rand(1,3);
Quaternion using eul2quat, intrinsic angles are: first around Z, second around Y', third around X''.
q1 = eul2quat(theta,'ZYX')
Quaternion based on frame rotation
q2 = quaternion(theta,'euler','ZYX','frame');
compact(q2)
So those two are the same.
The confusion, at least for me, comes in when generating the associatied direction cosine matrices (DCMs). I'm going to generate a DCM that I understand as a frame rotation for the intrinsic ZYX sequence
Zrot = [cos(theta(1)) sin(theta(1)) 0; -sin(theta(1)) cos(theta(1)) 0;0 0 1];
Yrot = [cos(theta(2)) 0 -sin(theta(2)); 0 1 0; sin(theta(2)) 0 cos(theta(2))];
Xrot = [1 0 0;0 cos(theta(3)) sin(theta(3)); 0 -sin(theta(3)) cos(theta(3))];
DCMp = Xrot*Yrot*Zrot;
Given a vector v resolved in coordinate frame xyz expressed in a column, DCMp resolves that same vector into frame x''y''z'' via post-multiplication by v
v = rand(3,1);
vp = DCMp*v;
That works the same using q2
DCM2 = rotmat(q2,'frame');
v2 = DCM2*v
However, the doc page for quat2rotm says that DCM1 is used by pre-multiplying by transpose(v), which is actually called "post-multiply format" here! (side note: I very much dislike this idea of pre-multiplication by a row vector). So we'll do that, and then transpose the result to get it back to column vector for comparison
DCM1 = quat2rotm(q1);
v1 = (v.' * DCM1).';
Compare the results, they are very, very close.
format long e
[vp - v1, vp - v2]
So, we see that angle inputs to eul2quat define a right-handed, frame rotation, but we have to be careful about the pre- and post-multiplication convention.
5 Comments
Cotinuing the discussion ...
rng(100);
theta = rand(1,3); % your origin data
q1 = eul2quat(theta,'ZYX');
R1 = eul2rotm(theta,'ZYX');
R2 = quat2rotm(q1);
R1 - R2
So R1 and R2 are equal. According to the doc page for quat2rotm R2 is to be used by premultiplying by a row vector, which I thought I illustrated above. The doc page for eul2rotm is silent on this issue, but R1 == R2, so I'll assume it's the same.
Your comment above is "The premise is ... that the point coordinates are in the right-hand side of the rotation matrix in the form of column vectors. " But R1 and R2 use coordinates on the left hand side as row vectors. So to be consistent with the premise, they both need to be transposed
R1p = transpose(R1);
R2p = transpose(R2);
Next, we have my diefintions of Zrot, etc.
Zrot = [cos(theta(1)) sin(theta(1)) 0; -sin(theta(1)) cos(theta(1)) 0;0 0 1];
Yrot = [cos(theta(2)) 0 -sin(theta(2)); 0 1 0; sin(theta(2)) 0 cos(theta(2))];
Xrot = [1 0 0;0 cos(theta(3)) sin(theta(3)); 0 -sin(theta(3)) cos(theta(3))];
As we can see, these are elemental frame rotations that multiply a column vector. For example:
format long e
Zrot - rotmat(quaternion([theta(1) 0 0],'euler','ZYX','frame'),'frame')
I'm shocked that the (3,3) element is identically zero. Regardless, DCMp is a frame rotation applied to column vector
DCMp = Xrot*Yrot*Zrot;
Now DCMp, R1p, and R2p are all the same
DCMp - R1p
DCMp - R2p
Finally, that leave us with
thetaR = rad2deg(theta);
myR = rotz(thetaR(1))*roty(thetaR(2))*rotx(thetaR(3));% common geometric transformation convention
Now it should be apparent that myR is the transpose of the others
DCMp - transpose(myR)
Whether or not myR is an extrinsic/point/muliply-by-column-on-right rotation I can't say. But it's clear from the formation of myR why it's the transpose of DCMp (and R1p and R2p). But, we can see that myR can be constructed from theta as a point rotation, but as @Brian Fanous state quaternion() uses intrinsic rotations.
myR - rotmat(quaternion(fliplr(theta),'euler','XYZ','point'),'point')
I don't disagree with this statement: "the document[ation] is not uniformly clear"
Brian Fanous
on 27 May 2022
xingxingcui
on 27 May 2022
Edited: xingxingcui
on 27 May 2022
Paul
on 27 May 2022
Since you aksed, and thanks for doing so ....
Please keep in mind that I don't claim to be familiar with all of the relevant toolboxes and doc pages. But from just poking around in response to this Question ....
Each relevant toolbox (Navigation, Aerospace, UAV, etc.) should have a standalone section that desribes the the conventions and definitions used for that toolbox.
The function doc pages in a toolbox that have anything to do with roation matrices need to clearly state if the convention is post-multiply by column or pre-multiply by row, unless the toolbox only ever uses one convention, which can be stated clearly in the standalone section. Similarly, for point/frame. Each doc page related to rotations should have a link back to the standalone page.
In at least one instance, the meaning of pre-mutiply by row was called a "post-multiply format," which was confusing.
It would be good for the standalone section to explicitly write out the single axis rotations (e.g., the R_x, R_y, R_z in your answer above) that the toolbox uses, and perhaps adopt different notaton for the elemental frame (R ) vs. point (T, as in your answer) if appropriate.
To answer your specific question, yes, have the doc define frame and point rotation as you've done in your Answer would be extremely helpful.
I do realize that documenting everything consistently and clearly across all relevant toolboxes could be a daunting task ...
xingxingcui
on 25 May 2022
0 votes
Categories
Find more on Computer Vision Toolbox in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!