1. 程式人生 > >ORB-SLAM2 論文&程式碼學習 —— 概覽

ORB-SLAM2 論文&程式碼學習 —— 概覽

轉載請註明出處,謝謝
原創作者:MingruiYU
原創連結:https://www.cnblogs.com/MingruiYu/p/12347171.html


本文要點:

  • ORB-SLAM2 簡介
  • ORB-SLAM2 實體物件之間的關係
  • ORB-SLAM2 系統概覽 (參考論文 + 程式碼)
  • 以思維導圖形式繪製的 ORB-SLAM2 程式導圖

寫在前面

最近準備開始做本科畢業設計,準備對 SLAM 系統中的迴環檢測模組下手。因為新冠疫情不知道什麼時候才能返校,這次放假回家就帶了個 matebook 14 回來,搬磚全靠這小電腦,它苦我也苦(流淚)。

作為開源 SLAM 系統中的經典之一 —— ORB-SLAM2,自然是要拿來好好研究一番。之前閱讀了 ORB-SLAM 和 ORB-SLAM2 論文,之後配置安裝了 ORB-SLAM2 跑了個 example 看看樣子(我的博文 ORB-SLAM2 初體驗 —— 配置安裝),這回準備開始磕程式碼。但越磕越發現,這玩意也太複雜了吧。為了實現較好的魯棒性,ORB-SLAM2 中加入了很多很多小 trick 來從細節上提升系統的效能。這些細節在論文裡往往就是一句話帶過,但在程式碼裡就是一大堆環環相扣繞來繞去的東西。雖然大家都說 ORB-SLAM2 的程式碼是結構清晰,註釋完整,易於理解,但本渣渣還是看的把頭髮撓成了鳥窩狀。

所以,我決定通過寫博文的方式,來更好地梳理 ORB-SLAM2 程式碼的框架和步驟,以加深自己的理解,也希望我的梳理能夠對大家有所幫助。

ORB-SLAM2 簡介

ORB-SLAM是15年Raul等人提出的一個單目SLAM系統,其在單目SLAM領域影響廣泛。詳情可見論文:[Monocular] Raúl Mur-Artal, J. M. M. Montiel and Juan D. Tardós. ORB-SLAM: A Versatile and Accurate Monocular SLAM System. IEEE Transactions on Robotics, vol. 31, no. 5, pp. 1147-1163, 2015. (2015 IEEE Transactions on Robotics Best Paper Award). PDF.

在單目ORB-SLAM的基礎上,17年Raul等人又提出了ORB-SLAM2,增加了對於雙目相機和RGB相機的支援。詳情可見論文:[Stereo and RGB-D] Raúl Mur-Artal and Juan D. Tardós. ORB-SLAM2: an Open-Source SLAM System for Monocular, Stereo and RGB-D Cameras. IEEE Transactions on Robotics, vol. 33, no. 5, pp. 1255-1262, 2017. PDF

ORB-SLAM2 的論文中,對於單目部分並沒有做很大修改,也沒有筆墨去重寫單目實現的細節。而其雖然增加了雙目和 RGB-D 相機的支援,但本質上還是在單目系統的基礎上加的,並不是從根本上以雙目或 RGB-D 輸入為設計出發點。所以個人認為,學習 ORB-SLAM2 還是要以單目為主,不能繞開單目去看雙目或 RGB-D 的實現。另外,因為 ORB-SLAM2 論文中並沒有重寫單目實現的細節,所以對於 ORB-SLAM2 的學習還是要從第一篇 ORB-SLAM 的論文入手。以下內容均以 ORB-SLAM 單目部分為基礎。

一些鋪墊

ORB-SLAM2 中的實體物件

ORB-SLAM2 中的實體物件包括:

  • Frame
  • KeyFrame
  • MapPoint
  • Map
  • KeyFrame Database

它們之間的關係是這樣的:

  • 每一個送入系統的視訊幀都會構造一個 Frame
  • Frame 中比較重要的會設為 KeyFrame
  • 每個 Frame 會提取很多 ORB 特徵點,每一個 ORB 特徵點可能會對應一個 MapPoint
  • 同一個 MapPoint 會對應多個不同 Frame 中 ORB 特徵
  • KeyFrames 和 MapPoints 構成了 Map
  • 重要的 KeyFrame 會存入 KeyFrame Database,用於迴環檢測和重定位

