ORBSLAM2的运动估计简介

  ORBSLAM2中的运动估计核心方法就是3D-2D的PNP,而在跟踪过程主要分为三种类型:

  1. 无运动模型的跟踪,即基于参考帧的跟踪;
  2. 基于匀速运动模型的跟踪;
  3. 重定位;

  上述三种方案,我们只介绍前两种,重定位由于需要用到回环检测,我们会在之后讲解。


PNP运动估计

  在介绍ORBSLAM2的跟踪策略之前,我们先了解一下他所用的运动估计方法——PNP。

  PNP是一种将匹配点从三维空间投影到像平面并与观测数据计算误差来估计相机运动的方法,我们也管这种方法叫重投影误差。基于解析的PNP方法只采用了少量的匹配对即可估计相对运动,然而,在SLAM问题当中,通常约束条件较多,因此基于解析的方法通常不能更好地利用约束条件。另外,若将错误匹配对纳入解析方程中,会错误估计相机运动。尽管可以通过随机选取多组匹配对进行估算多个相机运动并根据一定条件进行筛选出最合适的相机运动,但是笔者更倾向于用PNP解析解估算出一个初值,随后通过非线性优化的方法来优化相机运动。不过,值得一提的是,ORBSLAM2并不用PNP求初值,而是直接用参考帧的运动作为当前帧的运动初值进行优化。因此,本文只介绍基于非线性优化的PNP方法。

  与之前一样,为了让大家更直观的看到问题的描述,笔者为大家提供了一个图:

                                                      

  其中,空间点 $P$ 齐次坐标为 $P=[X,Y,Z,1]^{T}$,其在图像 $I_1$ 中投影的像素坐标为 $p_1=[u_1,v_1]^{T}$,在图像 $I_2$ 中的重投影像素坐标为 $p_2^{'}=[u_2^{'},v_2^{'}]^{T}$,而空间点 $P$ 在图像 $I_2$ 中的观测值为 $p_2=[u_2,v_2]^{T}$ ,$e=p_2-p_2^{'}$ 表示重投影误差。

  图中的理想重投影过程用公式$(1)$表达如下:

  \begin{equation}
    s_2u_2=Kexp(\xi^{\land})P
  \end{equation}

  其中,$s_2$ 表示空间点 $P$ 在图像 $I_2$ 所在相机坐标系的深度。$K$ 表示相机内参数,$exp( \xi^{\land} )$ 表示相机从图像 $I_1$ 到图像 $I_2$ 的姿态变换阵,也可以用 $T$ 表示,$\xi$ 表示 $T$ 对应的李代数。  

  然而,由于相机姿态初值估计不够好,因此重投影时通常会与真实值存在一定的误差,这个误差我们定义如下:

  \begin{equation}
    e_2 = u_2 - \frac{1}{s_2}Kexp(\xi^{\land})P
  \end{equation}

  一个相机姿态下观测到的特征点通常不止一个,假设我们有 $N$ 个特征点,则构成求相机姿态 $\xi$ 的最小二乘问题:
  \begin{equation}
    \xi^{\ast} = \mathop{\arg\min}_{\xi}\frac{1}{2}\sum_{i=1}^{N}\left\|e_i\right\|_2^{2} = \mathop{\arg\min}_{\xi}\frac{1}{2}\sum_{i=1}^{N}\left\|u_i - \frac{1}{s_i}Kexp(\xi^{\land})P_i\right\|_2^{2}
  \end{equation}

  为了满足所有重投影误差最小,我们通过不断调整$\xi$的值,使得上述误差不断下降,最终得到一个对当前匹配对最优的相机姿态。但是 $\xi$ 应该怎么调整?我们知道最小二乘优化是通过不断调整增量,使得整体的误差不断下降,直到收敛的过程。在这个过程中,我们需要选择增量的方向和步长。根据优化理论知识我们可知,求出误差相对于位姿的雅克比,这个优化问题我们基本上就算解决了。如果用了牛顿法,我们还需要再求个海塞阵,但通常我们都会用高斯牛顿法来替代牛顿法,避免计算海塞阵。
  通过链式法则,我们可以求出误差相对于位姿的雅克比:
  \begin{equation}
    \frac{\partial e}{\partial \delta\xi}=\frac{\partial e }{\partial P^{'}}\frac{\partial P^{'}}{\partial\delta\xi}
  \end{equation}

  其中,$P^{'}$ 表示 $P$ 位于图像 $I_2$ 处的相机坐标系下的坐标。
  上述雅克比为:
  \begin{equation}
    \frac{\partial e}{\partial \delta\xi} = -{\left[ \begin{array}{cccccc}\frac{f_{x}}{Z^{'}} & 0 & -\frac{f_{x}X^{'}}{Z^{'2}} & -\frac{f_{x}X^{'}Y^{'}}{Z^{'2}} & f_{x}+\frac{f_{x}X^{'2}}{Z^{'2}} & -\frac{f_{x}Y^{'}}{Z^{'}} \\
0 & \frac{f_{y}}{Z^{'}} & -\frac{f_{y}Y^{'}}{Z^{'2}} & -f_{y}-\frac{f_{y}Y^{'2}}{Z^{'2}} & \frac{f_{y}X^{'}Y^{'}}{Z^{'2}} & \frac{f_{y}X^{'}}{Z^{'}}  \end{array} \right]}
  \end{equation}
  得到雅克比以后我们就可以通过g2o或者ceres来求解公式 $(3)$ 的最小二乘问题了。(具体源码,之后笔者会更新在github上,并将在此附上链接)

  那么,到这里,基于非线性优化的PNP方法就差不多介绍完了。如果我们公式 $(3)$ 拓展一下,将参考帧的位姿和所有共同观测点作为优化变量加入优化函数中,我们就得到了完整的bundle adjustment,可以同时优化两个姿态和三维空间点。

  对基于PNP解析方法比较感兴趣的同学可以参考:

  涂金戈同学的博客:https://www.cnblogs.com/JingeTU/p/10646322.html ;

  或者参考高翔博士的《视觉SLAM十四讲》。

  --------------------------------------------------------------

  稍微加个插曲:

  在优化算法上,笔者根据自己的理解写出部分优化算法的优缺点(这也是视觉SLAM十四讲中的课后思考题):

  实际上,由于梯度下降法过于贪心,通常会导致锯齿状下降,导致收敛速度缓慢;

  而牛顿法尽管使用了二阶近似,提高了下降速度,但对于SLAM问题而言,求解海塞阵的计算量太大,非常不适用;

  基于牛顿法改进的高斯牛顿法,通过二次近似二阶泰勒展开,利用雅克比的二次方 $J^{T}J$ 来近似海塞阵,在计算量和下降速度上可以较好满足SLAM的需求,但存在的隐患是增量的范围超出泰勒展开时限定的微小邻域,导致近似失败;

  列文伯格-马夸尔特法是基于高斯牛顿法进一步改进的,通过限定搜索区域,防止出现近似失败的情况,LM方法也是SLAM中最常用的优化方法。


 基于参考帧的跟踪

  当没有运动模型时,ORBSLAM2采用跟踪参考帧的方式估计相机的相对运动。

  在ORBSLAM2中,参考关键帧的大部分特征点在地图中都有对应三维点。输入当前帧后,通过上一讲所介绍的特征匹配后,我们确定了当前帧和参考关键帧之间的二维特征匹配关系。已知参考关键帧特征点对应的地图三维点,我们很容易就可以得到匹配的三维空间点与当前帧特征点的对应关系。即我们有多对匹配的3D-2D点,于是我们很容易想到利用前面我们介绍的PNP方法来优化位姿。

  在前面我们提到过,ORBSLAM2并没有用解析解的方法求解一个相机位姿作为初值。在基于参考帧的跟踪中,ORBSLAM2用上一帧的相机姿态作为初值进行迭代优化。在优化阶段,有一些细节需要稍微注意一下:

  1. 初始化阶段,设置当前帧相机位姿作为节点。空间三维点都只作为观测信息,在此阶段不对空间三维点进行优化;

  2. 优化过程循环了4次,前两次优化调用了鲁棒核,防止误差值太过发散,更主要的原因是抑制错误匹配对的影响。后两次关闭了鲁棒核,认为前两次的优化基本上抑制了错误匹配的影响。每次优化迭代诗词;

  3. 每次优化结束后,根据预设误差阈值判断每一个特征点是内点还是外点。

  优化结束后,根据判断条件,将所有匹配的外点全部删除,统计内点(观测次数大于0)数量。若内点数量大于10,则认为跟踪成功,否则跟踪失败。


基于匀速运动模型的跟踪

  ORBSLAM2中每次跟踪成功后,都会将两帧间的相对运动记录下来作为运动模型。在估计下一帧运动时,将前一帧的姿态,乘上这个运动模型,就得到了当前帧的姿态初值。能用公式的地方,我们坚决不含糊,毕竟数学公式是没有歧义性的,因此先上公式:

  假设前一帧的相机姿态是 $T_{lw}$ ,表示从世界坐标系到前一帧相机坐标系的相对变换。运动模型为 $T_{cl}$ ,表示从前一帧到当前帧的相对变换。则当前帧的相机姿态初值可以描述为:

  \begin{equation}
    T_{cw} = T_{cl}T_{lw}
  \end{equation}

  确定了姿态初值,我们还需要查找匹配对。由于我们根据前一帧的相机姿态加上运动模型得到了当前帧的姿态,所以我们在需要在前一帧中查找匹配对。

  查找匹配对的方法非常有意思,有很值得大家借鉴:

  1. 从相机姿态中取出前一帧和当前帧对应的旋转和位移;

  2. 逐个取出前一帧特征点 $f_{i}$ 对应的地图点 $pM_{i}$,并将其投影到当前帧的像平面中;

  3. 根据设置的搜索区域阈值,确定搜索窗口半径 $r$;

  4. 获取当前帧中处于搜索窗口区域的所有候选特征点 $\left\{ f_{c}^{1}, f_{c}^{2}, \dots, f_{c}^{m}\right\}$;

  5. 将前一帧的特征点 $f_{i}$ 与上述所有候选特征点进行匹配,并根据阈值条件筛选最优匹配;

  6. 同样统计匹配对的特征主方向角度差值,取数量最多的前三个角度区间对应的匹配对作为最终匹配对;

  7. 若匹配对数量低于20,扩大搜索区域,重复步骤4-6,若仍然小于20,则跟踪失败。

  除了上述姿态初值的选择方式和匹配对的选择方式不同之外,两种跟踪方法在优化相机位姿时采用的步骤是一致的。因此,优化的方法就不再赘述了。(后续笔者会实现这部分功能,届时会将源码公布在github上,并在此提供源码链接)


总结:

  本文主要介绍了ORBSLAM2中的跟踪方案:

    涉及的运动估计方法主要是PNP,因此我们详细介绍了利用非线性优化的PNP方法;

    此外,我们还分析了两种跟踪方案的不同特点,大家可以根据实际需要选择跟踪方案,亦或是像ORBSLAM2一样,二者结合。

  另外,由于本文中已经涉及了PNP的非线性优化方法,局部优化我们就不单独写一讲了,详细的优化内容在本文中查看。之后介绍闭环时,我们也会细致地分析相关优化内容。

  局部优化我们通过扩大关键帧的数目,将当前帧关联的所有关键帧以及对应的所有观测点全部包含进来优化问题中,构成了更大的优化问题。利用同样的优化策略,我们就实现了局部的优化,防止相机姿态随着时间变化而漂移。  

  下一讲,笔者将为大家介绍前端中一个很重要的模块:关键帧的筛选和插入。

参考文献:

  [1] 视觉SLAM十四讲

  [2] 机器人学中的状态估计

PS:

  如果您觉得我的博客对您有所帮助,欢迎关注我的博客。此外,欢迎转载我的文章,但请注明出处链接。

  对本文有任何问题可以在留言区进行评论,也可以在泡泡机器人论坛:http://paopaorobot.org/bbs/index.php?c=cate&fid=1中的SLAM技术交流模块发帖提问。

  我的github链接是:https://github.com/yepeichu123/orbslam2_learn

(四)ORBSLAM运动估计的更多相关文章

  1. ORB-SLAM (四)Initializer单目初始化

    一. 通过对极约束并行计算F和H矩阵初始化 VO初始化目的是为了获得准确的帧间相对位姿,并通过三角化恢复出初始地图点.初始化方法要求适用于不同的场景(特别是平面场景),并且不要进行人为的干涉,例如选取 ...

  2. ORB-SLAM 代码笔记(四)tracking代码结构

    首先要清楚ORB-SLAM视觉跟踪的原理,然后对tracking.cc中的函数逐个讲解 代码的前面部分是从配置文件中读取校准好的相机参数(内参和畸变参数,以及双目的深度测量设定),并且加载ORB特征点 ...

  3. ORB-SLAM(四)追踪

    最近在读ORB-SLAM的代码,虽然代码注释算比较多了,但各种类和变量互相引用,看起来有点痛苦.索性总结了一下Tracking部分的代码结构,希望能抓住主要思路,不掉坑里. 追踪 追踪部分的主要思路是 ...

  4. ORB-SLAM (四)tracking跟踪解析

    初始化完成后,对于相机获取当前图像mCurrentFrame,通过跟踪匹配上一帧mLastFrame特征点的方式,可以获取一个相机位姿的初始值:为了兼顾计算量和跟踪鲁棒性,处理了三种模型: 1. Tr ...

  5. ORB-SLAM (四)tracking单目初始化

    单目初始化以及通过三角化恢复出地图点 单目的初始化有专门的初始化器,只有连续的两帧特征点均>100个才能够成功构建初始化器. ); 若成功获取满足特征点匹配条件的连续两帧,并行计算分解基础矩阵和 ...

  6. ORB-SLAM(十一)EPnP

    EPnP在ORB-SLAM中主要用于Tracking线程中的重定位Relocalization模块,需要通过当前关键帧Bow与候选帧匹配上的3D地图点,迅速建立当前相机的初始姿态. PnP问题解决了已 ...

  7. ORB-SLAM(五)优化

    ORB-SLAM作为单目SLAM,其精度很大程度上决定于帧与帧之间的位姿优化的是否准确.因此优化(optimization)在ORB-SLAM里面扮演了很重要的角色.这一小节探讨一下ORB-SLAM里 ...

  8. ORB-SLAM(一)简介

    ORB-SLAM是一种基于ORB特征的三维定位与地图构建算法(SLAM)[1].该算法由Raul Mur-Artal,J. M. M. Montiel和Juan D. Tardos于2015年发表在I ...

  9. ORB-SLAM(二)性能

    ORB-SLAM程序提供了运行Monocular.Stereo和RGBD数据的程序.编译成功后,可以通过运行TUM的标准数据来验证程序是否成功.如果想自己测试一些数据,可以通过OpenCV提供的接口调 ...

