视觉SLAM(三)李群与李代数 后续作业
第三章作业
作业:曾是少年
二 群的性质
课上我们讲解了什么是群。请根据群定义,求解以下问题:
1. \(\{Z, +\}\) 是否为群?若是,验证其满足群定义;若不是,说明理由。
答:{Z,+}是群;
对于\(\{Z,+\}\),设 \(a_1\in Z\) , \(a_2 \in Z\) , \(a_e \in Z\)。
- 对于\(\forall a_1\in Z\) , \(a_2 \in Z\), 有\(a_1+a_2\in Z\), 因此满足封闭性。
- 对于\(\forall a_1\in Z,a_2\in Z,a_3\in Z\), \((a_1+a_2)+a_3 = a_1+(a_2+a_3)\),因此满足结合律。
- Z中存在\(0\in Z\),对于\(\forall a \in Z\),有\(a+0=a\),因此慢足幺元
- 对于\(\forall a \in Z\), 存在 \(-a\in Z\),使得 \(a+(-a) = 0\),因此满足逆。
\(\{Z,+\}\)满足以上四条性质,因此是群
2. \(\{N, +\}\) 是否为群?若是,验证其满足群定义;若不是,说明理由。
其中\(Z\)为整数集,\(N\)为自然数集
答: \(\{N,+\}\) 不是群;
对于\(\forall a\in N\),且\(a\neq0\),\(-a\notin N\),不满足逆的性质要求。因此不是群。
三 验证向量叉乘的李代数性质
我们说向量和叉乘运算构成了李代数,现在请你验证它。书中对李代数的定义为:李代数由⼀个集合,V,⼀个数域 F 和⼀个⼆元运算 [, ] 组成。如果它们满足以下集几条性质,称$ (V, F, [, ])$ 为⼀个李代数,记作\(g\)。
-
封闭性 \(∀X, Y ∈ V, [X, Y ] ∈ V\).
-
双线性 \(∀X, Y , Z ∈ V, a, b ∈ F\), 有:
\[[aX + bY , Z] = a[X, Z] + b[Y , Z], [Z, aX + bY ] = a[Z, X] + b[Z, Y ]. \] -
自反性 \(∀X ∈ V, [X, X] = 0\).
-
雅可比等价 \(∀X, Y , Z ∈ V, [X, [Y , Z]] + [Y , [Z, X]] + [Z, [X, Y ]] = 0\).
其中二元运算被称为李括号。
现取集合\(V=R^3\),数域\(F=R\),李括号为:
请验证\(g=(R^3,R,\times)\)构成李代数。
验证:
- 封闭性
对于\(\forall X,Y \in R^3\),\(X \times Y\)依然是一个向量,即\(X\times Y \in R^3\),因此满足封闭性条件。
- 双线性
对于\(\forall X,Y,Z \in R^3\),\(a,b\in R\),向量叉乘运算满足分配律和线性性,因此有:
\((aX+bY)\times Z = aX\times Z+bY\times Z = a(X\times Z)+b(Y\times Z)\)
\(Z\times(aX+bY) = aZ\times X+bZ\times Y=a(Z\times X)+b(Z\times Y)\)
因此满足双线性
- 自反性
对于 \(\forall X \in R^3\),\(|X\times X| = |X||X|sin0=0\),因此\(X\times X = 0\),满足自反性。
- 雅可比等价
把三适量叉乘展开成点乘,向量的叉乘运算满足一下性质:
对于\(\forall X,Y,Z \in R^3\),
- \((X×Y)×Z=(XZ)Y-(YZ)X\)
- \(X\times(Y\times Z) = (XZ)Y-(XY)Z\)
因此
因此向量的叉乘运算满足雅可比恒等式。
综上所述,\(g=(R^3,R,\times)\)构成李代数
四 推导 SE(3) 的指数映射
课上给出了 SO(3) 的指数映射推导,但对于 SE(3),仅介绍了结论,没有给出详细推导。请你完成SE(3) 指数映射部分,有关左雅可比的详细推导。
设\(\xi = [\rho,\phi]^T\in se(3)\),它的指数映射为:
令\(\phi = \theta a\),那么:
这也正是课件里提到的左雅可比。
答:令\(\phi = \theta a\)
其中:
所以:
即:
五 伴随
在SO(3)
和SE(3)
上,有⼀个东西称为伴随(Adjoint)。下面请你证明SO(3) 伴随的性质。
对于SO(3)
,有:
此时称Ad(R) = R
。
提示:首先你需要证明\(\forall a\in R^3,Ra^{\wedge}{R^T} = (Ra)^{\wedge}\),[页面](https://math.stackexchange.com/questions/
2190603/derivation-of-adjoint-for-so3) 提示了⼀种简洁的途径。
对于SE(3),有:
其中Ad(T)
定义为:
这个性质将在后文的Pose Graph 优化中用到。但是SE(3) 的证明较为复杂,不作要求。
完整的SO(3) 和SE(3) 性质见1和2。
证明:
我们先来证明\(Ra^{\wedge}R^T=(Ra)^{\wedge}\),过程如下:·
我们可以通过使等式的RHS作用于任意向量v来证明该等式:
因此得到:
而R是正交矩阵,因此
令\(\rho=\theta a\)
证毕。
拓展:伴随表示
在数学中,一个李群 G 的伴随表示(adjoint representation)或伴随作用(adjoint action)是 G 在它自身的李代数上的自然表示。这个表示是群 G 在自身上的共轭作用的线性化形式。
六 轨迹的描绘
我们通常会记录机器人的运动轨迹,来观察它的运动是否符合预期。大部分数据集都会提供标准轨迹以供参考,如 kitti
、TUM-RGBD
等。这些文件会有各自的格式,但首先你要理解它的内容。记世界坐标系为 W
,机器⼈坐标系为 C
,那么机器人的运动可以用 \(T_{WC}\) 或 \(T_{CW}\) 来描述。现在,我们希望画出机器⼈在世界当中的运动轨迹,请回答以下问题:
-
事实上,\(T_{WC}\) 的平移部分即构成了机器人的轨迹。它的物理意义是什么?为何画出 \(T_{WC}\) 的平移部分就得到了机器⼈的轨迹?
答:物理意义: \(T_{WC}\)指的是从世界坐标系原点到相机中心的平移向量;
世界坐标系不随相机运动变化,因此可以认为\(T_{wc}\)是机器人相对于原点坐标在移动, 移动可视化在观察者眼中就是是机器人的运动轨迹
-
我为你准备了⼀个轨迹文件(code/trajectory.txt)。该文件的每⼀行由若干个数据组成,格式为
\[[t, t_x, t_y, t_z, q_x, q_y, q_z, q_w] \]其中 t 为时间,\(tx, ty, tz\) 为 \(T_{WC}\) 的平移部分,\(q_x, q_y, q_z, q_w\) 是四元数表示的 \(T_{WC}\) 的旋转部分,\(q_w\)为四元数实部。同时,我为你提供了画图程序
draw_trajectory.cpp
文件。该⽂件提供了画图部分的代码,请你完成数据读取部分的代码,然后书写CMakeLists.txt
以让此程序运行起来。注意我们需要用到Pangolin
库来画图,所以你需要事先安装Pangolin
(如果你做了第⼀次作业,那么现在已经安装了)。CMakeLists.txt
可以参照ORB-SLAM2
部分。答:实现过程:使用fstream读取文件中的数据,在编译的时候遇到一点小bug,不过都解决了.
读取数据的代码块如下:
double t,t_x,t_y,t_z,q_x,q_y,q_z,q_w; while(!inFILE.eof()) { inFILE>>t; inFILE>>t_x; inFILE>>t_y; inFILE>>t_z; inFILE>>q_x; inFILE>>q_y; inFILE>>q_z; inFILE>>q_w; poses.push_back(Sophus::SE3(Eigen::Quaterniond(q_w,q_x,q_y,q_z),Eigen::Vector3d(t_x,t_y,t_z))); }
运行结果如下所示;
该图中:轨迹首尾颜色不一样,通过观察,发现是着色函数设置的颜色随位置变化.
附加题 七 轨迹的误差
除了画出真实轨迹以外,我们经常需要把 SLAM 估计的轨迹与真实轨迹相比较。下面说明比较的原理,请你完成比较部分的代码实现。
设真实轨迹(ground-truth)为 \(T_g\),估计轨迹 \(T_e\)。它们都以 \(T_{WC}\) 的形式存储,格式同上题。现在,你需要计算估计轨迹的误差。我们假设每⼀个 \(T_g\) 都与给定的 \(T_e\) 对应。那么,对于任意第 i 个位姿,它的误差可定义为:
即两个位姿之差的李代数二范数。于是,可以定义两条轨迹的均方根(Root-Mean-Square-Error, RMSE)误差为:
我为你准备了 code/ground-truth.txt
和 code/estimate.txt
两条轨迹。请你根据上⾯公式,实现 RMSE的计算代码,给出最后的 RMSE 结果。作为验算,参考答案为:2.207。
注:
-
实际当中的轨迹比较还要更复杂⼀些。通常
ground-truth
由其他传感器记录(如 vicon),它的采样频率通常高于相机的频率,所以在处理之前还需要按照时间戳对齐。另外,由于传感器坐标系不一致致,还需要计算两个坐标系之间的差异。这件事也可以⽤ ICP 解得,我们将在后面的课程中讲到。 -
你可以用上题的画图程序将两条轨迹画在同⼀个图里,看看它们相差多少。
答:添加的代码主要包括三部分:
-
读取两个文件
ground-truth.txt
和estimate.txt
,该部分与上一题中的相同。 -
计算rmse,对于已经得到的两个pose集合,可以通过以下代码计算。
double calculateRMSE(vector<Sophus::SE3, Eigen::aligned_allocator<Sophus::SE3>> truth_poses,vector<Sophus::SE3, Eigen::aligned_allocator<Sophus::SE3>> estimated_poses) { double rmse=0.0; for(int i = 0;i<truth_poses.size();i++) { Eigen::Matrix<double ,6,1> se3; se3 = (truth_poses[i].inverse()*estimated_poses[i]).log(); //这里是通过一个把其中一个变换乘以一个逆变换得到一个差矩阵,再通过.log()可以转换为向量形式 rmse+=se3.squaredNorm(); } rmse = sqrt(rmse/(double)truth_poses.size()); return rmse; }
-
画图,修改轨迹绘制代码,函数部分代码如下所示:
while (pangolin::ShouldQuit() == false) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); d_cam.Activate(s_cam); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glLineWidth(2); for (size_t i = 0; i < truth_poses.size() - 1; i++) { glColor3f(1.0f, 0.0f, 0.0f); glBegin(GL_LINES); auto p1 = truth_poses[i], p2 = truth_poses[i + 1]; glVertex3d(p1.translation()[0], p1.translation()[1], p1.translation()[2]); glVertex3d(p2.translation()[0], p2.translation()[1], p2.translation()[2]); glEnd(); glColor3f(0.0f, 0.0f, 1.0f); glBegin(GL_LINES); p1 = estimated_poses[i], p2 = estimated_poses[i + 1]; glVertex3d(p1.translation()[0], p1.translation()[1], p1.translation()[2]); glVertex3d(p2.translation()[0], p2.translation()[1], p2.translation()[2]); glEnd(); } pangolin::FinishFrame(); usleep(5000); // sleep 5 ms }
最后运行结果如下:
/home/guoben/Project/SLAM-homework/ch3/draw_trajectory/bin/drawtraj rmse:2.20727
其中,红色轨迹表示真值,蓝色轨迹表示估计值