I am trying to find the Euler angles that allow the transformation from point A
to point B
in 3D space.
Consider the normalized vectors A = [1, 0, 0]
and B = [0.32 0.88 -0.34]
.
I understand that by computing the cross product A × B
I get the rotation axis. The angle between A
and B
is given by tan⁻¹(||cross||, A·B)
, where A·B
is the dot product between A
and B
.
This gives me the rotation vector rotvec = [0 0.36 0.93 1.24359531111]
, which is rotvec = [A × B; angle]
(the cross product is normalized).
Now my question is: How do I move from here to get the Euler angles that correspond to the transformation from A
to B
?
In MATLAB the function vrrotvec2mat receives as input a rotation vector and outputs a rotation matrix. Then the function rotm2eul should return the corresponding Euler angles. I get the following result (in radians): [0.2456 0.3490 1.2216]
, according to the XYZ
convention. Yet, this is not the expected result.
The correct answer is [0 0.3490 1.2216]
that corresponds to a rotation of 20°
and 70°
in Y
and Z
, respectively.
When I use eul2rot([0 0.3490 1.2216])
(with eul2rot
taken from here) to verify the resulting rotation matrix, this one is different from the one I obtain when using vrrotvec2mat(rotvec)
.
I also have a Python spinet that yields the exactly same results as described above.
--- Python (2.7) using transform3d ---
import numpy as np
import transforms3d
cross = np.cross(A, B)
dot = np.dot(A, B.transpose())
angle = math.atan2(np.linalg.norm(cross), dot)
rotation_axes = sklearn.preprocessing.normalize(cross)
rotation_m = transforms3d.axangles.axangle2mat(rotation_axes[0], angle, True)
rotation_angles = transforms3d.euler.mat2euler(rotation_m, 'sxyz')
What I am missing here? What should I be doing instead?
Thank you
A rotation matrix has 3 degrees of freedom but the constraints of your problem only constrain 2 of those degrees.
This can be made more concrete by considering the case where we have a rotation matrix R
which rotates from A
to B
so R*A == B
. If we then construct another rotation matrix RB
which rotates about vector B
then applying this rotation to R*A
won't have any effect, i.e. B == R*A == RB*R*A
. It will, however, produce a different rotation matrix RB*R
with different Euler angles.
Here's an example in MATLAB:
A = [1; 0; 0];
B = [0.32; 0.88; -0.34];
A = A / norm(A);
B = B / norm(B);
ax = cross(A, B);
ang = atan2(norm(ax), dot(A, B)); % ang = acos(dot(A, B)) works too
R = axang2rotm([ax; ang].');
ang_arbitrary = rand()*2*pi;
RB = axang2rotm([B; ang_arbitrary].');
R*A - B
RB*R*A - B
rotm2eul(R)
rotm2eul(RB*R)
Result
ans =
1.0e-15 *
-0.0555
0.1110
0
ans =
1.0e-15 *
0.2220
0.7772
-0.2776
ans =
1.2220 0.3483 0.2452
ans =
1.2220 0.3483 0.7549