使用eigen计算空间坐标变换

使用eigen计算空间坐标变换

机器人经常涉及不同坐标系之间的坐标变换,这里总结下使用eigen来计算坐标变换的方法。

常见的描述旋转的方式:四元数、RPY(roll、pitch、yaw)、旋转矩阵、旋转向量。

先看一个二维情况下的例子:
假设坐标系1(frame_1)在世界坐标系(world_frame)下旋转为: θ θ θ,平移 t 1 = ( t 1 x , t 1 y ) t1 = (t_1x,t_1y) t1=(t1x,t1y)
一个在坐标系1下的点 p 1 = ( p 1 x , p 1 y ) p_1 = (p_1x,p_1y) p1=(p1x,p1y)在世界坐标系下的坐标由旋转+平移的变换可得:
p w = R θ ∗ p 1 + t 1 p_w = R_θ * p_1 +t_1 pw=Rθp1+t1
( p w x p w y ) \begin{pmatrix}p_wx \\ p_wy \\ \end{pmatrix} (pwxpwy) = ( c o s θ − s i n θ s i n θ c o s θ ) \begin{pmatrix}cosθ & -sinθ \\ sinθ & cosθ\\ \end{pmatrix} (cosθsinθsinθcosθ) * ( p 1 x p 1 y ) \begin{pmatrix}p_1x \\ p_1y \\ \end{pmatrix} (p1xp1y) + ( t 1 x t 1 y ) \begin{pmatrix}t_1x \\ t_1y \\ \end{pmatrix} (t1xt1y)

可以带入值进行简单的验证:
假设点p在frame_1下的坐标为(1,0),frame_1相对于世界系的旋转为90°(π/2),frame_1相对于世界系的平移为(2,2)。
( 2 3 ) \begin{pmatrix}2 \\ 3 \\ \end{pmatrix} (23) = ( 0 − 1 1 0 ) \begin{pmatrix}0 & -1 \\ 1 & 0\\ \end{pmatrix} (0110) * ( 1 0 ) \begin{pmatrix}1 \\ 0 \\ \end{pmatrix} (10) + ( 2 2 ) \begin{pmatrix}2 \\ 2 \\ \end{pmatrix} (22)

三维的情况同理,当我们用eigen使用四元数来计算:
p w = q 1 ∗ p 1 + t 1 p_w = q_1* p_1 +t_1 pw=q1p1+t1
q 1 q_1 q1是旋转矩阵对应的四元数


Eigen::Quaterniond q1 = Eigen::AngleAxisd(3.141593/2.0, Eigen::Vector3d::UnitZ()) * 
						Eigen::AngleAxisd(0.0, Eigen::Vector3d::UnitY()) * 
						Eigen::AngleAxisd(0.0, Eigen::Vector3d::UnitX());
Eigen::Vector3d t1 = Eigen::Vector3d(2, 2, 0.0);
Eigen::Vector3d p1 = Eigen::Vector3d(1, 0.0, 0.0);
Eigen::Vector3d pw;
pw = q1 * p1 + t1;

也可以用欧氏变换矩阵来计算:
p2 = q2.inverse() * (q1 * p1 + t1 - t2)
p2 = T2.inverse() * T1 * p1
[ R t 0 T 1 ] \begin{bmatrix}R & t \\ 0^T & 1\\ \end{bmatrix} [R0Tt1]
TE=[R0Tt1]TE=[Rt0T1]

  1. 旋转矩阵 RR 是正交矩阵正交矩阵;
#include <iostream>
#include <string>
#include <Eigen/Eigen>
using namespace std;
//this test show how to use eigen to compute coordinate transform
int main(int argc, char *argv[])
{
	// Eigen::Quaterniond q1 = Eigen::Quaterniond(1.0, 0.0, 0.0, 0.0).normalized();
	Eigen::Quaterniond q1 = Eigen::AngleAxisd(0.0, Eigen::Vector3d::UnitZ()) * 
							Eigen::AngleAxisd(0.0, Eigen::Vector3d::UnitY()) * 
							Eigen::AngleAxisd(0.0, Eigen::Vector3d::UnitX());
    // Eigen::Quaterniond q2 = Eigen::Quaterniond(0.92388, 0.0, 0.0, 0.382683).normalized();
	Eigen::Quaterniond q2 = Eigen::AngleAxisd(3.141593, Eigen::Vector3d::UnitZ()) * 
							Eigen::AngleAxisd(0.0, Eigen::Vector3d::UnitY()) * 
							Eigen::AngleAxisd(0.0, Eigen::Vector3d::UnitX());

    Eigen::Quaterniond q3 = Eigen::AngleAxisd(3.141593/4.0, Eigen::Vector3d::UnitZ()) * 
							Eigen::AngleAxisd(0.0, Eigen::Vector3d::UnitY()) * 
							Eigen::AngleAxisd(0.0, Eigen::Vector3d::UnitX());
    Eigen::Quaterniond qe = q1 * q2 * q3;
    Eigen::Vector3d eulerAngle_e = qe.matrix().eulerAngles(0,1,2);
    cout <<"qe: \n"<< qe.coeffs() << "\n";
    cout <<"eulerAngle_e: \n"<< eulerAngle_e.transpose() << "\n";
    
    //平移向量
    Eigen::Vector3d t1 = Eigen::Vector3d(1, 1, 0.0);
    Eigen::Vector3d t2 = Eigen::Vector3d(2, 2, 0.0);
    Eigen::Vector3d t3 = Eigen::Vector3d(2, 2, 0.0);

    Eigen::Vector3d p0 = Eigen::Vector3d(1, 0.0, 0.0);
    Eigen::Vector3d pe;
    pe = q1 * (q2 * (q3 * p0 + t3) + t2) + t1;
    cout <<"pe: \n"<< pe.transpose() << "\n";
    //目标向量
    Eigen::Vector3d p1 = Eigen::Vector3d(2, 2, 0.0);
    Eigen::Vector3d p2;
	Eigen::Vector3d pw;

    //打印输出
    cout <<"q1: \n"<< q1.coeffs() << "\n"
         <<"q2: \n"<< q2.coeffs() << "\n"
         <<"t1: \n"<< t1.transpose() << "\n"
         <<"t2: \n"<< t2.transpose() << endl;
	pw = q1 * p1 + t1;
	cout <<"pw: \n"<< pw.transpose() << endl;
	//pw = q2 * p2 + t2; => q2 * p2 + t2 = q1 * p1 + t1  =>  p2 = q2^-1*(q1 * p1 + t1 - t2)
	//四元数求解
	p2 = q2.inverse() * (q1 * p1 + t1 - t2);
	cout << "四元数求解" << endl;
    cout <<"p2: \n"<< p2.transpose() << endl;

	
	//欧拉矩阵
    Eigen::Isometry3d T1 = Eigen::Isometry3d::Identity();
    Eigen::Isometry3d T2 = Eigen::Isometry3d::Identity();
    T1.rotate(q1.toRotationMatrix());
    T1.pretranslate(t1);
    T2.rotate(q2.toRotationMatrix());
    T2.pretranslate(t2);
    // cout << T1.matrix() << endl;
    // cout << T2.matrix() << endl;

    //欧拉矩阵求解
    p2 = T2.inverse() * T1 * p1;
    cout << "欧拉矩阵求解" << endl;
	cout <<"p2: \n"<< p2.transpose() << endl;
	return 0;
}
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值