视觉SLAM十四讲笔记-- 第三讲

第三讲课后题

1、验证旋转矩阵是正交矩阵。

(1)正交矩阵
定义:设A为n阶方阵,如果 A T A = I A^TA=I ATA=I 或者 A A T = I AA^T=I AAT=I,就称A为正交矩阵
性质

  • 正交矩阵的每一个列向量都是单位向量,且向量之间两两正交。
  • 正交矩阵的行列式为1 或者 -1
  • A − 1 = A T A^{-1}=A^T A1=AT(充要条件)

(2)旋转矩阵
旋转矩阵描述了坐标系之间的旋转变换,由3 × 3 的矩阵描述。

验证思路是利用 正交矩阵的充要条件 ( A − 1 = A T A^{-1}=A^T A1=AT)来验证。

根据书中的例子设单位正交基( e 1 , e 2 , e 3 e_1, e_2,e_3 e1,e2,e3)经过一次旋转变成了( e 1 ′ , e 2 ′ , e 3 ′ e^{'}_1, e^{'}_2,e^{'}_3 e1,e2,e3),因为同一向量 a 在两个坐标系下分别为( a 1 , a 2 , a 3 a_1, a_2,a_3 a1,a2,a3),( a 1 ′ , a 2 ′ , a 3 ′ a^{'}_1, a^{'}_2,a^{'}_3 a1,a2,a3),没有发生变化,根据坐标定义,因此有:
[ e 1 e 2 e 3 ] [ a 1 a 2 a 3 ] = [ e 1 ′ e 2 ′ e 3 ′ ] [ a 1 ′ a 2 ′ a 3 ′ ] ( 式 子 1.1 ) \begin{bmatrix} e_1&e_2&e_3\end{bmatrix} \begin{bmatrix} a_1\\\\a_2\\\\a_3\end{bmatrix} =\begin{bmatrix} e^{'}_1& e^{'}_2&e^{'}_3\end{bmatrix} \begin{bmatrix} a^{'}_1\\\\a^{'}_2\\\\a^{'}_3\end{bmatrix} \color{red}(式子1.1) [e1e2e3]a1a2a3=[e1e2e3]a1a2a31.1

