坐标系的变换(Eigen库四元数表示的坐标)

本文详述了如何利用Eigen库中的四元数进行空间坐标转换,包括从一个坐标系到另一个坐标系的旋转和平移计算,以及逆向求解的过程。通过具体示例,演示了四元数在机器人定位和姿态估计中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要介绍使用Eigen库中的四元数进行空间坐标的转换。
Eigen库的结构体对应的名称如下:
旋转矩阵(3×3) Eigen::Matrix3d
旋转向量(3×1)Eigen::AngleAxisd
欧式变换矩阵(4×4) Eigen::Isometry3d
四元数(4×1)Eigen::Quaterniond

坐标系转换如图
在这里插入图片描述

假设机器在p1处在世界坐标系下的位姿为(x,y,z,roll,pitch,yaw)=(1,1,0,0,0,0,),p2处世界坐标系下的位姿(x,y,z,roll,pitch,yaw)=(2,2,0,0 ,0,45)

1.已知p1,p2求p1 和p2之间的转换T12

此例中T12结果简单表示为(1,1,0,0,0,45)
程序如下:

#include<iostream>
#include<eigen3/Eigen/Core>
#include<eigen3/Eigen/Geometry>
int main()
{
    //1.p1 world position
    double p1yaw=0;
    double p1x=1;
    double p1y=1;
    Eigen::AngleAxisd rotzp1(p1yaw*M_PI/180, Eigen::Vector3d::UnitZ());
    Eigen::Vector3d  t1= Eigen::Vector3d(p1x,p1y, 0);
    Eigen::Quaterniond q1=Eigen::Quaterniond(rotzp1);
    //cout<<"q1.vec()"<<q1.vec()<<endl;
    cout<<"p1 eular angle in world axis"<<(180/M_PI)*q1.matrix().eulerAngles(0,1,2)<<endl;
    cout<<"p1 position in world axis"<<t1<<endl;
   //2.p2 world position
    double p2yaw=45;
    double p2x=2;
    double p2y=2;
    Eigen::AngleAxisd rotzp2(p2yaw*M_PI/180, Eigen::Vector3d::UnitZ());
    Eigen::Vector3d  t2= Eigen::Vector3d(p2x,p2y, 0);
    Eigen::Quaterniond q2=Eigen::Quaterniond(rotzp2);
    //cout<<"q1.vec()"<<q1.vec()<<endl;
    cout<<"p2 eular angle in world axis"<<(180/M_PI)*q2.matrix().eulerAngles(0,1,2)<<endl;
    cout<<"p2 position in world axis"<<t2<<endl;


    // 3.calculate T12
    //q1*q12=q2
    Eigen::Quaterniond q12=q1.inverse()*q2;
    cout<<"rotaion from p1  to p2 "<<(180/M_PI)*q12.matrix().eulerAngles(0,1,2)<<endl;

   // Eigen::Vector3d t2=t1+q1.toRotationMatrix()*t12;

    Eigen::Vector3d  t12=q1.toRotationMatrix().inverse()*(t2-t1);
    cout<<"translation base on p1 aixs t12="<<t12<<endl;
}

2已知p1和t12求p2

假设机器在p1处在世界坐标系下的位姿为(x,y,z,roll,pitch,yaw)=(1,1,0,0,0,0,),p1 和p2之间的转换(p1经过旋转和平移)为t12表示为(1,1,0,0,0,45),
求p2处世界坐标系下的位姿(x,y,z,roll,pitch,yaw)?
结果为(2,2,0,0,0,45)
程序如下:

#include<iostream>
#include<eigen3/Eigen/Core>
#include<eigen3/Eigen/Geometry>

