如何开始SLAM学习
自动驾驶里首先需要解决的问题就是建图和定位,如果地图和定位没有做好,无人车根本就跑不起来。而建图和定位又涉及SLAM技术。这里我主要是分享下我学习SLAM的经历和一些小小的思考,希望能够帮助大家。
了解阶段
因为我是从零开始的,我认为第一个阶段主要是了解SLAM技术,知道它的大致原理和用途就可以了。
SLAM的名称理解起来非常容易,我觉得SLAM技术中取名字唯一值得推荐的就是SLAM这个名词本身。同时定位与地图构建(Simultaneous localization and mapping),我们来到一个陌生环境,由于没有地图,只能通过探索,一边获取自己的相对位置,一边绘制当前环境的地图,当探索完该区域之后,我们就可以得到该未知区域的完整地图了。
除了SLAM,其它的一些名词大部分都晦涩难懂,我一度怀疑这些大神都是在秀屠龙技能。站在一个新手的角度来说,一个贴切和容易理解的技术名词非常关键,一个不知所措的名词往往都会吓退新人,比如BA,李代数群,词袋。我不排除其它学科的一些缩写和专有名词,但是这些名词完全无法用一句话解释它的用途,理解起来也非常不形象,这是我觉得不太合理的地方。
接下来是前端和后端,在计算机技术中前端通常指的是网页,后端通常指的是后台的服务器程序。而SLAM中恰恰又有前端和后端的概念,导致我理解起来也有点费力气,一是因为我之前就有惯性思维,二是感觉也不太贴切,虽然功能上有一个大概的影子,但是拿前端和后端去统称这2个过程有什么现实的意义吗?下面贴一张前端和后端划分的图。
以我目前的理解前端是进行特征提取,获取相邻帧的位姿变换,而后端则是进行地图的拼接和位姿优化。这2个过程有点类似在线计算和离线计算的架构,也就是大数据的lambda架构,实时计算的是相邻帧的位姿,然后再离线计算位姿的优化并且提供给在线使用。用前和后来指代这2个过程我无法理解它们的作用。
因此我觉得了解阶段最主要的也是最重要的是理解SLAM的名词本身,并且知道SLAM的大致的原理,也就是通过相邻帧来获取相对位姿,计算相对位置,同时利用历史轨迹信息来建图,并且优化之前和现在的位姿。
第一阶段知道了SLAM的大概原理就成功了,千万不要再去刻意理解上述这些名词,有可能只是增加烦恼。
学习框架
因为做自动驾驶,这里我主要以Lidar SLAM为例子来说明。目前lidar slam我认为优先学习lego-loam框架,然后是cartographer框架。其实如果开始只是了解SLAM的原理,一下子跳到看框架可能觉得跨度有点大,实际上我是非常建议一开始就是去学习框架,而不是看书,学习完整理论,学习数学之类,理由如下。
首先LEGO-LOAM的代码总共才4000行,也就是说就算是一行一行的啃,难度也不会非常大,一天看100行,40天也看完了。总之没看到代码前我还忐忑,代码会不会动则上万行,甚至几十万行,既然只有4000行,我觉得完全可以放心了,下定决心啃代码就可以了。
其次LEGO-LOAM还有论文讲解,我觉得这非常关键,比如开始我以为LEGO是代表积木的意思,可以类似乐高积木来搭建SLAM系统,实际上LEGO是基于地面做优化(Lightweight and Ground-Optimized)。论文中也详细介绍了程序的每个步骤,以及原因和背景,可以说结合代码食用效果非常好。
最后,LEGO-LOAM是当前比较主流的开源Lidar SLAM算法,学习动力足,不是什么过时或者不实用的算法。
等看完开源框架,基本上就对SLAM的整体框架有了一个大致的理解,比如前面所说的前端、后端,如何提取特征,如何做pose图优化,回环检测之类的。
进阶阶段
由于我本人目前仅限于前面2个阶段,因此这里主要是一些想法,后面如果有更进一步的学习,我会继续补充。
网上有集成了各种算法的OpenSLAM平台,这里面集成了一些开源的SLAM算法。我的理解是SLAM算法有点类似于编程,个人有很大的发挥空间,而不是按部就班的按照某几步操作就可以完成,比如提取特征,摄像机和Lidar提取的方式就不一样,而且如何提取特征也不一样。如何去除树叶,如何找到显著的特征,是基于传统的查找线和角特征,还是基于其它的算法,这些都没有成熟完善的方法论,都是基于经验和方法的结合,也就是个人的发挥占很大的因素。
拿SLAM和编程相比,虽然2者的实现起来都有很大的发挥空间,但是编程为什么好学习一点,之所以编程可以快速入门的原因,是因为有非常成熟的学习曲线,比如编程就是数据结构和算法。因此大部分人了解下编程语言,然后学习数据结构和算法,就可以很好的胜任编程了。所以我个人觉得SLAM学习网站可以不要一味的汇集各种SLAM算法,然后整成一个大杂烩,让个人去学习,而是应该把底层技术抽丝剥茧,总结成一些方法,然后分别去深入学习,等到使用时,再从这些方法中寻找合适的工具去组合。
比如特征提取,就有地面查找算法,聚类算法,这些算法什么时候适用于什么情况。如何做回环检测,如何进行pose-graph优化等。把这些单点的技术类似数据结构和算法总结出来,进行进一步的学习,然后再结合具体的场景去组合发挥出SLAM的威力,这可能是我目前比较推荐的学习思路和方法。
补充阶段
这几天又沉下心来看了《SLAM 14讲》可以说这本书对初学者来说非常友好,我个人觉得最大的收获在于,对基础概念解决的非常好,也就是说虽然之前的知识都懂,但是没有联系起来;另外就是结构清晰,比如SLAM的前端、后端、回环检测,虽然这些知识前面都可以了解,看书之后可以加深印象和理解。
接下来就是根据模块把每个部分在进一步做深,比如前端就看匹配算法,后端就看优化算法,回环就看字典匹配等。当然还有一些开放问题,例如移动物体比较多的情况,环境变换的情况,长隧道等。
总结
说实话一开始我只是用NDT在建图,之前一直尝试NDT建图没有成功的原因一是我没有理解pose之类的计算,二是没有好的工具,特别是可视化工具,能够手工加入旋转之类方便理解。实现了NDT之后,后面开始接触lego-loam,之前也是觉得高深莫测,但是一旦下定决心,并且只有4000行的代码量之后,接下来就容易多了,当然SLAM中名词混淆和刻意夸大优化算法公式之类的也是阻碍学习的重要原因之一,实际上这些优化算法都有对应的库可以实现,开始不用刻意理解。如果是后面涉及开发新的算法,可以在此基础上进一步学习。
最后侯捷老师说“使用一个东西却不知道它的原理,显得不太高明。”希望大家百尺竿头更进一步,也希望SLAM的学习曲线能够更加系统和专业。
后续我会对lego-loam做一些系统的笔记,并且尝试重构lego-loam的代码。
SLAM论文综述
- Past, Present, and Future of Simultaneous Localization And Mapping: Towards the Robust-Perception Age 2016年
- A critique of current developments in simultaneous localization and mapping 2016年
往期回顾