博文中可能出現的簡稱

  • KF:表示 KeyFrame
  • Current KF:表示當前 KeyFrame
  • Covisible KF:表示在 Covisibility Graph 中與 Current KF 相連的 KFs
  • Loop KF:表示迴環 KeyFrame,即和 Current KF 相匹配的 KeyFrame Database 中的 KF
  • Candidate KF:表示可能是 Current KF 的 Loop KF 的候選 KF
  • Reference KF:表示距離當前幀最近的上一 KF
  • KF Database:表示用來儲存 KFs 的 Database,這些 KFs 會用於迴環檢測和重定位

ORB-SLAM2 系統概覽

下面我會從論文和程式碼(程式導圖)兩個角度出發,對 ORB-SLAM2 系統進行一個概覽。

以論文為參考

ORB-SLAM 論文中,有一張圖非常經典且重要:

ORB-SLAM 系統同時執行三個執行緒:

  • Tracking 執行緒:
    • 對於新讀取的幀,提取 ORB 特徵
    • (系統初始化)
    • 相機位姿初值估計(根據上一幀 + motion-only BA,或進行重定位)
    • 區域性地圖跟蹤
      • 對上一步得到的位姿初值進行進一步 BA 優化
      • 區域性地圖:指 Covisibility Graph 中附近的 KFs 及其 MapPoints 所組成的區域性的地圖
    • 決定是否將該幀作為關鍵幀插入 LocalMapping 執行緒
  • LocalMapping 執行緒:
    • 接收從 Tracking 執行緒插入的 KF,並進行預處理
    • 剔除質量較差的 MapPoints
    • 通過三角化生成新的 MapPoints
      • Current KF 未與現有 MapPoints 匹配的 ORB 特徵點 與其 Covisible KFs 的特徵點進行匹配,並三角化
    • Local BA
    • 剔除冗餘的區域性關鍵幀
  • LoopClosing 執行緒
    • 接收 LoopClosing 送來的篩選處理後的 KF
    • 檢測出一批 Candidate KFs
    • 計算 Sim3,確定最終的 Loop KF
    • 進行迴環融合
    • 優化 Essential Graph

其中 Covisibility Graph 指的是:其節點為所有 KF。一個 KF,如果它與另一個 KF 觀測到的相同的 MapPoints 的數量大於15個,則這兩個 KFs 之間有邊相連。從而組成了 Covisibility Graph。同時,Covisibility Graph 中的每條邊有權重,權重即為兩個 KFs 共同觀測到的 MapPoints 數目。

其中 Essential Graph 指的是:系統會構造一個生成樹。當一個新的 KF 插入時,將它與(與它觀測到相同的 MapPoints 的數量最多的 KF)相連,從而得到一個生成樹。Essential Graph = 該生成樹 + Covisibility Graph 中權重大於100的邊。

從上圖可以看出,Covisibility Graph 中的邊很多,生成樹就是一條線,而 Essential Graph 介於兩者之間。

以程式碼(程式導圖)為參考

上面論文裡那張框架圖概括的非常好,但是這張圖還是太簡略了,光看它也搞不懂每個步驟之間的邏輯關係是怎樣。而它們之間複雜的邏輯關係用大段文字更是很難描述清楚。在通讀程式碼的時候,我經常讀著讀著就忘了前面讀了什麼,忘了現在讀的部分是巢狀在哪裡迴圈裡,是屬於哪個子函式。於是我想了個辦法 —— 用思維導圖來梳理程式碼的結構和邏輯。試驗過後,我覺得這個辦法很好用。此處獻上我梳理的非常非常大的 ORB-SLAM2 程式導圖:

(如果下方顯示不出來,就點 ORB-SLAM2 程式框圖 連結檢視吧)

這個導圖梳理的挺詳細的了,希望它能對大家有幫助。(我用的 MindMaster 這款畫思維導圖的軟體,Windows Linux ios Andriod 都支援,同時可以將導圖儲存在個人雲上多裝置共享,另外也支援生成並分享導圖連結)

 

我繪製的程式導圖是以 mono_tum.cc 程式為入口,該程式是官方提供的 example,其對 TUM 資料集中的視訊序列進行 SLAM。根據該程式,我們可以清晰地看出該怎麼呼叫整個 ORB-SLAM2 系統。

ORB-SLAM2 系統以 System.cc 為系統的入口,其負責建立各種物件,同時建立 Tracking,LocalMapping, LoopCLosing 三個執行緒並執行。其中,System::TrackMonocular()是啟動 Tracking 執行緒的入口。Tracking 執行緒為主執行緒,而 LocalMapping 和 LoopClosing 執行緒是通過 new thread 建立的。
  
 

關於 Tracking,LocalMapping, LoopCLosing 三個執行緒的具體內容,我會在以後的博文中進行更為詳細的介紹和梳理。

其它相關博文

ORB-SLAM2 初體驗 —— 配置安