如何将时间段内的角速度向量转换为四元数?不同方法结果为何有差异
结果差异的核心原因
你测试的两类计算逻辑对应完全不同的旋转表示,物理意义完全不一致,因此结果存在差异:
- Matlab
angle2quat、Eigen链式AngleAxis相乘的逻辑是XYZ顺规欧拉角转四元数:输入的[1,2,3]是三个独立的欧拉角,代表依次绕当前坐标系X轴旋转1rad、Y轴旋转2rad、Z轴旋转3rad的分步叠加旋转,和角速度的物理定义不匹配。 - 参考方法、在线转换器的逻辑是旋转向量(轴角)转四元数:输入的
[1,2,3]是旋转向量,向量方向为旋转轴,模长为绕该轴旋转的总角度,代表单次绕固定轴的旋转,和角速度的物理定义完全对应。
角速度转四元数的正确方法
角速度的物理意义是瞬时旋转轴+单位时间旋转角度,因此角速度向量ω乘以时间间隔Δt得到的是旋转向量,而非欧拉角,应使用旋转向量转四元数的逻辑实现,Eigen下有两种常用实现方式:
方法1:调用Eigen内置AngleAxis构造(推荐)
该方法代码更简洁,Eigen底层已做好数值边界处理:
double delta_t = 1.0; // 时间间隔 Eigen::Vector3d omega(1, 2, 3); // 角速度向量 double rot_angle = omega.norm() * delta_t; // 小角度兜底,避免角速度为0时除以0的问题 Eigen::Vector3d rot_axis = rot_angle < 1e-6 ? Eigen::Vector3d::UnitX() : omega.normalized(); Eigen::Quaterniond delta_q(Eigen::AngleAxisd(rot_angle, rot_axis));
方法2:手动计算四元数分量
逻辑和常用的社区参考实现一致:
double delta_t = 1.0; Eigen::Vector3d omega(1, 2, 3); double omega_norm = omega.norm(); double half_theta = omega_norm * delta_t / 2.0; double w = cos(half_theta); Eigen::Vector3d v; if (omega_norm < 1e-6) { // 小角度近似,避免除以0 v = omega * delta_t / 2.0; } else { v = (omega / omega_norm) * sin(half_theta); } Eigen::Quaterniond delta_q(w, v.x(), v.y(), v.z());
以上两种方法得到的结果完全一致,是角速度转增量四元数的标准实现。
内容的提问来源于stack exchange,提问作者discipulus
相关产品推荐
相关产品推荐

