SLAM练习题(四)——三维空间刚体旋转

从零手写SLAM笔记

旋转方式转化

题目1:已知旋转矩阵定义是沿着Z轴旋转45°。请按照该定义初始化旋转向量、旋转矩阵、四元数、欧拉角。请编程实现:

1、以上四种表达方式的相互转换关系并输出,并参考给出的结果验证是否正确。

2、假设平移向量为(1,2,3),请输出旋转矩阵和该平移矩阵构成的欧式变换矩阵,并根据欧式变换矩阵提取旋转向量及平移向量。
**知识点:**1、学习eigen中刚体旋转的四种表达方式,熟悉他们之间的相互转换关系 2、熟悉旋转平移和欧式变换矩阵的相互转换关系

四种旋转方式的初始化:

    // 初始化

    // 旋转向量(轴角):沿z轴旋转45°
    Eigen::AngleAxisd rotation_vector(M_PI/4, Eigen::Vector3d(0,0,1));
    cout<<"rotation_vector axis=\n"<<rotation_vector.axis()<<endl;
    cout<<"rotation_vector angles\n"<<rotation_vector.angle()<<endl;

    // 旋转矩阵: 沿z轴旋转45°
    Eigen::Matrix3d rotation_matrix = Eigen::Matrix3d::Identity();
    rotation_matrix<<
        0.707, -0.707, 0,
        0.707,  0.707, 0,
        0,      0,     1;
    cout<<"rotation matrix=\n"<<rotation_matrix<<endl;

    // 四元数: 沿z轴旋转45度
    Eigen::Quaterniond quat = Eigen::Quaterniond(0,0,0.383,0.924);  // 赋值方式为(w,x,y,z)
    cout<<"四元数输出方式1:quaternion=\n"<<quat.coeffs()<<endl;    // 输出方式为(x,y,z,w)
    cout<<"四元数输出方式2:\tw="<<quat.w()<<"\tx="<<quat.x()
        <<"\ty="<<quat.y()<<"\tz="<<quat.z()<<endl;
    
    // 欧拉角: 沿z轴旋转45°
    Eigen::Vector3d euler_angles = Eigen::Vector3d(M_PI/4,0,0);// zyx顺序即yaw pitch roll顺序
    cout<<"Euler:yaw pitch roll="<<euler_angles.transpose()<<endl;

旋转矩阵,四元数,旋转向量的相互转化:

在这里插入图片描述

仔细品一下可以看到,旋转向量和四元数转化为旋转矩阵,Eigen提供了两种函数:toRotationMatrix() 和 Matrix()。

对于旋转矩阵转化为旋转向量,Eigen提供了fromRotationMatrix()。

其余两者转换可以通过eg: V=R or V®两种方式进行赋值。

	// 相互转换关系
    
    // 旋转向量转化为其他形式
    cout<<"旋转向量转化为旋转矩阵方法1:rotation matrix=\n"<<
        rotation_vector.toRotationMatrix()<<endl;
    cout<<"旋转向量转化为旋转矩阵方法2:rotation matrix=\n"<<
        rotation_vector.matrix();
    quat = rotation_vector;
    cout<<"旋转向量转化为四元数:quaternion=\n"<<quat.coeffs()<<endl;

    // 旋转矩阵转换为其他形式
    cout<<"旋转矩阵转换为旋转向量:rotation_vector axis=\n"<<
    rotation_vector.fromRotationMatrix(rotation_matrix).axis()<<
    "\n rotation_vector angle = "<<rotation_vector.fromRotationMatrix(rotation_matrix).angle()<<endl;
    // fromRotationMatrix 参数只适用于旋转向量,不适用于四元数

    rotation_vector = rotation_matrix;
    cout<<"旋转矩阵直接给旋转向量赋值初始化: rotation_vector angle= \n"<<rotation_vector.angle()<<endl;
    cout<<"rotation_vector axis=\n"<<rotation_vector.axis()<<endl;

    euler_angles = rotation_matrix.eulerAngles(2,1,0); //难点 z y x 
    cout<<"旋转矩阵转化为欧拉角: yaw pitch roll="<<euler_angles.transpose()<<endl;
    quat = rotation_matrix;
    cout<<"旋转矩阵转化为四元数:quaternion=\n"<<quat.coeffs()<<endl;

    // 四元数转换为其他形式
    rotation_vector = quat;
    cout<<"四元数转化为旋转向量:rotation_vector axis=\n"<<rotation_vector.axis()
        <<"rotation_vector angle=\n"<<rotation_vector.angle()<<endl;
    
    rotation_matrix = quat.toRotationMatrix();
    cout<<"四元数转换为旋转矩阵方法1:rotation matrix=\n"<<rotation_matrix<<endl;

    rotation_matrix = quat.matrix();
    cout<<"四元数转化为旋转矩阵方法2:rotation matrix=\n"<<rotation_matrix<<endl;