随机推荐

  1. mybatis批量插入报错

    报错内容 org.springframework.jdbc.UncategorizedSQLException: ### Error updating database. Cause: java.sq ...

  2. 《你必须掌握的Entity Framework 6.x与Core 2.0》勘误

    第5章 5.1.1----致谢网友[宪煌] public virtual ICollection Post {get;set;} 修改为 public virtual ICollection<P ...

  3. js创建对象,放进js集合

    var list=[]; for (var i=0;i<nodes.length;i++){ if(nodes[i].type=='user'){ person=new Object(); pe ...

  4. mysql查询order by 指定字段排序

    当MySQL查询时排序的字段不是数字时而是汉字的时候也可以用when  then 来指定排序. 列如yewu_check表的status 字段不是0,1,2而是汉字待办,已办,退回.可以如下写法: S ...

  5. git命令的理解与扩展

    Git的模式如图: Workspace:工作区 Index / Stage:暂存区 Repository:仓库区(或本地仓库) Repository:仓库区(或本地仓库) 一.新建代码库 # 查看gi ...

  6. js 对象 类型转换

    对象不相等 var o = {x: 1}, p = {x: 1}; console.log(o == p); console.log(o === p); var arr1 = [], arr2 = [ ...

  7. 文件实时同步(rsync+inotify)

    目标服务器:10.11.6.11 源服务器:10.11.6.12 准备条件: 1.关闭selinux: vi /etc/selinux/config #编辑防火墙配置文件 #SELINUX=enfor ...

  8. 2D-2D:对极几何 基础矩阵F 本质矩阵E 单应矩阵H

    对极约束 \[ \boldsymbol{x}_{2}^{T} \boldsymbol{F} \boldsymbol{x}_{1}=\boldsymbol{0} \quad \hat{\boldsymb ...

  9. 在windows环境利用celery实现简单的任务队列

    测试使用环境: 1.Python==3.6.1 2.MongoDB==3.6.2 3.celery==4.1.1 4.eventlet==0.23.0 Celery分为3个部分 (1)worker部分 ...

  10. POJ2385——Apple Catching

                                                $Apple~Catching$ Time Limit: 1000MS   Memory Limit: 6553 ...