两边同时左乘 [ e 1 T e 2 T e 3 T ] \begin{bmatrix} e^T_1\\\\e^T_2\\\\e^T_3\end{bmatrix} e1Te2Te3T,就变成了如下:
[ e 1 T e 2 T e 3 T ] [ e 1 e 2 e 3 ] [ a 1 a 2 a 3 ] = [ e 1 T e 2 T e 3 T ] [ e 1 ′ e 2 ′ e 3 ′ ] [ a 1 ′ a 2 ′ a 3 ′ ] \begin{bmatrix} e^T_1\\\\e^T_2\\\\e^T_3\end{bmatrix} \begin{bmatrix} e_1&e_2&e_3\end{bmatrix} \begin{bmatrix} a_1\\\\a_2\\\\a_3\end{bmatrix} = \begin{bmatrix} e^T_1\\\\e^T_2\\\\e^T_3\end{bmatrix} \begin{bmatrix} e^{'}_1& e^{'}_2&e^{'}_3\end{bmatrix} \begin{bmatrix} a^{'}_1\\\\a^{'}_2\\\\a^{'}_3\end{bmatrix} e1Te2Te3T[e1e2e3]a1a2a3=e1Te2Te3T[e1e2e3]a1a2a3
左式由于基向量正交所以得到单位阵,所以式子化简如下:
a = [ a 1 a 2 a 3 ] = [ e 1 T e 1 ′ e 1 T e 2 ′ e 1 T e 3 ′ e 2 T e 1 ′ e 2 T e 2 ′ e 2 T e 3 ′ e 3 T e 1 ′ e 3 T e 2 ′ e 3 T e 3 ′ ] [ a 1 ′ a 2 ′ a 3 ′ ] = R a ′ ( 式 子 1.2 ) a=\begin{bmatrix} a_1\\\\a_2\\\\a_3\end{bmatrix} =\begin{bmatrix} e^T_1e^{'}_1 & e^T_1e^{'}_2 & e^T_1e^{'}_3 \\\\ e^T_2e^{'}_1 & e^T_2e^{'}_2 & e^T_2e^{'}_3 \\\\ e^T_3e^{'}_1 & e^T_3e^{'}_2 & e^T_3e^{'}_3 \end{bmatrix} \begin{bmatrix} a^{'}_1\\\\a^{'}_2\\\\a^{'}_3\end{bmatrix} = Ra^{'} \color{red}(式子1.2) a=a1a2a3=e1Te1e2Te1e3Te1e1Te2e2Te2e3Te2e1Te3e2Te3e3Te3a1a2a3=Ra1.2
同理,式子1.1 两边同时左乘 [ e 1 ′ T e 2 ′ T e 3 ′ T ] \begin{bmatrix} e^{'T}_1\\\\e^{'T}_2\\\\e^{'T}_3\end{bmatrix} e1Te2Te3T,就变成了如下:
[ e 1 ′ T e 2 ′ T e 3 ′ T ] [ e 1 e 2 e 3 ] [ a 1 a 2 a 3 ] = [ e 1 ′ T e 2 ′ T e 3 ′ T ] [ e 1 ′ e 2 ′ e 3 ′ ] [ a 1 ′ a 2 ′ a 3 ′ ] \begin{bmatrix} e^{'T}_1\\\\e^{'T}_2\\\\e^{'T}_3\end{bmatrix} \begin{bmatrix} e_1&e_2&e_3\end{bmatrix} \begin{bmatrix} a_1\\\\a_2\\\\a_3\end{bmatrix} = \begin{bmatrix} e^{'T}_1\\\\e^{'T}_2\\\\e^{'T}_3\end{bmatrix} \begin{bmatrix} e^{'}_1& e^{'}_2&e^{'}_3\end{bmatrix} \begin{bmatrix} a^{'}_1\\\\a^{'}_2\\\\a^{'}_3\end{bmatrix} e1Te2Te3T[e1e2e3]a1a2a3=e1Te2Te3T[e1e2e3]a1a2a3
右式由于基向量正交所以得到单位阵,所以式子化简如下:
R T = [ e 1 ′ T e 1 e 1 ′ T e 2 e 1 ′ T e 3 e 2 ′ T e 1 e 2 ′ T e 2 e 2 ′ T e 3 e 3 ′ T e 1 e 3 ′ T e 2 e 3 ′ T e 3 ] [ a 1 a 2 a 3 ] = [ a 1 ′ a 2 ′ a 3 ′ ] = a ′ R^T= \begin{bmatrix} e^{'T}_1e_1& e^{'T}_1e_2&e^{'T}_1e_3\\\\ e^{'T}_2e_1&e^{'T}_2e_2&e^{'T}_2e_3\\\\ e^{'T}_3e_1&e^{'T}_3e_2&e^{'T}_3e_3\end{bmatrix} \begin{bmatrix} a_1\\\\a_2\\\\a_3\end{bmatrix} = \begin{bmatrix} a^{'}_1\\\\a^{'}_2\\\\a^{'}_3\end{bmatrix} = a^{'} RT=e1Te1e2Te1e3Te1e1Te2e2Te2e3Te2e1Te3e2Te3e3Te3a1a2a3=a1a2a3=a
所以由 式子1.2 R T = R − 1 R^T =R^{-1} RT=R1
由正交矩阵充要条件 A − 1 = A T A^{-1}=A^T A1=AT可得,旋转矩阵就是正交矩阵。

2.*寻找罗德里格斯公式的推导过程并加以理解。

答:个人理解,就是旋转向量到旋转矩阵的转换公式。
可以参考这个博客:https://blog.csdn.net/q583956932/article/details/78933245

3.验证四元数旋转某个点后,结果是一个虚四元数(实部为零),所以仍然对应到一个三维空间点,见式(3.33)。

答:
设空间中某个虚四元数 p = [ 0 , v ] p=\begin{bmatrix} 0, v\\ \end{bmatrix} p=[0,v] ,旋转 q = [ s a , v a ] q=\begin{bmatrix} s_a, v_a\\ \end{bmatrix} q=[sa,va],由书中的各种公式:
(1)旋转公式: p ′ = q p q − 1 p^{'}=qpq^{-1} p=qpq1
(2)求逆公式: q − 1 = q ∗ / ∣ ∣ q ∣ ∣ 2 q^{-1}=q^*/||q||^2 q1=q/q2
(3)共轭公式: q ∗ = [ s , − v ] T q*=[s, -v]^T q=[s,v]T
(4)乘法法则: q a q b = [ s a s b − v a T v b , s a v b + s b v a + v a × v b ] T q_aq_b=[s_as_b-v^T_av_b, s_av_b + s_bv_a + v_a × v_b ]^T qaqb=[sasbvaTvb,savb+sbva+va×vb]T
第一步计算 : q p = [ − v a T v , s a v b + v a × v ] T qp=[-v^T_av,s_av_b + v_a × v ]^T qp=[vaTv,savb+va×v]T
第二步计算: q p q − 1 = q p q ∗ / ∣ ∣ q ∣ ∣ 2 qpq^{-1}=qpq^*/||q||^2 qpq1=qpq/q2 ,完全计算比较麻烦,现在就可以转换成计算 q p q ∗ qpq^* qpq的实部
q p q ∗ = [ − v a T v , s a v b + v a × v ] T [ s a , − v a ] T qpq^*=[-v^T_av,s_av_b + v_a × v ]^T [s_a, -v_a]^T qpq=[vaTv,savb+va×v]T[sa,va]T
实部为: − v a T v s a − [ s a v b + v a × v ] T ( − v a ) = − v a T v s a + v a T v s a + ( v a × v ) T v a = ( v a × v ) T v a -v^T_avs_a-[s_av_b + v_a × v ]^T(-v_a)=-v^T_avs_a+v^T_avs_a+(v_a × v )^Tv_a=(v_a × v)^Tv_a vaTvsa[savb+va×v]T(va)=vaTvsa+vaTvsa+(va×v)Tva=(va×v)Tva
因为 v a × v v_a × v va×v v a v_a va 垂直,因此 q p q − 1 qpq^{-1} qpq1的实部为0,为纯虚四元数。

4.画表总结旋转矩阵、轴角、欧拉角、四元数的转换关系。

答:如下表格:

旋转矩阵轴角四元数
旋转矩阵 θ = arccos ⁡ ( t r ( R ) − 1 2 ) \theta=\arccos\bigg(\tfrac{tr(R)-1}{2}\bigg) θ=arccos(2tr(R)1) 转轴n是
矩阵R特征值1对应的特征向量
q 0 = t r ( R ) + 1 2 q_0=\tfrac{\sqrt{\smash[b]{tr(R)+1}}}{2} q0=2tr(R)+1

q 1 = m 23 − m 32 4 q 0 q_1=\tfrac{m_{23} - m{32}}{4q_0} q1=4q0m23m32

q 2 = m 31 − m 13 4 q 0 q_2=\tfrac{m_{31} - m{13}}{4q_0} q2=4q0m31m13

q 3 = m 12 − m 21 4 q 0 q_3=\tfrac{m_{12} - m{21}}{4q_0} q3=4q0m12m21
轴角 R = cos ⁡ θ I + ( 1 − cos ⁡ θ ) n n T + sin ⁡ θ n ∧ R=\cos\theta\boldsymbol I+(1-\cos\theta)nn^T+\sin\theta\boldsymbol n^{\land} R=cosθI+(1cosθ)nnT+sinθn逆变换即可
四元数 R = v v T + s 2 I + 2 s v ∧ + ( v ∧ ) 2 R=vv^T+s^2I+2sv^{\land}+(v^{\land})^2 R=vvT+s2I+2sv+(v)2 θ = 2 arccos ⁡ q 0 \theta=2\arccos{q_0} θ=2arccosq0

[ n x , n y , n z ] T = [ q 1 , q 2 , q 3 ] T / sin ⁡ θ 2 [n_x, n_y, n_z]^T=[q_1, q_2, q_3]^T/\sin{ \theta \over 2 } [nx,ny,nz]T=[q1,q2,q3]T/sin2θ

5.假设有一个大的Eigen矩阵,想把它的左上角3×3的块取出来,然后赋值为 I 3 × 3 \boldsymbol I_{3 × 3} I3×3 ,请编程实现。

答:代码如下

// Eigen 几何模块
#include <Eigen/Dense>
#include <iostream>

#define Matrix_size 50

using namespace std;
using namespace Eigen;

int main ( int argc, char** argv )
{
        MatrixXd matrix_x;

        matrix_x=MatrixXd::Random(Matrix_size,Matrix_size);

        cout<<"matrix_x=\n"<<matrix_x<<endl;
        
        //方法1:直接取左上角的矩阵
        Matrix3d m;
        m=matrix_x.topLeftCorner(3,3);
        cout<<"方法1:\n"<<m<<endl;
        m=Matrix3d::Identity(3,3);
        cout<<"Matrix3d::Identity(3,3)=\n"<<m<<endl;
        //方法2:待定
        matrix_x.block<3,3>(0,0);
        cout<<"matrix_x.block=\n"<<matrix_x.block<3,3>(0,0).Identity()<<endl;
        return 0;
}

6.*一般线性方程 An =b有哪几种做法?你能在 Eigen中实现吗?

答:代码如下

#include <iostream>
#include <Eigen/Core>
#include <Eigen/Dense>

using namespace Eigen;
using namespace std;

#define Matrix_size 10


int main ( int argc, char** argv )
{
        // 动态维度的矩阵
        MatrixXd A=MatrixXd::Random(Matrix_size,Matrix_size);
        MatrixXd b=MatrixXd::Random(Matrix_size,1);
//         cout<<"A=\n"<<A<<endl;
//         cout<<"b=\n"<<b<<endl;
        
        //1:直接求逆
        Matrix<double,Matrix_size,1> x=A.inverse()*b;
        cout<<"直接求逆=\n"<<x.transpose()<<endl<<endl;

        //2:QR分解
        x=A.colPivHouseholderQr().solve(b);
        cout<<"QR分解=\n"<<x.transpose()<<endl<<endl;

        //3:LLT分解
//        x=A.llt().solve(b);//要求矩阵正定
//        cout<<x.transpose()<<endl<<endl;

        //4: LDLT分解法
//        x=A.ldlt().solve(b);//要求矩阵正或负半定
//        cout<<x.transpose()<<endl<<endl;

        //5:
        x=A.fullPivHouseholderQr().solve(b);
        cout<<"fullPivHouseholderQr=\n"<<x.transpose()<<endl<<endl;

        //6:LU分解法
        x=A.householderQr().solve(b);
        cout<<"householderQr=\n"<<x.transpose()<<endl<<endl;

        //7:partialPivLu
        x=A.partialPivLu().solve(b);
        cout<<"partialPivLu=\n"<<x.transpose()<<endl<<endl;


        return 0;
}

参考文献:
[1]. https://www.cnblogs.com/cc111/p/9240545.html
[2]. https://katex.org/docs/supported.html
[3]. https://www.cnblogs.com/cc111/p/9354924.html
[4]. https://zhuanlan.zhihu.com/p/338322663