RoMa快速入门:旋转矩阵、四元数、旋转向量与欧拉角互转全解教程
RoMa快速入门:旋转矩阵、四元数、旋转向量与欧拉角互转全解教程
【免费下载链接】romaRoMa: A lightweight library to deal with 3D rotations in PyTorch.项目地址: https://gitcode.com/gh_mirrors/roma1/roma
RoMa(Rotation Manipulation)是一个面向 PyTorch 的轻量级 3D 旋转处理库,专为 PyTorch 中的 3D 旋转设计。它提供旋转矩阵、四元数、旋转向量、欧拉角四种常用表示之间的可微互转,以及刚体变换、测地距离、球面插值等旋转空间工具,是机器学习与梯度优化场景中处理 3D 旋转的实用工具箱。
为什么需要 RoMa?
在 3D 视觉、机器人学、姿态估计等领域,旋转的表达方式五花八门:
| 表示方式 | 维度 | 特点 |
|---|---|---|
| 旋转矩阵 RotMat | 3×3 | 直观、可线性应用,但参数冗余 |
| 四元数 UnitQuat | 4 | 无万向锁、插值稳定,但约束多 |
| 旋转向量 RotVec | 3 | 紧凑,适合回归网络输出 |
| 欧拉角 Euler | 3 | 人类易读,但存在奇异点 |
手动实现这些表示的互转既容易出错,又难以保证反向传播时梯度的正确性。RoMa 的核心价值在于:所有映射都是可微的,可以直接嵌入神经网络做端到端训练,这在 roma/mappings.py 中通过自定义 SVD 的 backward 实现(见ProcrustesWithJVP相关逻辑)保证了从任意 3×3 矩阵回归旋转矩阵时的梯度质量。
一键安装:最快配置方法
安装只需一行 pip 命令:
pip install roma导入后即可使用,全部 API 通过 roma/init.py 统一导出,无需关心子模块结构。
四表示互转:核心 API 速查
1. 旋转向量 ↔ 四元数 ↔ 旋转矩阵
这是最常用的转换链路,对应 roma/mappings.py 中的函数:
import torch import roma rotvec = torch.randn(2, 3, 3) # 支持任意批次维度 q = roma.rotvec_to_unitquat(rotvec) # 旋转向量 -> 四元数 (xyzw) R = roma.unitquat_to_rotmat(q) # 四元数 -> 旋转矩阵 Rbis = roma.rotvec_to_rotmat(rotvec) # 旋转向量 -> 旋转矩阵(一步到位)反向转换同样一步完成:
R = roma.rotmat_to_unitquat(q) # 实际为 rotmat_to_unitquat(R) rotvec = roma.rotmat_to_rotvec(R)💡 注意:RoMa 的四元数默认采用xyzw排列顺序。若你的数据来自其他库(如 wxyz 顺序),可用
roma.quat_xyzw_to_wxyz()/roma.quat_wxyz_to_xyzw()快速转换。
2. 欧拉角:支持任意轴序
欧拉角转换实现在 roma/euler.py 中,convention参数接受如 "xyz"、"ZYX" 等任意轴序字符串,且支持角度/弧度切换:
# 欧拉角(deg)-> 四元数 / 旋转向量 / 旋转矩阵 q = roma.euler_to_unitquat("xyz", angles, degrees=True) rv = roma.euler_to_rotvec("xyz", angles) R = roma.euler_to_rotmat("ZYX", angles) # 四元数 / 旋转矩阵 -> 欧拉角 angles = roma.unitquat_to_euler("xyz", q, degrees=True) angles = roma.rotmat_to_euler("xyz", R)从任意输入回归旋转矩阵
如果你的网络输出是一个"接近旋转但不严格正交"的 3×3 矩阵,直接loss到目标矩阵会破坏旋转约束。RoMa 提供三条"投影"路径(均在 roma/mappings.py):
| 函数 | 输入 | 说明 |
|---|---|---|
roma.special_procrustes(M) | 3×3 任意矩阵 | SVD 正交化,最通用的做法 |
roma.special_gramschmidt(M) | 3×2 矩阵 | 6D 连续旋转表示(Zhou et al. 方案) |
roma.symmatrixvec_to_unitquat(x) | 10 维向量 | 从 4×4 对称矩阵系数恢复四元数 |
R = roma.special_procrustes(torch.randn(2, 3, 3))相关回归方法还可参考项目论文Deep Regression on Manifolds: a 3D Rotation Case Study(3DV 2021)。
旋转空间度量与插值
判断两个旋转"差多远"、在两个姿态之间平滑过渡,是动画、SLAM 中的高频需求,工具集中在 roma/utils.py:
测地距离(旋转角度差)
R1, R2 = roma.random_rotmat(size=5), roma.random_rotmat(size=5) theta = roma.utils.rotmat_geodesic_distance(R1, R2) # 两矩阵间的最小旋转角球面线性插值(SLERP):沿测地线取最短路径,比线性插值更平滑:
steps = torch.linspace(0, 1.0, 5) rotvec_interp = roma.rotvec_slerp(rotvec0, rotvec1, steps) q_interp = roma.unitquat_slerp(q0, q1, steps)此外还有quat_product(四元数乘法)、quat_conjugation(共轭)、rotvec_inverse(求逆)等基础算子,完整示例可参考 examples/snippets/quat_operations.py 与 examples/snippets/rotvec_slerp.py。
进阶:刚体变换 Rigid
当旋转还要配合平移时,roma/transforms.py 提供了roma.Rigid类,把旋转矩阵 R 和平移向量 t 封装为刚体变换:
t = torch.randn(2, 3) T = roma.Rigid(R, t) identity = T @ T.inverse() # 变换与其逆相乘 = 单位变换 M = identity.to_homogeneous() # 转为 4×4 齐次矩阵@运算符用于变换复合,T.apply(v)对点集应用变换,T.inverse()求逆变换,非常适合机器人学中的坐标帧计算。
新手常见问题 FAQ
Q1:批次维度怎么处理?所有 API 都自动支持任意前缀批次维度(batch dims),torch.randn(2, 3, 3)、torch.randn(4, 5, 3)均可直接传入,无需手动reshape。
Q2:为什么我的四元数转出来是 xyzw 而不是 wxyz?RoMa 统一使用quat = [x, y, z, w]顺序,与其他库交换数据时记得先做顺序转换。
Q3:欧拉角转矩阵出现 NaN?欧拉角在特定姿态存在万向锁(Gimbal Lock),若下游对角度精度敏感,建议优先用四元数或旋转向量表示。
Q4:想校验自己的矩阵是否是合法旋转矩阵?用roma.utils.is_rotation_matrix(R)即可检查正交性与行列式为 1。
总结
RoMa 用一行pip install就能补齐 PyTorch 生态中 3D 旋转的完整拼图:四种表示互转、旋转回归、度量与插值、刚体变换全部可微可用。无论是训练姿态估计网络,还是做基于梯度的 3D 重建,从 README.md 的使用示例出发,配合 examples/snippets/ 下的代码片段,即可快速上手。
【免费下载链接】romaRoMa: A lightweight library to deal with 3D rotations in PyTorch.项目地址: https://gitcode.com/gh_mirrors/roma1/roma
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
