SLAM,即Simultaneous Localization and Mapping,中文译作同时定位与地图创建,是近几十年里机器人领域有重大发展的研究方向。作为自主机器人的核心技术,SLAM在机器人导航、控制、生产等方面都有着重要的研究意义。尤其在二十一世纪,以视觉传感器为中心的视觉SLAM技术,在理论和方法上都经历了明显的转变与突破,正逐步从实验室研究迈向成熟的市场应用。在国外研究如火如荼之际,它在国内的研究尚处于起步阶段。有关SLAM的中文资料、书籍更是难以一见。然而,随着机器人技术得到国家的重视,越来越多的青年研究者、学生正逐渐跨入这片领域。本文档则试图为这些刚走进SLAM的同事们,提供一些简单而实际的参考。 小萝卜:师兄!你上面写的都是些什么东西啊! 师兄:都是些没什么卵用的废话啊……但是没这些东西文档就不上档次啊。 小萝卜:师兄!你别干这些无聊的事情了!赶紧教我做SLAM啊! 师兄:前言才写了一段,读者会觉得我在敷衍他们的吧。算了,不管了,前两天让你跑的rgbd-slam怎么样了? 小萝卜:跑起来了!然后呢? 师兄:然后你就可以调调参数,改改代码啥的啊。 小萝卜:师兄!我看不懂! 师兄:呃这个…… 小萝卜:师兄!你给我写一个SLAM程序吧! 师兄:呃这个…… 小萝卜:赶紧写啦师兄!写完了你请我吃饭! 师兄:吃饭啊,那好吧…… 于是,师兄就开始写这本文档了。由于师兄也不知道什么时候会写完,所以他每写一段就拿给小萝卜看(然后请他吃饭)。还好小萝卜热情很高,每次师兄给他写好的代码,都拿回去仔细看而且跑了。这也给了师兄很大动力继续往下写。
本文将带领读者自己动手去写一个RGB-D SLAM程序。 因为我相信只有通过自己写程序,才能真正懂得slam的原理。 小萝卜:为什么要写一个SLAM程序,而不采用现有的代码呢? - 师兄:为了更深的理解。
另一方面,自己写程序,不代表要用C++实现矩阵的线性代数。基本的库我们还是会用的。 我们要用的库:OpenCV, PCL, g2o. 还等什么?赶紧动手吧!
编程环境:ubuntu 12.04。建议读者和我们使用一样或类似的环境。如果你(出于酷或者其他什么原因)就是要用Arch/Fedora/Mac,请你自己配环境。 必备软件的安装:
到这里,必备的库就安装完了。之后若需要装别的软件,我们会单独讲。
我们已经安装好了OpenCV和PCL,下面我们开始来写第一个程序吧! 小萝卜:终于可以开始写程序喽!我最爱写程序!我感到程序员之魂在我体内燃烧! 师兄:呃,可是我们第一个程序要做什么呢? 小萝卜:我们马上来写SLAM吧! 师兄:可是那样读者能看懂吗……我们还是从简单的东西开始吧。 小萝卜:好!那就写一个简单的SLAM! 师兄:不不不,首先我们来构建一个CMake项目,作为今后写代码的模板。开头读者可能会觉得困难,但是万事开头难,后来你就慢慢习惯了。 Linux下的CMake项目通常由几个文件夹组成。例如我们今天讲的slam,你可以在机器上建一个叫slam的文件夹(注意:这个文件夹就是你代码的根目录了!)。然后往里面建几个子文件夹:
bin 用来放编译好的可执行二进制文件。 为什么要用这种目录结构呢?其实这是一种编译习惯,当然你可以把所有文件都搁一个目录里,但是这样看起来很乱不是么。通常我们把源代码和编译好的东西分开。如果源代码比较多,还会按模板分开。像opencv和pcl的代码就是由好多个模块组成的。 我们要把目录结构告诉cmake。所以我们在代码根目录下写一个CMakeLists.txt。cmake在生成代码时,会读这个文件,并按照它来编译你的代码。刚才我们对opencv进行编译时,也采用了这个步骤。好,现在在代码根目录下新建一个CMakeLists.txt: touch CMakeLists.txt
写入: CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) #设定版本 PROJECT( slam ) #设定工程名 SET( CMAKE_CXX_COMPILER "g++") #设定编译器 #设定可执行二进制文件的目录 SET( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) #设定存放编译出来的库文件的目录 SET( LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) #并且把该目录设为连接目录 LINK_DIRECTORIES( ${PROJECT_SOURCE_DIR}/lib) #设定头文件目录 INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/include) #增加子文件夹,也就是进入源代码文件夹继续构建 ADD_SUBDIRECTORY( ${PROJECT_SOURCE_DIR}/src) 井号后面的是我的注释,只是为了帮助你理解,你可以不敲。通过这个文件,你应该了解了CMakeLists.txt的一些基本的用法。如果你想找一个系统的介绍,我们提供了《CMake实践》电子书,我认为是一个不错的参考资料。 小萝卜:等一下师兄!库文件和二进制都是什么啊! 师兄:二进制就是可以直接运行的程序啦,库文件呢,就是为这些二进制提供函数的啦。有main函数的代码可以编译成二进制,其他的则编译成库文件。链接时,把库文件链到二进制上,就可以运行啦。 小萝卜:师兄我还是不懂! 师兄:呃,那我们还是通过实例来做吧。在src/文件夹下新建一个main.cpp文件,输入: 1 #include <iostream> 2 3 int main(int argc, char**argv) 4 { 5 std::cout<<"Hello SLAM!"<<std::endl; 6 return 0; 7 } 这当然是个很简单的,一目了然的程序。所以我也没有加注释。然后,我们要从这个源代码生成一个二进制。在src/目录下新建一个CMakeLists.txt,输入: # 增加一个可执行的二进制
ADD_EXECUTABLE( main main.cpp )
这样,cmake就会把这个main.cpp编译成一个叫做main的二进制了。赶紧来试试吧。首先转到代码根目录下,输入: 1 mkdir build 2 cd build 3 cmake .. 4 make 编译通过的话,就会在bin/目录下生成一个main的二进制哦!如果你执行这个二进制,就会输出Hello SLAM的语句啦! 是不是觉得这个程序太简单了?没关系,难的在后面呢! 小萝卜:难道这一讲就这样结束了? 师兄:是啊……毕竟写得还是蛮辛苦的,我得去休息一会。 小萝卜:可是我们基本上没写什么程序啊! 师兄:别急啊,你先把cmake好好学学,之后的工作都得在这上面做。 小萝卜:好吧!那师兄我们下一讲要做什么呢? |
|