SLAM,即Simultaneous Localization and Mapping,中文譯作同時(shí)定位與地圖創(chuàng )建,是近幾十年里機器人領(lǐng)域有重大發(fā)展的研究方向。作為自主機器人的核心技術(shù),SLAM在機器人導航、控制、生產(chǎn)等方面都有著(zhù)重要的研究意義。尤其在二十一世紀,以視覺(jué)傳感器為中心的視覺(jué)SLAM技術(shù),在理論和方法上都經(jīng)歷了明顯的轉變與突破,正逐步從實(shí)驗室研究邁向成熟的市場(chǎng)應用。在國外研究如火如荼之際,它在國內的研究尚處于起步階段。有關(guān)SLAM的中文資料、書(shū)籍更是難以一見(jiàn)。然而,隨著(zhù)機器人技術(shù)得到國家的重視,越來(lái)越多的青年研究者、學(xué)生正逐漸跨入這片領(lǐng)域。本文檔則試圖為這些剛走進(jìn)SLAM的同事們,提供一些簡(jiǎn)單而實(shí)際的參考。
小蘿卜:師兄!你上面寫(xiě)的都是些什么東西??!
師兄:都是些沒(méi)什么卵用的廢話(huà)啊……但是沒(méi)這些東西文檔就不上檔次啊。
小蘿卜:師兄!你別干這些無(wú)聊的事情了!趕緊教我做SLAM??!
師兄:前言才寫(xiě)了一段,讀者會(huì )覺(jué)得我在敷衍他們的吧。算了,不管了,前兩天讓你跑的rgbd-slam怎么樣了?
小蘿卜:跑起來(lái)了!然后呢?
師兄:然后你就可以調調參數,改改代碼啥的啊。
小蘿卜:師兄!我看不懂!
師兄:呃這個(gè)……
小蘿卜:師兄!你給我寫(xiě)一個(gè)SLAM程序吧!
師兄:呃這個(gè)……
小蘿卜:趕緊寫(xiě)啦師兄!寫(xiě)完了你請我吃飯!
師兄:吃飯啊,那好吧……
于是,師兄就開(kāi)始寫(xiě)這本文檔了。由于師兄也不知道什么時(shí)候會(huì )寫(xiě)完,所以他每寫(xiě)一段就拿給小蘿卜看(然后請他吃飯)。還好小蘿卜熱情很高,每次師兄給他寫(xiě)好的代碼,都拿回去仔細看而且跑了。這也給了師兄很大動(dòng)力繼續往下寫(xiě)。
本文將帶領(lǐng)讀者自己動(dòng)手去寫(xiě)一個(gè)RGB-D SLAM程序。
因為我相信只有通過(guò)自己寫(xiě)程序,才能真正懂得slam的原理。
小蘿卜:為什么要寫(xiě)一個(gè)SLAM程序,而不采用現有的代碼呢?
- 師兄:為了更深的理解。
另一方面,自己寫(xiě)程序,不代表要用C++實(shí)現矩陣的線(xiàn)性代數?;镜膸煳覀冞€是會(huì )用的。
我們要用的庫:OpenCV, PCL, g2o.
還等什么?趕緊動(dòng)手吧!
編程環(huán)境:ubuntu 12.04。建議讀者和我們使用一樣或類(lèi)似的環(huán)境。如果你(出于酷或者其他什么原因)就是要用Arch/Fedora/Mac,請你自己配環(huán)境。
必備軟件的安裝:
mkdir buildcd buildcmake ..makesudo make install
編譯過(guò)程需要一點(diǎn)時(shí)間,長(cháng)短視你機器的配置而定。慢一點(diǎn)的可能一下午就過(guò)去了,請順便找點(diǎn)其他事干干例如看場(chǎng)電影之類(lèi)的。
小蘿卜:裝完之后OpenCV在哪里呢?
師兄:頭文件在/usr/local/include/,里面有opencv和opencv2的頭文件。我們基本只用opencv2啦。
師兄:庫文件就在/usr/local/lib/下面,當然這些在install的時(shí)候都是可以改動(dòng)的,我列的是默認位置。
小蘿卜:師兄!剛才用的cmake是什么東西???
師兄:cmake就是linux下的C++管理工具啦。簡(jiǎn)單的代碼你可以用g++一條條敲,再多些可以用Makefile來(lái)管理,cmake就是自動(dòng)生成makefile的工具,比makefile集成度更高一些。
小蘿卜:哦好的!我懂了師兄!請我吃飯哦!
師兄:好!
PCL就是Point Cloud Library啦,處理點(diǎn)云的必備工具。
小蘿卜:師兄!為什么要處理點(diǎn)云?
師兄:啊……忘了說(shuō)了,這篇文檔是講RGB-D SLAM的呀,深度相機采出來(lái)的本來(lái)就是點(diǎn)云數據啦。
小蘿卜:這么重要的事情為什么你不放到開(kāi)頭去講??!
師兄:我忘了……
不管如何,PCL官網(wǎng)(http://pointclouds.org)上已經(jīng)給出了ubuntu的安裝方法。因為很多開(kāi)發(fā)工具在ubuntu上裝起來(lái)最方便,也比較適合小蘿卜這種新手,所以我們才選用了ubuntu。
Step 1.
1 sudo add-apt-repository ppa:v-launchpad-jochen-sprickerhof-de/pcl2 sudo apt-get update3 sudo apt-get install libpcl-all
師兄:怎么樣?是不是很簡(jiǎn)單?
小蘿卜:是!
師兄:那么,類(lèi)似的,你能否找到PCL的頭文件以及庫文件的安裝目錄呢?我們把這個(gè)作為留給讀者的作業(yè)吧!
小蘿卜:師兄你不怕讀者把你電話(huà)打爆嗎?
到這里,必備的庫就安裝完了。之后若需要裝別的軟件,我們會(huì )單獨講。
我們已經(jīng)安裝好了OpenCV和PCL,下面我們開(kāi)始來(lái)寫(xiě)第一個(gè)程序吧!
小蘿卜:終于可以開(kāi)始寫(xiě)程序嘍!我最?lèi)?ài)寫(xiě)程序!我感到程序員之魂在我體內燃燒!
師兄:呃,可是我們第一個(gè)程序要做什么呢?
小蘿卜:我們馬上來(lái)寫(xiě)SLAM吧!
師兄:可是那樣讀者能看懂嗎……我們還是從簡(jiǎn)單的東西開(kāi)始吧。
小蘿卜:好!那就寫(xiě)一個(gè)簡(jiǎn)單的SLAM!
師兄:不不不,首先我們來(lái)構建一個(gè)CMake項目,作為今后寫(xiě)代碼的模板。開(kāi)頭讀者可能會(huì )覺(jué)得困難,但是萬(wàn)事開(kāi)頭難,后來(lái)你就慢慢習慣了。
Linux下的CMake項目通常由幾個(gè)文件夾組成。例如我們今天講的slam,你可以在機器上建一個(gè)叫slam的文件夾(注意:這個(gè)文件夾就是你代碼的根目錄了?。?。然后往里面建幾個(gè)子文件夾:

bin 用來(lái)放編譯好的可執行二進(jìn)制文件。
src 用來(lái)放源代碼。
lib 用來(lái)放編譯好的庫文件。
include 用來(lái)放頭文件。
為什么要用這種目錄結構呢?其實(shí)這是一種編譯習慣,當然你可以把所有文件都擱一個(gè)目錄里,但是這樣看起來(lái)很亂不是么。通常我們把源代碼和編譯好的東西分開(kāi)。如果源代碼比較多,還會(huì )按模板分開(kāi)。像opencv和pcl的代碼就是由好多個(gè)模塊組成的。
我們要把目錄結構告訴cmake。所以我們在代碼根目錄下寫(xiě)一個(gè)CMakeLists.txt。cmake在生成代碼時(shí),會(huì )讀這個(gè)文件,并按照它來(lái)編譯你的代碼。剛才我們對opencv進(jìn)行編譯時(shí),也采用了這個(gè)步驟。好,現在在代碼根目錄下新建一個(gè)CMakeLists.txt:
touch CMakeLists.txt寫(xiě)入:
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) #設定版本PROJECT( slam ) #設定工程名SET( CMAKE_CXX_COMPILER "g++") #設定編譯器 #設定可執行二進(jìn)制文件的目錄SET( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) #設定存放編譯出來(lái)的庫文件的目錄SET( LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) #并且把該目錄設為連接目錄LINK_DIRECTORIES( ${PROJECT_SOURCE_DIR}/lib) #設定頭文件目錄INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/include) #增加子文件夾,也就是進(jìn)入源代碼文件夾繼續構建ADD_SUBDIRECTORY( ${PROJECT_SOURCE_DIR}/src)井號后面的是我的注釋?zhuān)皇菫榱藥椭憷斫?,你可以不敲。通過(guò)這個(gè)文件,你應該了解了CMakeLists.txt的一些基本的用法。如果你想找一個(gè)系統的介紹,我們提供了《CMake實(shí)踐》電子書(shū),我認為是一個(gè)不錯的參考資料。
小蘿卜:等一下師兄!庫文件和二進(jìn)制都是什么??!
師兄:二進(jìn)制就是可以直接運行的程序啦,庫文件呢,就是為這些二進(jìn)制提供函數的啦。有main函數的代碼可以編譯成二進(jìn)制,其他的則編譯成庫文件。鏈接時(shí),把庫文件鏈到二進(jìn)制上,就可以運行啦。
小蘿卜:師兄我還是不懂!
師兄:呃,那我們還是通過(guò)實(shí)例來(lái)做吧。在src/文件夾下新建一個(gè)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 }
這當然是個(gè)很簡(jiǎn)單的,一目了然的程序。所以我也沒(méi)有加注釋。然后,我們要從這個(gè)源代碼生成一個(gè)二進(jìn)制。在src/目錄下新建一個(gè)CMakeLists.txt,輸入:
# 增加一個(gè)可執行的二進(jìn)制ADD_EXECUTABLE( main main.cpp )這樣,cmake就會(huì )把這個(gè)main.cpp編譯成一個(gè)叫做main的二進(jìn)制了。趕緊來(lái)試試吧。首先轉到代碼根目錄下,輸入:
1 mkdir build2 cd build3 cmake ..4 make
編譯通過(guò)的話(huà),就會(huì )在bin/目錄下生成一個(gè)main的二進(jìn)制哦!如果你執行這個(gè)二進(jìn)制,就會(huì )輸出Hello SLAM的語(yǔ)句啦!

是不是覺(jué)得這個(gè)程序太簡(jiǎn)單了?沒(méi)關(guān)系,難的在后面呢!
小蘿卜:難道這一講就這樣結束了?
師兄:是啊……畢竟寫(xiě)得還是蠻辛苦的,我得去休息一會(huì )。
小蘿卜:可是我們基本上沒(méi)寫(xiě)什么程序??!
師兄:別急啊,你先把cmake好好學(xué)學(xué),之后的工作都得在這上面做。
小蘿卜:好吧!那師兄我們下一講要做什么呢?
師兄:嗯,我們會(huì )用opencv讀個(gè)圖,再把它轉成點(diǎn)云,怎么樣?
小蘿卜:聽(tīng)起來(lái)不難啊,那下一講再見(jiàn)啦!
聯(lián)系客服