原文链接:https://blog.csdn.net/weixin_35695879/article/details/103511418

前言

在激光SLAM中,相关性扫描匹配可是重点中的重点,而分支限界加速更是大大提高了它的实时性。本文就来详细解读一下其中的奥秘。

激光SLAM前端

既然是SLAM,那么通常都会分为前端和后端。前端充当里程计的角色,比如我们熟知的VO(视觉里程计)和VIO(视觉惯性里程计)。激光SLAM也需要前端,对于每一帧点云,通常是使用所谓的扫描匹配(scan-match)方法进行位姿估计。

简单地说,扫描匹配就是想办法把两帧点云对齐,对齐过程中的旋转和平移就是两帧之间的相对位姿。这是最最简单的方式,实际中,为了提高鲁棒性,通常把当前帧点云和地图进行扫描匹配,更不容易出错。

扫描匹配的实现方式有两种,第一种是相关性扫描匹配,第二种是基于优化的扫描匹配。第一种思路简单,但有一些复杂的细节,而第二种则是构建非线性最小二乘优化问题并求解。实际中,通常是两种方法同时用,先用相关性扫描匹配求初值,再用基于优化的扫描匹配进一步优化。

相关性扫描匹配

相关性扫描匹配的思路其实非常简单。想象给定一个栅格地图,再给定当前帧的点云,怎样才能知道激光雷达所在的位置呢?最简单的办法,把激光雷达放在地图的每个格子上,看在这个位置时,点云是否与地图重合,重合程度最高的位置就是激光雷达的真实位姿。

显然,这个方法就是暴力搜索。虽然肯定搜得出来,但速度比较慢。想要加速,就得祭出我们的算法神器了——分支限界。

分支限界加速

如果上过计算机算法课,就一定接触过分支限界法。这是一个通用的算法,一般用于搜索离散空间的最优解。我们这里的解空间显然就是一个离散的空间,而且可以很方便地按照地图分辨率构造树形结构。

举例来说,假设有一张4×4的地图,我们降低其分辨率,每2×2的格子合并成一个,得到一张2×2的地图,再降低其分辨率,得到一张1×1的地图。这样,地图被分成了三层,如下图所示。

有了多分辨率地图后,我们先在第二层的解空间中搜索,找到最优的位姿对应的格子。然后再在该格子中搜索下一层中对应的小格子,找到最优的位姿。

这么简单?当然不是。请注意,上面的做法是完全错误的。它有两个问题。首先,在第二层的格子中搜索最优的位姿,实际上是把位姿放在格子的中心,计算其点云的评分(即hit点的评分之和,下文直接称其为位姿的评分)。但是格子中心的位姿并不能代表格子其它位置的位姿,很有可能格子中心的评分低于其它位置的评分,那么第二层最优的格子中并不一定包含第三层最优的格子。怎么办呢,我们可以想办法让格子中心的评分高于其所有子格子的评分,此时格子的评分是其子格子的评分上界,这样就可以保证子格子的最高评分体现在父格子中。

但是,此时又引入了第二个问题,虽然格子的评分是其子格子的评分上界,但并非上确界。也就是说,可能存在格子的评分很高,但其所有子格子的评分都很低的情况。这样的话,我们仍然无法选取最大评分格子的同时抛弃其它格子。

剩下的选择就只有一个,绝不抛弃任何一个可能存在最优解的格子,只抛弃那些绝对不存在最优解的格子。这正是分支限界的思想。

