I'm working with Euler angles and SciPy's implementation of them. I'm having a hard time understanding how SciPy initializes rotations matrices from Eulers, or how it represents matrices as Eulers, or both. From reading the documentation, I would assume that a single call
from_euler("ZYX", (yaw, pitch, roll))
is equivalent to a multiplication of three matrices computed from one axis each, but a simple test invalidates this assumption:
from scipy.spatial.transform import Rotation as R
def r1(roll, pitch, yaw):
r = R.from_euler("ZYX", (yaw, pitch, roll), degrees=True)
yaw, pitch, roll = r.as_euler("ZYX", degrees=True)
print(f"r:{roll:5.1f} p:{pitch:5.1f} y:{yaw:5.1f}")
def r2(roll, pitch, yaw):
r = R.from_euler("ZYX", (0, 0, roll), degrees=True) * \
R.from_euler("ZYX", (0, pitch, 0), degrees=True) * \
R.from_euler("ZYX", (yaw, 0, 0), degrees=True)
yaw, pitch, roll = r.as_euler("ZYX", degrees=True)
print(f"r:{roll:5.1f} p:{pitch:5.1f} y:{yaw:5.1f}")
r1(35, 25, 115) # as expected: "r: 35.0 p: 25.0 y: 115.0"
r2(35, 25, 115) # surprising: "r: 5.5 p:-41.8 y: 120.9"
I would be grateful for any pointers to documentation that can elaborate further on who SciPy does, or, alternatively, the obvious-to-everyone-else thing I'm missing about rotation matrices.
Maybe try:
from scipy.spatial.transform import Rotation as R
def r1(roll, pitch, yaw):
r = R.from_euler("ZYX", (yaw, pitch, roll), degrees=True)
yaw, pitch, roll = r.as_euler("ZYX", degrees=True)
print(f"r:{roll:5.1f} p:{pitch:5.1f} y:{yaw:5.1f}")
def r2(roll, pitch, yaw):
r = R.from_euler("ZYX", (0, 0, roll), degrees=True) * \
R.from_euler("ZYX", (0, pitch, 0), degrees=True) * \
R.from_euler("ZYX", (yaw, 0, 0), degrees=True)
yaw, pitch, roll = r.as_euler("ZYX", degrees=True)
print(f"r:{roll:5.1f} p:{pitch:5.1f} y:{yaw:5.1f}")
# solution
def r3(roll, pitch, yaw):
r = R.from_euler("ZYX", (yaw, 0, 0), degrees=True) * \
R.from_euler("ZYX", (0, pitch, 0), degrees=True) * \
R.from_euler("ZYX", (0, 0, roll), degrees=True)
yaw, pitch, roll = r.as_euler("ZYX", degrees=True)
print(f"r:{roll:5.1f} p:{pitch:5.1f} y:{yaw:5.1f}")
r1(35, 25, 115) # as expected: "r: 35.0 p: 25.0 y: 115.0"
r2(35, 25, 115) # surprising: "r: 5.5 p:-41.8 y: 120.9"
r3(35, 25, 115) # as expected: "r: 35.0 p: 25.0 y: 115.0"