這是一本介紹視覺SLAM 的書,也很可能是第一本以視覺SLAM 為主題的中文書。那么,SLAM 是什么?
SLAM 是Simultaneous Localization and Mapping 的縮寫,中文譯作“同時定位與地圖構建”。它是指搭載特定傳感器的主體,在沒有環境先驗信息的情況下,于運動過程中建立環境的模型,同時估計自己的運動。如果這里的傳感器主要為相機,那就稱為“視覺SLAM”。
本書的主題就是視覺SLAM。這里我們刻意把許多個定義放到一句話中,是希望讀者有一個較明確的概念。首先,SLAM 的目的是解決“定位”與“地圖構建”這兩個問題。也就是說,一邊要估計傳感器自身的位置,一邊要建立周圍環境的模型。那么怎么解決呢?這需要用到傳感器的信息。傳感器能以一定形式觀察外部的世界,不過不同傳感器觀察的方式是不同的。而之所以要花一本書的內容去討論這個問題,是因為它很難——特別是我們希望實時地、在沒有先驗知識的情況下進行SLAM。當用相機作為傳感器時,我們要做的就是根據一張張連續運動的圖像(它們形成了一段視頻),從中推斷相機的運動,以及周圍環境的情況。
這似乎是個很直觀的問題。我們自己走進陌生的環境時不就是這么做的嗎?
在計算機視覺(Computer Vision)創立之初,人們就想象著有朝一日計算機將和人一樣,通過眼睛去觀察世界,理解周遭的物體,探索未知的領域——這是一個美妙而又浪漫的夢想,吸引了無數的科研人員日夜為之奮斗。我們曾經以為這件事情并不困難,然而進展卻遠不如預想的那么順利。我們眼中的花草樹木、蟲魚鳥獸,在計算機中卻是那樣的不同:它們只是一個個由數字排列而成的矩陣(Matrix)。讓計算機理解圖像的內容,就像讓我們自己理解這些數字一樣困難。我們既不了解自己如何理解圖像,也不知道計算機該如何理解、探索這個世界。于是我們困惑了很久,直到幾十年后的今天,才發現了一點點成功的跡象:通過人工智能(Artificial Intelligence)和機器學習(Machine Learning)技術,計算機漸漸能夠辨別出物體、人臉、聲音、文字——盡管它所用的方式(概率學建模)與我們是如此不同。另一方面,在SLAM 發展了將近30 年之后,我們的相機才漸漸開始能夠認識到自身的位置,發覺自己在運動——雖然方式還是和我們人類有巨大的差異。不過,至少研究者們已經成功地搭建出種種實時SLAM系統,有的能夠快速跟蹤自身位置,有的甚至能夠進行實時的三維重建。
這件事情確實很困難,但我們已經有了很大的進展。更令人興奮的是,近年來隨著科技的發展,涌現出了一大批與SLAM 相關的應用點。在許多地方,我們都希望知道自身的位置:室內的掃地機和移動機器人需要定位,野外的自動駕駛汽車需要定位,空中的無人機需要定位,虛擬現實和增強現實的設備也需要定位。SLAM 是那樣重要。沒有它,掃地機就無法在房間自主地移動,只能盲目地游蕩;家用機器人就無法按照指令準確到達某個房間;虛擬現實也將永遠固定在座椅之上——所有這些新奇的事物都無法出現在現實生活中,那將多么令人遺憾。
今天的研究者和應用開發人員,逐漸意識到了SLAM 技術的重要性。在國際上,SLAM 已經有近三十年的研究歷史,也一直是機器人和計算機視覺的研究熱點。21 世紀以來,以視覺傳感器為中心的視覺SLAM 技術,在理論和實踐上都經歷了明顯的轉變與突破,正逐步從實驗室研究邁向市場應用。同時,我們又遺憾地發現,至少在國內,與SLAM 相關的論文、書籍仍然非常匱乏,讓許多對SLAM 技術感興趣的初學者無從一窺門徑。雖然SLAM 的理論框架基本趨于穩定,但其編程實現仍然較為復雜,有著較高的技術門檻。剛步入SLAM 領域的研究者,不得不花很長的時間,學習大量的知識,往往要走過許多彎路才得以接近SLAM 技術的核心。
本書全面系統地介紹了以視覺傳感器為主體的視覺SLAM 技術,我們希望它能(部分地)填補這方面資料的空白。我們會詳細地介紹SLAM 的理論背景、系統架構,以及各個模塊的主流做法。同時,極其重視實踐:本書介紹的所有重要算法,都將給出可以運行的實際代碼,以求加深讀者的理解。之所以這么做,主要是考慮到SLAM 畢竟是一項和實踐緊密相關的技術。再漂亮的數學理論,如果不能轉化為可以運行的代碼,那就仍是可望而不可即的空中樓閣,沒有實際意義。我們相信,實踐出真知,實踐出真愛。只有實際地演算過各種算法之后,你才能真正地認識SLAM,真正地喜歡上科研。
自1986 年提出以來,SLAM 一直是機器人領域的熱點問題。關于它的文獻數以千計,想要對SLAM 發展史上的所有算法及變種做一個完整的說明,是十分困難而且沒有必要的。本書中會介紹SLAM 所牽涉的背景知識,例如射影幾何、計算機視覺、狀態估計理論、李群李代數等,并在這些背景知識之上,給出SLAM 這棵大樹的主干,而略去一部分形狀奇特、紋理復雜的枝葉。我們認為這種做法是有效的。如果讀者能夠掌握主干的精髓,那么自然會有能力去探索那些邊緣的、細節的、錯綜復雜的前沿知識。所以,我們的目的是,讓SLAM 的初學者通過閱讀本書快速地成長為能夠探索這個領域邊緣的研究者。另一方面,即便你已經是SLAM 領域的研究人員,本書也可能有一些你還覺得陌生的地方,可以讓你產生新的見解。
目前,與SLAM 相關的書籍主要有《概率機器人》(Probabilistic robotics)、《計算機視覺中的多視圖幾何》(Multiple View Geometry in Computer Vision)、《機器人學中的狀態估計》(State Estimation for Robotics: A Matrix-Lie-Group Approach)等。它們內容豐富、論述全面、推導嚴謹,是SLAM 研究者中膾炙人口的經典教材。然而就目前來看,還存在兩個重要的問題:其一,這些圖書的目的在于介紹基礎理論,SLAM 只是其應用之一。因此,它們并不能算是專門講解SLAM 的書籍。其二,它們的內容偏重于數學理論,基本不涉及編程實現,導致讀者經常出現“書能看懂卻不會編程”的情況。而我們認為,只有讀者親自實現了算法,調試了各個參數,才能談得上真正理解了問題本身。
我們會提及SLAM 的歷史、理論、算法、現狀,并把完整的SLAM 系統分成幾個模塊:視覺里程計、后端優化、建圖,以及回環檢測。我們將陪著讀者一點點實現這些模塊中的核心部分,探討它們在什么情況下有效,什么情況下會出問題,并指導大家在自己的機器上運行這些代碼。你會接觸到一些必要的數學理論和許多編程知識,會用到Eigen、OpenCV、PCL、g2o、Ceres 等庫à,掌握它們在Linux 操作系統中的使用方法。
從寫作風格上,我們不想把本書寫成枯燥的理論書籍。技術類圖書應該是嚴謹可靠的,但嚴謹不意味著刻板。一本優秀的技術書應該是生動有趣而易于理解的。如果你覺得“這個作者怎么這么不正經”,敬請原諒,因為我并不是一個非常嚴肅的人。無論如何,有一件事是可以肯定的:只要你對這門新技術感興趣,在學習本書的過程中肯定會有所收獲!您會掌握與SLAM 相關的理論知識,你的編程能力也將有明顯的進步。在很多時候,您會有一種“我在陪你一起做科研”的感覺,這正是我所希望的。但愿您能在此過程中發現研究的樂趣,喜歡這種“通過一番努力,看到事情順利運行”的成就感。
好了,話不多說,祝你旅行愉快!
如何使用本書
本書名為“視覺SLAM 十四講”。顧名思義,我們會像在學校里講課那樣,以“講”作為本書的基本單元。每一講都對應一個固定的主題,其中會穿插“理論部分”和“實踐”。如果你完全沒有聽說過它們,那么應該感到興奮,這說明你會從本書中收獲很多知識。你會經常在腳注中發現一些神奇的東西。
“實踐部分”兩種內容。通常是理論部分在前,實踐部分在后。在理論部分中,我們將介紹理解算法所必需的數學知識,并且大多數時候以敘述的方式,而不是像數學教科書那樣用“定義—定理—推論”的方式,因為我們覺得這樣的方式閱讀起來更容易一些,盡管有時候顯得不那么嚴謹。實踐部分主要是編程實現,討論程序里各部分的含義及實驗結果。看到標題中帶有“實踐”兩個字的章節,你就應該(興致勃勃地)打開電腦,和我們一起愉快地編寫代碼了。
值得一提的是,我們只會把與解決問題相關的數學知識放在書里,并盡量保持淺顯。雖然我們是工科生,但也要承認,某些做法只要經驗上夠用,沒必要非得在數學上追求完備。只要我們知道這些算法能夠工作,并且數學家們告訴了我們在什么情況下可能不工作,那么我們就表示滿意,而不追究那些看似完美但實際復雜冗長的證明(當然它們固有自己的價值)。由于SLAM 牽涉到了太多數學背景,為了防止使本書變成數學教科書,我們把一些細節上的推導和證明留作習題和補充閱讀材料,方便感興趣的讀者進一步閱讀參考文獻,更深入地掌握相關細節。
每一講正文之后,我們設計了一些習題。其中,帶* 號的習題是具有一定難度的。我們強烈建議讀者把習題都練習一遍,這對你掌握這些知識很有幫助。
全書內容主要分為兩個部分。
第一部分為數學基礎篇,我們會以淺顯易懂的方式,鋪墊與視覺SLAM 相關的數學知識,包括:
第1 講是前言,介紹這本書的基本信息,習題部分主要包括一些自測題。
第2 講為SLAM 系統概述,介紹一個SLAM 系統由哪些模塊組成,各模塊的
具體工作是什么。實踐部分介紹編程環境的搭建過程以及IDE 的使用。
第3 講介紹三維空間運動,你將接觸到旋轉矩陣、四元數、歐拉角的相關知識,并且在Eigen 當中使用它們。
第4 講為李群和李代數。即便你現在不懂李代數為何物,也沒有關系。你將學到李代數的定義和使用方式,然后通過Sophus 操作它們。
第5 講介紹針孔相機模型以及圖像在計算機中的表達。你將用OpenCV 來調取相機的內外參數。
第6 講介紹非線性優化,包括狀態估計理論基礎、最小二乘問題、梯度下降方法。你會完成一個使用Ceres 和g2o 進行曲線擬合的實驗。
這些就是我們要用到的所有數學知識了,當然,其中還隱含了你以前學過的高等數學和線性代數。我們保證它們看起來都不會很難。當然,若你想進一步深入挖掘,我們會提供一些參考資料供你閱讀,那些材料可能會比正文里講的知識難一些。 它們也可能成為今后相關行業的面試題,或許還能幫你在找工作時留個好印象。
第二部分為SLAM 技術篇。我們會使用第一部分所介紹的理論,講述視覺SLAM中各個模塊的工作原理。
第7 講為特征點法的視覺里程計。該講內容比較多,包括特征點的提取與匹配、對極幾何約束的計算、PnP 和ICP 等。在實踐中,你將用這些方法去估計兩個圖像之間的運動。
第8 講為直接法的視覺里程計。你將學習光流和直接法的原理,然后利用g2o 實現一個簡單的RGB-D 直接法。
第9 講為視覺里程計的實踐章,你將搭建一個視覺里程計框架,綜合運用先前學過的知識,實現它的基本功能。這個過程中,你會碰到一些問題,例如優化的必要性、關鍵幀的選擇等。
第10 講為后端優化,主要為對Bundle Adjustment 的深入討論,包括基本的BA,以及如何利用稀疏性加速求解過程。你將用Ceres 和g2o 分別書寫一個BA 程序。
第11 講主要講后端優化中的位姿圖。位姿圖是表達關鍵幀之間約束的一種更緊湊的形式。你將用g2o 和gtsam 對一個位姿球進行優化。
第12 講為回環檢測,主要介紹以詞袋方法為主的回環檢測。你將使用dbow3書寫字典訓練程序和回環檢測程序。
第13 講為地圖構建。我們會討論如何使用單目進行稠密深度圖的估計(以及這是多么不可靠),然后討論RGB-D 的稠密地圖構建過程。你會書寫極線搜索與塊匹配的程序,然后在RGB-D 中遇到點云地圖和八叉樹地圖的構建問題。
第14 講主要介紹當前的開源SLAM 項目以及未來的發展方向。相信在閱讀了前面的知識之后,你會更容易理解它們的原理,實現自己的新想法。
最后,如果你完全看不懂上面在說什么,那么恭喜你!這本書很適合你!加油!
代碼。本書所有源代碼均托管在github 上:https://github.com/gaoxiang12/slambook
強烈建議讀者下載它們以供隨時查看。代碼是按章節劃分的,比如,第7 講的內容就會放在ch7 文件夾中。此外,對于書中用到的一些小型庫,會以壓縮包的形式放在3rdparty 文件夾下。對于像OpenCV 那種大中型庫,我們會在它們第一次出現時介紹其安裝方法。如果你對代碼有任何疑問,請單擊GitHub 上的Issues 按鈕,提交問題。如果確實是代碼出現問題,我們會及時進行修改;即使是你的理解有偏差,我們也會盡可能回復。如果你不習慣使用Git,那么單擊右側包含download 字樣的按鈕將代碼下載至本地即可。
面向的讀者。本書面向對SLAM 感興趣的學生和研究人員。閱讀本書需要一定的基礎,我們假設你具備以下知識:
高等數學、線性代數、概率論。這些是大部分讀者應該在大學本科階段接觸過的基本數學知識。你應當明白矩陣和向量是什么,或者做微分和積分是什么意思。對于SLAM 中用到的專業知識,我們會額外加以介紹。
C++ 語言基礎。由于我們采用C++ 作為編碼語言,所以建議讀者至少熟悉這門語言的語法。比如,你應該知道類是什么,如何使用C++ 標準庫,模板類如何使用,等等。我們會避免過多地使用技巧,但有些地方確實無法避免。此外,我們還使用了一些C++ 11 標準的內容,不過,我們會在用到的地方加以解釋。
Linux 基礎。我們的開發環境是Linux 而非Windows,并且只提供Linux 下的源程序,不會再提供Windows 下的開發方法介紹。我們認為,掌握Linux 是一個SLAM 研究人員所必需的,請初學者暫時不要問為什么,把本書的知識學好之后相信你會和我們有同樣的想法。各種程序庫在Linux 下的配置都非常便捷,
你也會在此過程中體會到Linux 的便利。如果讀者此前從未使用過Linux,那么最好找一本Linux 的教材稍加學習(掌握基本知識即可,一般就是相關圖書的前面幾章內容)。我們不要求讀者具備高超的Linux 操作技能,但希望讀者至少知道“打開終端,進入代碼目錄”是如何操作的。本講的習題里有一些Linux 知識自測題,如果你清楚自測題的答案,那么閱讀本書代碼不會有任何問題。
對SLAM 感興趣但不具備上述知識的讀者,可能在閱讀本書時會感到困難。如果你不了解C++ 的基本知識,可以讀一點C++ Primer Plus 之類的圖書入門;如果你缺少相關的數學知識,也可以先閱讀一些相關數學教材補充知識,不過我們認為,對大多數大學本科水平的朋友,讀懂本書所需的數學背景肯定是具備了。代碼方面,你最好花點時間親自輸入一遍,再調節里面的參數,看看效果會發生怎樣的改變。這會對學習很有幫助。
本書可作為SLAM 相關課程的教材,亦可作為課外自學材料使用。
致謝和聲明
在本書漫長的寫作過程中,我們得到了許多人的幫助,包括但不限于:
中科院的賀一家博士為第5講的相機模型部分提供了材料。
顏沁睿提供了第7講的公式推導材料。
華中科大的劉毅博士為本書第6講和第10講提供了材料。
眾多的老師、同學為本書提供了修改意見:肖錫臻、謝曉佳、耿欣、李帥杰、劉富強、袁夢、孫志明、陳昊升、王京、朱晏辰、丁文東、范帝楷、衡昱帆、高揚、李少朋、吳博、閆雪嬌、張騰、鄭帆、盧美奇、楊楠,等等。在此向他們表示感謝。
此外,感謝我的導師張濤教授一直以來對我的支持和幫助。感謝電子工業出版社鄭柳潔編輯的支持。沒有他們的幫助,本書不可能以現在的面貌來到讀者面前。本書的成書與出版是所有人共同努力的結晶,盡管我沒法把他們都列在作者列表中,但是它的出版離不開他們的工作。
本書寫作過程中參考了大量文獻和論文。其中大部分數學理論知識是前人研究的成果,并非我的原創。一小部分實驗設計亦來自各開源代碼的演示程序,不過大部分是我自己編寫的。此外,也有一些圖片摘自公開發表的期刊或會議論文,文中均已注明。
未做說明的圖像,或為原創,或來自網絡,恕不一一列舉。如有問題,請與我們聯系,我們會在第一時間加以修正。
本書涉及知識點眾多,錯漏在所難免。如有疑問,歡迎通過電子郵件與我聯系。
感謝我的愛人劉麗蓮女士長期的理解和支持。這本書是獻給她的。