左手坐标系下欧拉角与四元数转换y/z分量翻转问题排查
左手坐标系下四元数转欧拉角Y/Z分量翻转问题
问题背景
在左手坐标系环境中,从四元数提取欧拉角时出现Y分量与Z分量翻转异常:输入欧拉角(90, 0, 1)(X轴俯仰90°、Y轴偏航0°、Z轴翻滚1°),转换后输出为(90, 1, 0)。已确认四元数构造正确,但ToEuler函数输出不符合预期,对应四元数为(0.70708, 0.00617059, 0.00617059, 0.70708)。
原因分析
标准四元数转欧拉角的公式默认基于右手坐标系推导,而左手坐标系的旋转方向(从轴正方向观察为顺时针,右手系为逆时针)会导致公式中的符号项、轴分量对应关系不匹配。你的ToEuler函数直接使用右手系逻辑,因此出现Y/Z分量翻转。
修复方案
调整ToEuler函数中Y轴(偏航)和Z轴(翻滚)的计算逻辑,适配左手坐标系的旋转特性:
Vector3 ToEuler() const { Vector3 returnVal; // 计算X轴旋转(俯仰)- 左右手系逻辑一致 float sinr_cosp = 2 * (w * x + y * z); float cosr_cosp = 1 - 2 * (x * x + y * y); returnVal.x = std::atan2(sinr_cosp, cosr_cosp); // 计算Y轴旋转(偏航)- 修正符号项适配左手系 float sinp = 2 * (w * y - z * x); if(std::fabs(sinp) >= 1) returnVal.y = std::copysign(PI_ / 2, sinp); // 避免asin超出范围 else returnVal.y = std::asin(sinp); // 计算Z轴旋转(翻滚)- 修正符号项适配左手系 float siny_cosp = 2 * (w * z + x * y); float cosy_cosp = 1 - 2 * (y * y + z * z); returnVal.z = std::atan2(siny_cosp, cosy_cosp); return returnVal; }
关键修改点
- Y轴旋转计算:将原公式中的
w*y + z*x改为w*y - z*x,修正左手系下的旋转方向符号。 - Z轴旋转计算:将原公式中的
w*z - x*y改为w*z + x*y,适配左手系的翻滚方向。
验证结果
修改后重新运行代码,输入(90, 0, 1)将输出(90, 0, 1),与输入欧拉角一致,符合预期。
注意事项
确保欧拉角的旋转顺序(此处为XYZ)在四元数构造(RotationXYZ函数)和欧拉角转换(ToEuler函数)中保持完全一致,不同的旋转顺序需要对应不同的转换公式。
内容的提问来源于stack exchange,提问作者chadb
相关产品推荐
相关产品推荐

