PCL 轴角转四元数

发布于:2025-06-24 ⋅ 阅读:(18) ⋅ 点赞:(0)

在这里插入图片描述

一、算法原理

1、概述

   已知旋转轴 u = ( u x , u y , u z ) \mathbf{u} = (u_x, u_y, u_z) u=(ux,uy,uz)(单位向量)和旋转角度 θ \theta θ,根据四元数旋转原理, 轴角到对应的四元数 q = ( w , x , y , z ) q = (w, x, y, z) q=(w,x,y,z)的转换公式为:

q = cos ⁡ ( θ 2 ) + sin ⁡ ( θ 2 ) ( u x i + u y j + u z k ) (1) q = \cos\left(\frac{\theta}{2}\right) + \sin\left(\frac{\theta}{2}\right)(u_x\mathbf{i} + u_y\mathbf{j} + u_z\mathbf{k}) \tag{1} q=cos(2θ)+sin(2θ)(uxi+uyj+uzk)(1)

式(1)展开后得到四元数的四个分量:
{ w = cos ⁡ ( θ 2 ) x = u x sin ⁡ ( θ 2 ) y = u y sin ⁡ ( θ 2 ) z = u z sin ⁡ ( θ 2 ) (2) \begin{cases} w = \cos\left(\dfrac{\theta}{2}\right) \\ x = u_x \sin\left(\dfrac{\theta}{2}\right) \\ y = u_y \sin\left(\dfrac{\theta}{2}\right) \\ z = u_z \sin\left(\dfrac{\theta}{2}\right) \end{cases} \tag{2} w=cos(2θ)x=uxsin(2θ)y=uysin(2θ)z=uzsin(2θ)(2)

可得四元数分量的模长为1:
∥ q ∥ 2 = w 2 + x 2 + y 2 + z 2 = cos ⁡ 2 ( θ 2 ) + sin ⁡ 2 ( θ 2 ) ( u x 2 + u y 2 + u z 2 ) = cos ⁡ 2 ( θ 2 ) + sin ⁡ 2 ( θ 2 ) ⋅ 1 = 1 (3) \begin{align*} \|q\|^2 &= w^2 + x^2 + y^2 + z^2 \\ &= \cos^2\left(\frac{\theta}{2}\right) + \sin^2\left(\frac{\theta}{2}\right)(u_x^2 + u_y^2 + u_z^2) \\ &= \cos^2\left(\frac{\theta}{2}\right) + \sin^2\left(\frac{\theta}{2}\right) \cdot 1 \\ &= 1 \end{align*} \tag{3} q2=w2+x2+y2+z2=cos2(2θ)+sin2(2θ)(ux2+uy2+uz2)=cos2(2θ)+sin2(2θ)1=1(3)

   其中, w w w 为四元数的实部,表示旋转角度的一半; ( x , y , z ) (x,y,z) (x,y,z) 为虚部表示旋转轴的方向;当 θ = 0 \theta=0 θ=0 时, q = ( 1 , 0 , 0 , 0 ) q=(1,0,0,0) q=(1,0,0,0) 表示无旋转。

2、注意事项

⚠️ 注意事项

  1. 奇异值处理:当 ∥ u ∥ < ϵ \|\mathbf{u}\| < \epsilon u<ϵ 时返回单位四元数
  2. 连续性:当 θ \theta θ 2 π − 2\pi^- 2π 0 + 0^+ 0+ 时,四元数 w w w 分量需保持连续
  3. 性能优化:在实时系统中可预先计算 sin ⁡ / cos ⁡ \sin/\cos sin/cos 半角值

二、代码实现

#include <pcl/common/eigen.h>
#include <Eigen/Geometry>

Eigen::Quaternionf axisAngleToQuaternion(const Eigen::Vector3f& axis, float angle_rad) 
{
    // 确保旋转轴是单位向量
    Eigen::Vector3f normalized_axis = axis.normalized();
    
    // 计算半角三角函数值
    float half_angle = angle_rad / 2.0f;
    float cos_half = std::cos(half_angle);
    float sin_half = std::sin(half_angle);
    
    // 构造四元数 (w, x, y, z)
    return Eigen::Quaternionf(
        cos_half, 
        sin_half * normalized_axis.x(),
        sin_half * normalized_axis.y(),
        sin_half * normalized_axis.z()
    ).normalized(); // 最终归一化确保精度
}

// 示例使用
int main() 
{
    // 定义绕Y轴旋转45°
    Eigen::Vector3f axis(0, 1, 0);
    float angle_deg = 45.0f;
    float angle_rad = angle_deg * M_PI / 180.0f;
    
    Eigen::Quaternionf q = axisAngleToQuaternion(axis, angle_rad);
    
    std::cout << "Resulting quaternion: (w,x,y,z) = ("
              << q.w() << ", " << q.x() << ", " 
              << q.y() << ", " << q.z() << ")" << std::endl;
    return 0;
}

关键说明

  1. 轴归一化:必须显式归一化输入旋转轴,防止非单位向量导致错误
  2. 角度单位:输入角度需为弧度制,如使用度数需转换(deg * π/180
  3. 数值稳定性:当 θ ≈ 0 \theta \approx 0 θ0 时,直接返回单位四元数 ( 1 , 0 , 0 , 0 ) (1,0,0,0) (1,0,0,0)
  4. 四元数归一化:最终调用.normalized()消除浮点计算误差

三、结果展示

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到