如何在nalgebra或其他Rust库中获取zyx顺序欧拉角?
解决四元数转ZYX顺序欧拉角的问题
我来帮你搞定这个转换问题~目前nalgebra确实只内置了XYZ顺序的欧拉角转换,但我们有两种可行的方案:手动基于旋转矩阵计算ZYX欧拉角,或者用支持自定义顺序的替代库。
方案一:基于nalgebra手动计算ZYX欧拉角
我们可以先把四元数转换成旋转矩阵,再用ZYX顺序的欧拉角反解公式来计算。这里以Z-Y-X extrinsic顺序(即依次绕世界坐标系的Z轴、Y轴、X轴旋转)为例,代码如下:
use nalgebra::{UnitQuaternion, Matrix3}; use std::f32::consts::PI; pub fn raw_quaternion_to_zyx_euler(w: f32, x: f32, y: f32, z: f32) -> (f32, f32, f32) { // 构造单位四元数 let unit_quat = UnitQuaternion::from_quaternion(nalgebra::Quaternion::from_vector([w, x, y, z])); // 转换为3x3旋转矩阵 let rot_mat: Matrix3<f32> = unit_quat.into(); // 计算Z-Y-X顺序的欧拉角(yaw: Z轴旋转角, pitch: Y轴旋转角, roll: X轴旋转角) let yaw = rot_mat[(0, 0)].atan2(rot_mat[(1, 0)]); let pitch = (-rot_mat[(2, 0)]).asin(); let roll = rot_mat[(2, 1)].atan2(rot_mat[(2, 2)]); // 可选:将角度调整到[0, 2π]范围(如果需要的话,也可以保留[-π, π]) let yaw = if yaw < 0.0 { yaw + 2.0 * PI } else { yaw }; let pitch = if pitch < 0.0 { pitch + 2.0 * PI } else { pitch }; let roll = if roll < 0.0 { roll + 2.0 * PI } else { roll }; (yaw, pitch, roll) }
如果需要的是intrinsic(内旋)Z-Y-X顺序(依次绕自身坐标系的Z轴、Y轴、X轴旋转),只需要调整公式即可,你可以参考欧拉角的官方转换逻辑来修改计算步骤。
方案二:使用支持自定义欧拉角顺序的替代库
如果不想手动写公式,推荐使用glam库——这是一个专为游戏和图形开发优化的Rust线性代数库,直接支持指定欧拉角顺序转换。
首先在Cargo.toml中添加依赖:
[dependencies] glam = "0.24" # 可以使用最新版本
然后实现转换的代码非常简洁:
use glam::{Quat, EulerRot}; pub fn raw_quaternion_to_zyx_euler(w: f32, x: f32, y: f32, z: f32) -> (f32, f32, f32) { // 构造glam的四元数(参数顺序为wxyz,和你的输入一致) let quat = Quat::from_wxyz(w, x, y, z); // 指定ZYX顺序转换,返回(yaw, pitch, roll)对应Z、Y、X轴的旋转角 quat.to_euler(EulerRot::ZYX) }
glam还支持其他多种欧拉角顺序,比如XYZ、XZY等,完全能满足不同的旋转需求。
关于XYZ转ZYX顺序的说明
这里要提醒一下:不同顺序的欧拉角不是简单调换顺序或修改符号就能转换的,它们对应的旋转逻辑完全不同,直接转换会得到错误的结果。所以最好的方式还是直接从四元数计算目标顺序的欧拉角,而不是先转成XYZ再转换。
内容的提问来源于stack exchange,提问作者user1782747
相关产品推荐
相关产品推荐