具体实现的时候,先从根节点开始遍历,把它拆分成4个子格子。这4个子格子分别计算评分,并由高到低排序。从中选出分数最高的格子,进一步拆分成4个子格子。假设这4个子格子已经到了叶子节点,也就是达到了真实地图的分辨率。此时计算出的4个子格子的评分代表了真实的位姿评分(只有叶子节点的评分是真实评分,其它格子的评分都是上界),找出其最大值,记作best_score。以上过程,我们体会了分支是如何实现的。接下来,该轮到限界出场了。第二层的格子还有3个未曾探索,我们当然是选择最大的那个开始分支。但别急,先看一下它的评分是否大于best_score,如果是,继续分支,如果否,就可以直接剪枝了,抛弃这个格子及其所有子格子。因为格子的评分代表了其子格子评分的上界,如果上界都小于best_score,就不可能再有子格子的评分大于它了。按照如此方法,大刀阔斧地剪枝即可。注意,当遇到评分大于best_score的叶子节点时,记得更新best_score,这样可以更快地缩小搜索空间。

讲到这里,你是不是有点摸不着头脑?别怕,因为这里有个最最关键的问题我还没有解释,也就是如何能够快速计算出格子评分的上界。

计算评分上界
先说一个平凡方法。既然要算子格子评分的上界,那就把每一个子格子拿出来算一遍,求个最大值。对了,子格子还会有子格子,所以这是个递归运算,直到把叶子节点都算出来才行。那这跟直接暴力搜索就没什么两样了,不行不行。

我们还是得追求在O(1)时间复杂度内求出格子的评分。想了想,之所以叶子节点评分可以在O(1)时间内求出,是因为它是直接在地图中查表得到的(严谨地说,是通过查其所有hit点的评分再求和得到的,但由于hit点数量固定,可以认为时间复杂度是O(1))。但我们构造的多分辨率地图能不能也维护类似的概率表格,使得格子的评分可以在对应分辨率地图中查询得到呢?

多么机智的想法啊!试想,把地图中每个格子的概率用其附近区域内的最大概率代替。这样的话,直接查对应分辨率地图就可以得到格子的评分,因为这个评分已经事先在附近区域中取了最大值。

上面提到的“某个范围”,需要与地图分辨率保持一致。也就是说,越低分辨率的地图(也就是越高层的地图),应该在越大的区域求最大值,其大小与当前分辨率下格子的大小一致。

不同分辨率的地图需要事先计算好,大概长这个样子:


可以看到,越靠后的地图分辨率越低,格子中的概率越接近1,也就代表了越高的上限。这与我们的直观理解是一致的。

总结

说实话,本文内容非常抽象,又限于笔者画图能力太差,实在画不出合适的插图,只能靠读者自己想象了。

不得不说,除非事先有所了解,否则读了之后可能还是一头雾水。所以,如果你对激光SLAM还没有整体的了解,还不知道什么是点云、什么是地图、如何计算概率。那么请关注一下文末的参考资料,相信会对你有所帮助。

相关性扫描匹配及分枝限界加速在谷歌Cartographer的论文中有详细介绍,建议大家去看一看。

参考资料
Real-Time Loop Closure in 2D LIDAR SLAM Wolfgang Hess, Damon Kohler, Holger Rapp, Daniel Andor

