ch3 eigen
3.1 理论
3.1.1 旋转方法
这讲没太多说的,主要是介绍了三种旋转形式:旋转矩阵;四元数;欧拉角。
四元数可以看作是向量角的一种表现形式,它的冗余度比旋转矩阵好点,同时没有欧拉角的万向节锁问题,所以还是很常用的。
注意:万向节锁问题最大的痛点其实是从万向节锁的状态转到下一个状态时,会产生一条无法预料的曲线轨迹,这是我们不希望出现的。同时,万向节锁简单来说就是无论按什么顺序旋转,第二个旋转的角度为90度,第一个旋转和第三个旋转将是绕同一个轴旋转,也就是丢失了一个自由度。
旋转矩阵都是标准正交矩阵,否则就不是欧式变换。
3.1.2 反对称矩阵符号
两个向量叉乘axb可以表示为a的反对称矩阵乘b,记作a^b。
a^ = [0,-a3,a2 ; a3 0 -a1 ; -a2 a1 0]
3.1.3 其他类型的变换
相似变换:他就只是正交阵了,R被替换为sR,也就是转换后的目标和原目标相似,也就是角度一样,比例一样,但是尺寸可能有变化。自由度7.
仿射变换:R被替换为可逆阵A,也就是说不仅尺寸可能变化,角度也可能变化了,但是平行关系仍然保持不变。自由度12.
射影变换:形式为[A, t ;a^T , v],也就是平行关系也被打破了,只剩下相交/相切关系得到保存。自由度15.
3.2 代码
eigen库。引用部分必备 Eigen/Core;涉及到定义矩阵,向量,四元数等数据结构,用 Eigen/Dense,定义的数据结构有很多方法,比如矩阵都能一键求特征值,求逆等;然后是方法库Eigen/Geometry,集成了一系列方法,用于矩阵运算,方程组求解等
注意:Eigen不同类型的矩阵无法直接运算,如matrix3d和matrix3f运算之前要先类型转换。
ch4 李群与李代数 sophus
4.1 基础知识
4.1.1 李群
群的四个特征:封结幺逆。
在这里最重要的两个李群:SO(3)和SE(3)分别对应着旋转矩阵R和T,也就是R和T有上述四个性质。
注意:上述两个矩阵只有乘法连续性而没有加法连续性,因此用定义式(f(x)-f(x+△x))/(△x)求导时,不能直接用李群,因为定义式要求x到x+△x区间内要连续,这就存在问题了。
4.1.2 李代数
李代数提出的目的是为了解决李群求导的问题。只看so(3),se(3)六维的太麻烦懒得看。
定义:三维向量(t)有^
结论:R= exp(^) ,李括号[
4.1.3 BCH公式的近似
书上P82,懒得抄了。核心思想是两个矩阵的指数的乘积,在其中一个矩阵较小时,可以做一个近似板换,让乘法能够通过一定的变换近似转换为加法,为求导打好基础
4.1.4 矩阵指数求导
P83,重点还是解决x+△x那项。
4.1.5 李代数求导模型
它应用于什么呢,比如一个旋转后p' = RP,然后想知道R对p'的影响,所以暂时记作求偏导的格式。详见P84。
4.1.6 扰动求导模型
P85,结果比李代数求导模型更简单,少算了一个雅可比阵,所以更常用
4.2代码 sophus库
可以看作是eigen的DLC包,主要就是有SE3和SO3两个群,他们的李代数直接用eigen的vector3d和vector6d(6x1矩阵,自己typedef)表示即可。需要注意的是,这两个群不能直接打印,要调用自带的.matrix()方法。
ch5 相机内外参
就相机的内参和外参,没什么好讲的,单目就fx fy cx cy T,双目就b f d(r_L - r_R)
代码的话介绍了一下cv库,看完以后起码会看图读图吧,和python版cv库差不多;反而是那个boost库,感觉解决了c++笨重的问题,boost::format 能够拼字批量完成命名或读文件
boost::format fmt(规则);(fmt%参数1%参数2% ...).str();
ch6状态估计(位姿)
6.1.1 最大后验估计 MAP
x_map = argmax P(z|x)P(x)
其中x是先验信息,可以看做是上一时刻的位姿;z是观测信息,视觉slam里,它就是新收到的一张图片。
6.1.2 最大似然估计 MLE
x_mle = argmax P(z|x)
这个简单且精度姑且够用,所以常用它。
6.1.3 最小二乘问题
我们最终的目的是为了让观测值尽可能贴近实际值,也就是让其差值最小,则可以转为问题:
argmin((x_k - f(x_k-1,u_k))^T · R^-1 · (x_k - f(x_k-1,u_k)))
求解步骤:给定一个初值x0,如果没有先验信息(经验值)那就随机给定一个符合要求的值;然后开始迭代,每次都给一个小变化△xk,让f的模达到局部极小值(贪心算法),这样迭代n次以后,没有符合要求的△x了,或者△x小于某个阈值。
注意:实际编码中,高斯牛顿法的最终结果可能不收敛;dogleg和lm法不会出现这种问题,可能是因为g-n没有设置有效区间吧。
6.2 代码 ceres&g2o
注意:
·最新版g2o甚至只能用c++ 17编译,且g2o::make_unique()不存在,需要改为std::make_unique。
·ceres文档更多,学起来更方便;g2o和slam关系更强,相关库更多。
CH7 特征点法
主要讲ORB,他是用oriented fast+steer brief,其中给角点加方向是用“灰度中心”描述的,并且这种方法提取特征点容易让特征点聚堆(可以想象一下,如果是一个尖尖,那么属于这个尖尖的所有像素都满足fast条件,但这意义不大),所以需要非极大值抑制。