-
前言
2016.11 更新
- 增加了對16.04的支持。
- 整理了過時的代碼。
SLAM,即Simultaneous Localization and Mapping,中文譯作同時定位與地圖創建,是近幾十年里機器人領域有重大發展的研究方向。作為自主機器人的核心技術,SLAM在機器人導航、控制、生產等方面都有着重要的研究意義。尤其在二十一世紀,以視覺傳感器為中心的視覺SLAM技術,在理論和方法上都經歷了明顯的轉變與突破,正逐步從實驗室研究邁向成熟的市場應用。在國外研究如火如荼之際,它在國內的研究尚處於起步階段。有關SLAM的中文資料、書籍更是難以一見。然而,隨着機器人技術得到國家的重視,越來越多的青年研究者、學生正逐漸跨入這片領域。本文檔則試圖為這些剛走進SLAM的同事們,提供一些簡單而實際的參考。
小蘿卜:師兄!你上面寫的都是些什么東西啊!
師兄:都是些沒什么卵用的廢話啊……但是沒這些東西文檔就不上檔次啊。
小蘿卜:師兄!你別干這些無聊的事情了!趕緊教我做SLAM啊!
師兄:前言才寫了一段,讀者會覺得我在敷衍他們的吧。算了,不管了,前兩天讓你跑的rgbd-slam怎么樣了?
小蘿卜:跑起來了!然后呢?
師兄:然后你就可以調調參數,改改代碼啥的啊。
小蘿卜:師兄!我看不懂!
師兄:呃這個……
小蘿卜:師兄!你給我寫一個SLAM程序吧!
師兄:呃這個……
小蘿卜:趕緊寫啦師兄!寫完了你請我吃飯!
師兄:吃飯啊,那好吧……
於是,師兄就開始寫這本文檔了。由於師兄也不知道什么時候會寫完,所以他每寫一段就拿給小蘿卜看(然后請他吃飯)。還好小蘿卜熱情很高,每次師兄給他寫好的代碼,都拿回去仔細看而且跑了。這也給了師兄很大動力繼續往下寫。
-
本文的目標
本文將帶領讀者自己動手去寫一個RGB-D SLAM程序。
因為我相信只有通過自己寫程序,才能真正懂得slam的原理。
小蘿卜:為什么要寫一個SLAM程序,而不采用現有的代碼呢?
- 師兄:為了更深的理解。
- 一個完整的程序含有大量的算法與GUI的代碼,你讀一遍需要多久?弄清楚原理要多久?
- 別人工具都做好了,代碼都寫完了,參數也調好了,你拿過來運行。那頂多給別人做一下評測。
- 你遲早要自己寫代碼。
另一方面,自己寫程序,不代表要用C++實現矩陣的線性代數。基本的庫我們還是會用的。
我們要用的庫:OpenCV, PCL, g2o.
還等什么?趕緊動手吧!
-
預備知識與編程環境
編程環境:ubuntu 12.04。建議讀者和我們使用一樣或類似的環境。如果你(出於酷或者其他什么原因)就是要用Arch/Fedora/Mac,請你自己配環境。
必備軟件的安裝:
- OpenCV
推薦從源代碼安裝的模式。編譯過程需要一點時間。
Step 1.
下載OpenCV源代碼: http://opencv.org/downloads.html。
目前(2015.6)較好的版本是2.4系列,因為3.0系列還不完善(主要是沒文檔)。請把它下載到電腦上隨意一個目錄下。
在下載過程中,你可以安裝依賴項。基本的依賴項是底下那些,直接拷貝到終端執行。
1 sudo apt-get install build-essential libgtk2.0-dev libjpeg-dev libtiff4-dev libjasper-dev libopenexr-dev cmake python-dev python-numpy python-tk libtbb-dev libeigen2-dev yasm libfaac-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev libx264-dev libqt4-dev libqt4-opengl-dev sphinx-common texlive-latex-extra libv4l-dev libdc1394-22-dev libavcodec-dev libavformat-dev libswscale-dev
把OpenCV解壓到下載目錄中,用cmake編譯再安裝.
mkdir build cd build cmake .. make sudo make install
編譯過程需要一點時間,長短視你機器的配置而定。慢一點的可能一下午就過去了,請順便找點其他事干干例如看場電影之類的。
小蘿卜:裝完之后OpenCV在哪里呢?
師兄:頭文件在/usr/local/include/,里面有opencv和opencv2的頭文件。我們基本只用opencv2啦。
師兄:庫文件就在/usr/local/lib/下面,當然這些在install的時候都是可以改動的,我列的是默認位置。
小蘿卜:師兄!剛才用的cmake是什么東西啊?
師兄:cmake就是linux下的C++管理工具啦。簡單的代碼你可以用g++一條條敲,再多些可以用Makefile來管理,cmake就是自動生成makefile的工具,比makefile集成度更高一些。
小蘿卜:哦好的!我懂了師兄!請我吃飯哦!
師兄:好!更新:你也可以使用 sudo apt-get install libopencv-dev 安裝OpenCV 2.4.9 。
- PCL
PCL就是Point Cloud Library啦,處理點雲的必備工具。
小蘿卜:師兄!為什么要處理點雲?
師兄:啊……忘了說了,這篇文檔是講RGB-D SLAM的呀,深度相機采出來的本來就是點雲數據啦。
小蘿卜:這么重要的事情為什么你不放到開頭去講啊!
師兄:我忘了……
不管如何,PCL官網(http://pointclouds.org)上已經給出了ubuntu的安裝方法。因為很多開發工具在ubuntu上裝起來最方便,也比較適合小蘿卜這種新手,所以我們才選用了ubuntu。
在Ubuntu 1404或更低版本,你需要通過私有源來安裝PCL庫
Step 1.1 sudo add-apt-repository ppa:v-launchpad-jochen-sprickerhof-de/pcl 2 sudo apt-get update 3 sudo apt-get install libpcl-all
在 Ubuntu 1604,PCL庫已經存在於公共軟件源中,直接安裝即可:
sudo apt-get install libpcl-dev pcl-tools
但是,在1604中PCL的配置似乎有bug,需要在cmakelist中加一條指令修復。
師兄:怎么樣?是不是很簡單?
小蘿卜:是!
師兄:那么,類似的,你能否找到PCL的頭文件以及庫文件的安裝目錄呢?我們把這個作為留給讀者的作業吧!
小蘿卜:師兄你不怕讀者把你電話打爆嗎?
到這里,必備的庫就安裝完了。之后若需要裝別的軟件,我們會單獨講。
-
HELLO SLAM!
我們已經安裝好了OpenCV和PCL,下面我們開始來寫第一個程序吧!
小蘿卜:終於可以開始寫程序嘍!我最愛寫程序!我感到程序員之魂在我體內燃燒!
師兄:呃,可是我們第一個程序要做什么呢?
小蘿卜:我們馬上來寫SLAM吧!
師兄:可是那樣讀者能看懂嗎……我們還是從簡單的東西開始吧。
小蘿卜:好!那就寫一個簡單的SLAM!
師兄:不不不,首先我們來構建一個CMake項目,作為今后寫代碼的模板。開頭讀者可能會覺得困難,但是萬事開頭難,后來你就慢慢習慣了。
Linux下的CMake項目通常由幾個文件夾組成。例如我們今天講的slam,你可以在機器上建一個叫slam的文件夾(注意:這個文件夾就是你代碼的根目錄了!)。然后往里面建幾個子文件夾:
bin 用來放編譯好的可執行二進制文件。
src 用來放源代碼。
lib 用來放編譯好的庫文件。
include 用來放頭文件。
為什么要用這種目錄結構呢?其實這是一種編譯習慣,當然你可以把所有文件都擱一個目錄里,但是這樣看起來很亂不是么。通常我們把源代碼和編譯好的東西分開。如果源代碼比較多,還會按模板分開。像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好好學學,之后的工作都得在這上面做。
小蘿卜:好吧!那師兄我們下一講要做什么呢?
師兄:嗯,我們會用opencv讀個圖,再把它轉成點雲,怎么樣?
小蘿卜:聽起來不難啊,那下一講再見啦!
本文的pdf版本,源代碼,圖片等資源可在我的git里下載到。
網址: https://github.com/gaoxiang12/rgbd-slam-tutorial-gx