Cartographer的CSM理解相关推荐

  1. cartographer CSM理解

    格网地图怎么建立? 参考<概率机器人> M(i,j)为二维地图像素点取值大小,(i,j)为坐标,如M(17,867)=255,即在地图上坐标 (17,867)那点像素点的值为255.M(1 ...

  2. cartographer中分支定界法理解——为什么能保证上界

    定界原理 储存的不同分辨率栅格图,为保证上边界正确性,即高层中的评分一定高于其底层节点的评分,压缩的地图并非直接从原图固定间隔采样,而是将固定间隔中所有坐标概率值最大值作为低分辨率地图. 理解: 1. ...

  3. 激光SLAM——第四节(激光SLAM的前端配准方法)

    @[目录] ICP变种方法 – 第四章 激光的前端配准算法(ICP) 4.1.2.3.4的ICP方法,一个比一个精度高,计算量也大. 点云匹配算法是为了匹配两帧点云数据,从而得到传感器(激光雷达或摄像 ...

  4. Scrum联盟发布《2016年度Scrum状态调查报告》

    对Scrum的使用正日益扩展到IT和软件开发领域之外:有一部分企业对敏捷采用了一种"混搭"(Mix-and-Match)方法:ScrumMaster角色的演化更趋向于职能共享,只有 ...

  5. 一起做激光反光板(六)-基于滑窗的EKF-SLAM及外参自动标定公式推导

    在第四篇中已经提到,如果场景中反光板不够多,容易造成EKF系统效果不好的问题,且我们还想用上其他的点云信息,保证在反光板不够的情况下仍能够正确的收敛. 我们考虑扩充观测信息: (1)角点和线段特征,加 ...

  6. Cartographer分枝定界算法比喻理解

    Cartographer的代码非常紧凑,为了加深自己的理解和印象,尝试用比喻的方法去描述出来,欢迎大家交流指正. BnB比喻: 一家公司,有多个职位等级(对应多分辨率地图),现在要评项目奖金. 符合以 ...

  7. cartographer 理解

    整体理论概述 里面有scan与submap的匹配,这部分的匹配方法是有scan_matching 中的RealTimeCorrelationScanMatcher实现的.还有一个匹配是在完成闭环检测的 ...

  8. cartographer坐标系_cartographer个人对框架解读

    cartographer的代码主要包括两个部分:cartographer和cartographer_ros. 一.cartographer和cartographer_ros的关系 cartograph ...

  9. cartographer代码框架(谷歌最近修改之后的)

    cartographer理解与代码框架 由于cartographer最近进行了一次改动,对之前的cartographer的代码进行了调整,特此记录 一.按着框架来看程序的话,首先是传感器数据,这些统一 ...

最新文章

  1. GPM - 多语言实现视频
  2. VTK:可视化之VectorOfActors
  3. 用php实现随机点名,使用javascript做的一个随机点名程序
  4. 向着DJANGO奔跑!
  5. django组件-cookie与session
  6. 图论算法——无向图的邻接链表实现
  7. 第二阶段冲刺10天 第二天
  8. python进行接口请求,第一个接口返回的数据作为第二个参数的入参
  9. 940mx黑苹果驱动_黑苹果intel网卡驱动方法
  10. 肿瘤 材料 计算机模拟,PeerJ: 计算机模拟揭示癌症多样性
  11. 如何获取微信小店页面路径
  12. QQ聊天记录备份助手 v1.0——搜索、备份、恢复QQ聊天记录文件,重装系统必备...
  13. sony6000正在连接服务器,极速对焦+11张每秒连拍 Sony A6000评测
  14. 什么是Linux系统架构?
  15. 用C#编写一个图片浏览器,实现鼠标控制图片的平移缩放与图片的灰度化
  16. 遥感处理平台的发展(ENVI与GEE的比较)
  17. Linux下system () 函数详解简介
  18. 荣耀折叠旗舰Magic Vs系列;卡西欧搭配可拆卸表圈的G-SHOCK新品;联发科天玑8200 5G移动芯片 | 科技新品...
  19. 网页中登陆注册是如何实现的
  20. 【Java】什么是面向对象

热门文章

  1. java8新特性 Stream流的优雅操作
  2. SequoiaDB巨杉数据库成为唯一入选 “硅谷2016 大数据地形图”中国厂商, 企业级市场超越MongoDB等海外产品...
  3. 2009年最新虚拟主机提供商排名榜
  4. 〖Python 数据库开发实战 - Python与MySQL交互篇④〗- 数据库连接池技术
  5. centos/redhat kernel-debug-info-xx.rpm与kernel-debuginfo-xx.rpm区别
  6. 如何打赢一场 DevOps 阻击战
  7. 16、Kanzi插件——通过Kanzi Engine插件创建自定义动作+代码解析
  8. xss绕过字符过滤_xss绕过过滤之方法
  9. 大数量级组合数的快速计算方法
  10. 灰色产业链成病毒传播最大渠道 流量生意或迎来最后的疯狂