模型测试阶段:如何从四元数(Quaternion)计算欧拉角?
从批量四元数计算欧拉角的实现方案
针对你的需求,提供两种可行的实现方式,均适配PyTorch批量张量(包括CUDA张量),且与你参考的旋转矩阵转欧拉角逻辑对齐:
方法1:四元数转旋转矩阵再复用现有欧拉角转换代码
先将批量四元数转换为旋转矩阵,再调用你参考的旋转矩阵转欧拉角函数计算结果,步骤如下:
批量四元数转旋转矩阵代码
import torch def quat_to_rotmat(quats): # 输入:quats 形状为 Bx4,四元数顺序为 [x, y, z, w] x, y, z, w = quats[:, 0], quats[:, 1], quats[:, 2], quats[:, 3] batch_size = quats.shape[0] # 预计算元素项 xx, yy, zz = x*x, y*y, z*z xy, xz, yz = x*y, x*z, y*z xw, yw, zw = x*w, y*w, z*w # 构造旋转矩阵 rotmat = torch.zeros(batch_size, 3, 3, device=quats.device) rotmat[:, 0, 0] = 1 - 2*(yy + zz) rotmat[:, 0, 1] = 2*(xy - zw) rotmat[:, 0, 2] = 2*(xz + yw) rotmat[:, 1, 0] = 2*(xy + zw) rotmat[:, 1, 1] = 1 - 2*(xx + zz) rotmat[:, 1, 2] = 2*(yz - xw) rotmat[:, 2, 0] = 2*(xz - yw) rotmat[:, 2, 1] = 2*(yz + xw) rotmat[:, 2, 2] = 1 - 2*(xx + yy) return rotmat
使用示例
# 你的批量四元数输入 quats = torch.tensor([[ 0.0725, -0.0645, 0.0308, 0.9948], [-0.5235, -0.2456, 0.0824, 0.8117]], device='cuda:0') # 转旋转矩阵 rotmats = quat_to_rotmat(quats) # 调用你参考的旋转矩阵转欧拉角函数 euler_angles = compute_euler_angles_from_rotation_matrices(rotmats)
方法2:直接从四元数计算欧拉角
跳过旋转矩阵转换步骤,直接通过公式计算Z-Y-X顺序(对应yaw-pitch-roll)的欧拉角,与你参考的旋转矩阵转换逻辑完全对齐:
批量四元数转欧拉角代码
import torch def quat_to_euler(quats): # 输入:quats 形状为 Bx4,四元数顺序为 [x, y, z, w] # 输出:euler_angles 形状为 Bx3,欧拉角顺序为 [yaw, pitch, roll],单位为弧度 x, y, z, w = quats[:, 0], quats[:, 1], quats[:, 2], quats[:, 3] # 计算roll(X轴旋转) sinr_cosp = 2 * (w * x + y * z) cosr_cosp = 1 - 2 * (x*x + y*y) roll = torch.atan2(sinr_cosp, cosr_cosp) # 计算pitch(Y轴旋转),处理数值稳定性避免asin输入越界 sinp = 2 * (w * y - z * x) sinp = torch.clamp(sinp, -1.0, 1.0) pitch = torch.asin(sinp) # 计算yaw(Z轴旋转) siny_cosp = 2 * (w * z + x * y) cosy_cosp = 1 - 2 * (y*y + z*z) yaw = torch.atan2(siny_cosp, cosy_cosp) # 组合结果 euler_angles = torch.stack([yaw, pitch, roll], dim=1) return euler_angles
使用示例
# 你的批量四元数输入 quats = torch.tensor([[ 0.0725, -0.0645, 0.0308, 0.9948], [-0.5235, -0.2456, 0.0824, 0.8117]], device='cuda:0') # 直接计算欧拉角 euler_angles = quat_to_euler(quats)
关键注意事项
- 四元数顺序:上述代码基于你提供的
[x,y,z,w]顺序编写,若你的四元数存储为[w,x,y,z],需调整代码中x/y/z/w的索引。 - 欧拉角顺序:代码采用Z-Y-X(yaw-pitch-roll)顺序,与你参考的旋转矩阵转换逻辑一致,若需其他顺序需修改对应公式。
- 数值稳定性:计算pitch时通过
torch.clamp限制输入范围,避免浮点误差导致的计算错误。
内容的提问来源于stack exchange,提问作者Redhwan
相关产品推荐
相关产品推荐

