
本文详解 euler 角与四元数互转时因旋转顺序大小写混淆(如 "zyx" vs "zyx")导致的不一致性问题,指出内在/外在旋转的本质差异,并提供可复现的修复代码与最佳实践。
本文详解 euler 角与四元数互转时因旋转顺序大小写混淆(如 "zyx" vs "zyx")导致的不一致性问题,指出内在/外在旋转的本质差异,并提供可复现的修复代码与最佳实践。
在三维姿态表示中,Euler 角与四元数之间的双向转换是常见操作,但极易因旋转约定不统一而产生看似“失真”的结果——例如输入 [45°, 30°, 60°](ZYX 顺序),还原后却得到 [4.4°, 52.1°, 45.2°]。这并非数值精度误差或算法缺陷,而是源于 scipy.spatial.transform.Rotation 中一个关键设计:大写字母(如 "ZYX")表示 intrinsic(固连系)旋转,小写字母(如 "zyx")表示 extrinsic(固定系)旋转。二者数学上等价于不同顺序的逆运算,因此混用将直接破坏可逆性。
以下为修正后的完整流程(严格统一使用 "ZYX"):
import numpy as np
from scipy.spatial.transform import Rotation as R
# 原始测试数据(单位:度)
testrotation = np.array([
[[45, 30, 60], [10, 20, 30]],
[[90, 0, 45], [90, 45, 30]]
])
# ✅ Step 1: Euler (deg) → Quaternion — 统一用大写 "ZYX"(intrinsic)
euler_rad = np.radians(testrotation)
quat_xyzw = R.from_euler("ZYX", euler_rad.reshape(-1, 3)).as_quat() # 输出为 xyzw 格式
quat_wxyz = np.roll(quat_xyzw, shift=1, axis=-1).reshape(testrotation.shape + (4,))
print("✅ Quaternions (wxyz):\n", quat_wxyz)
# ✅ Step 2: Quaternion → Euler — 必须使用相同约定:"ZYX"
euler_back_rad = R.from_quat(quat_xyzw).as_euler("ZYX", degrees=False)
euler_back_deg = np.degrees(euler_back_rad).reshape(testrotation.shape)
print("\n✅ Euler angles after round-trip (ZYX → quat → ZYX):\n", euler_back_deg)
# ✅ Step 3: 验证可逆性 — 再次转回四元数,应完全一致
quat_recon_xyzw = R.from_euler("ZYX", np.radians(euler_back_deg.reshape(-1, 3))).as_quat()
quat_recon_wxyz = np.roll(quat_recon_xyzw, shift=1, axis=-1).reshape(testrotation.shape + (4,))
print("\n✅ Reconverted quaternions (wxyz) — identical to original:\n",
np.allclose(quat_wxyz, quat_recon_wxyz, atol=1e-10))关键注意事项:
-
R.from_euler("ZYX", ...)与R.from_euler("zyx", ...)不等价:前者是绕自身坐标系依次旋转 Z→Y→X;后者是绕世界坐标系依次旋转 z→y→x,等价于"XYZ"的逆序(即"ZYX"的反向应用)。 - SciPy 默认输出四元数为
xyzw(x, y, z, w),若需wxyz格式(如 PyTorch3D、ROS 等常用),务必用np.roll(..., shift=1),且该操作必须在所有转换步骤中保持一致。 - 对于任意 Euler 序列(如
"XYZ","ZYZ"),大小写必须全程统一;推荐始终使用大写以明确表达 intrinsic 意图,这是机器人学与图形学中的主流约定。
总结: Euler ↔ quaternion 的可逆性不依赖于数值库实现,而取决于旋转语义的一致性。只要确保 from_euler 和 as_euler 使用完全相同的字符串(包括大小写与顺序),即可获得精确的双向转换结果。调试时建议优先检查该字符串是否被意外修改(如 .lower() 或拼写错误),而非怀疑浮点精度问题。

