特别注意旋转矩阵转化为欧拉角:

euler_angles = rotation_matrix.eulerAngles(2,1,0); //难点 z y x 

参数2 1 0表示按z y x 也就是按yaw ,pitch,roll的顺序表示欧拉角

欧式变换矩阵:

// 欧式变换矩阵使用Eigen::Isometry ,仿射变换用Eigen::Affine3d, 射影变换用Eigen::Projective3d
    Eigen::Isometry3d T = Eigen::Isometry3d::Identity();    // 初始化
    T.rotate(rotation_vector);
    Eigen::Vector3d v1 = Eigen::Vector3d(1,2,3);
    T.pretranslate(v1);

    cout<<"Transform matrix = \n"<<T.matrix()<<endl;
    cout<<"rotation matrix of T is :\n"<<T.rotation()<<endl;
    cout<<"translation of T is :\n"<<T.translation()<<endl;

注意到初始化T的旋转部分的函数是rotate(),而输出T的旋转部分函数是rotation()。

对于函数命名的感悟:似乎函数赋值这类的函数名字一般用动词,而输出已有的成员的时候用名词。这样做确实更加符合逻辑。

讨论

(参考星球讨论)
问:

  1. 在旋转矩阵直接转换成欧拉角代码里rotation_matrix.eulerAngles(2.1.0)这里的2,1,0代表什么意思?

答:分别是代表不同的坐标轴 :代码中注释是rotation_matrix.eulerAngles(2, 1, 0); // ZYX顺序,即roll pitch
yaw顺序。查一下eigen官网,看如下链接Eigen: Geometry module发现了 Each of the three parameters a0,a1,a2
represents the respective rotation axis as an integer in {0,1,2}. For instance, in:Vector3f ea = mat.eulerAngles(2, 0, 2); “2” represents the z axis and “0” the x axis, etc.

  1. 欧氏变换矩阵使用代码里T.rotate()这个括号里是不是可以选择另一种方式旋转?

答:是的,具体支持的类型也是要去看定义,在这里Eigen: Eigen::Transform< _Scalar, _Dim, _Mode, _Op…可以看
支持我们所有的旋转类型

提示:遇到不懂函数可以去查找定义,要多看多写代码。

:旋转矩阵的计算方法:

在这里插入图片描述

rot(x, θ) 表示绕X轴旋转 θ表示旋转的角度 其它同理。矩阵右下角的表示放大倍数,矩阵第4行和第4列可以不要

四元数

题目:单位四元数q可以表达旋转。一个三维空间点可以用虚四元数p表示,用四元数 q 旋转点 p 的结果p’为:
p ′ = q p q − 1 p'=qpq^{-1} p=qpq1,证明:此时 p′ 必定为虚四元数(实部为零)。
知识点:四元数
参考答案:《视觉SLAM十四讲》P55页留题


q = [ s , v a ] , p = [ 0 , v b ] q=[s,v_a] , p=[0,v_b ] q=[s,va],p=[0,vb]
根据四元数的逆
q − 1 = q ∗ ∣ ∣ q ∣ ∣ 2 = 1 ∣ ∣ q ∣ ∣ 2 [ s , − v a ] \mathbf q^{-1}= \frac{q*}{||q||^2} = \frac{1}{||q||^2}[s,-v_a] q1=q2q=q21[s,va]
根据四元数乘法
q p = [ − v a T v b , s v b + v a × v b ] qp=[-v_a^Tv_b, sv_b+v_a×v_b] qp=[vaTvb,svb+va×vb]
再计算 q p q − 1 qpq^{-1} qpq1,利用四元数乘法公式,得其实部:
1 ∥ q ∥ 2 ( − v a T v b s + ( s v b + v a × v b ) T v a ) = 1 ∥ q ∥ 2 ( − v a T v b s + s v b T v a + ( v a × v b ) T v a ) = 0 \begin{aligned} & \frac{1}{\|q\|^{2}}\left(-v_{a}^{T} v_{b} s+\left(s v_{b}+v_{a} \times v_{b}\right)^{T} v_{a}\right) \\ =& \frac{1}{\|q\|^{2}}\left(-v_{a}^{T} v_{b} s+s v_{b}^{T} v_{a}+\left(v_{a} \times v_{b}\right)^{T} v_{a}\right) \\ =& 0 \end{aligned} ==q21(vaTvbs+(svb+va×vb)Tva)q21(vaTvbs+svbTva+(va×vb)Tva)0

得证,p’必为虚四元数。

参考:
视觉SLAM十四讲
从零开始一起学习SLAM | 三维空间刚体的旋转

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛定猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值