using namespace std;
int main()
{
//    //1.p1 world position
    double p1yaw=0;
    double p1x=1;
    double p1y=1;
    Eigen::AngleAxisd rotzp1(p1yaw*M_PI/180, Eigen::Vector3d::UnitZ());
    Eigen::Vector3d  t1= Eigen::Vector3d(p1x,p1y, 0);
    Eigen::Quaterniond q1=Eigen::Quaterniond(rotzp1);
    //cout<<"q1.vec()"<<q1.vec()<<endl;
    cout<<"p1 eular angle"<<(180/M_PI)*q1.matrix().eulerAngles(0,1,2)<<endl;
    
    //2. t12 value
    double t12yaw=45;
    double t12x=1;
    double t12y=1;
    Eigen::AngleAxisd rott12(t12yaw*M_PI/180, Eigen::Vector3d::UnitZ());
    Eigen::Vector3d  t12= Eigen::Vector3d(t12x,t12y, 0);
    Eigen::Quaterniond q12=Eigen::Quaterniond(rott12);
     cout<<"t12 rotation eular angle "<<(180/M_PI)*q12.matrix().eulerAngles(0,1,2)<<endl;
  //  cout<<"q12.vec()"<<q12.vec()<<endl;
     
//    3.calculate p2 world positon
    Eigen::Quaterniond q2=q1*q12;
   // cout<<" q2 vector " <<q2.vec()<<endl;
    Eigen::Vector3d t2=t1+q1.toRotationMatrix()*t12;
    cout<<"t2="<<t2<<endl;
    cout<<"t2 eular angle "<<(180/M_PI)*q2.matrix().eulerAngles(0,1,2)<<endl;
}

参考文献
Eigen中四元数、欧拉角、旋转矩阵、旋转向量之间的转换
https://blog.csdn.net/yang__jing/article/details/82316093

### 如何使用Eigen进行坐标系旋转操作 #### 定义必要的头文件和命名空间 为了能够利用Eigen的功能,需要引入相应的头文件,并定义使用的命名空间。这一步骤确保了后续可以简洁地调用Eigen的各种功能。 ```cpp #include <iostream> #include <Eigen/Dense> using namespace std; using namespace Eigen; ``` #### 创建旋转对象 通过`AngleAxisf`类创建一个表示特定角度绕指定轴旋转的对象。这里以绕Z轴逆时针旋转90度为例说明[^1]。 ```cpp // 绕z轴旋转PI/2的角度 AngleAxisf rotation_z(M_PI / 2, Vector3f::UnitZ()); ``` #### 应用旋转至向量或坐标系 一旦有了旋转对象,就可以将其应用于任何三维向量来观察其效果。下面的例子展示了如何将上述定义好的旋转应用到一个初始位于X正方向上的单位向量上[^2]。 ```cpp Vector3f initial_vector(1, 0, 0); // 初始沿+x方向的单位向量 Vector3f rotated_vector = rotation_z * initial_vector; cout << "Rotated vector: " << rotated_vector.transpose() << endl; ``` #### 结合平移实现完整的坐标变换 除了单纯的旋转外,在实际应用场景中通常还需要考虑位置的变化。此时可以通过组合旋转和平移的方式构建更复杂的变换矩阵。对于给定的位置偏移t以及前面提到过的旋转r,可以直接相乘得到最终的结果[^4]。 ```cpp Translation<float, 3> translation(Vector3f(0.5, -0.5, 0)); // 平移部分 Transform<float, 3, Affine> transform = translation * rotation_z; Vector3f point_in_world_frame(1, 0, 0); Vector3f transformed_point = transform * point_in_world_frame; cout << "Point after transformation: " << transformed_point.transpose() << endl; ``` #### 处理四元数形式的旋转表达 有时候也会遇到需要用四元数描述姿态的情况。这时同样可以用Eigen轻松处理。假设有一个代表某次旋转的四元数q,则可通过如下方式完成相同的操作[^5]。 ```cpp Quaternionf q(sqrt(2)/2, 0, sqrt(2)/2, 0); // 表示绕y轴旋转π/2的一个四元数 Vector3f vec_before_rotation(1, 0, 0); Matrix3f m = q.toRotationMatrix(); Vector3f vec_after_rotation = m * vec_before_rotation; cout << "After quaternion-based rotation: " << vec_after_rotation.transpose() << endl; ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值