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


轉載請注明出處,謝謝
原創作者:Mingrui
原創鏈接: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 特征點(FeaturePoint),每一個 ORB 特征點可能會對應一個 MapPoint
  • 同一個 MapPoint 會對應多個不同 Frame 中 ORB 特征
  • KeyFrames 和 MapPoints 構成了 Map
  • 重要的 KeyFrame 會存入 KeyFrame Database,用於回環檢測和重定位

一個有意思的地方在於,ORB-SLAM2 中並沒有給 ORB 特征點(FeaturePoint)建立一個對象。因為在 ORB-SLAM2 中,幾乎所有的匹配都是 FeaturePoint 和 MapPoint 之間的匹配,只有在做三角化的時候會有FeaturePoint 和 FeaturePoint 之間的匹配。

博文中可能出現的簡稱

  • KF:表示 KeyFrame
  • Current KF:表示當前 KeyFrame
  • Covisible KF:表示在 Covisibility Graph 中與 Current KF 相連的 KF
  • 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 所組成的局部的地圖
    • 決定是否將當前幀作為關鍵幀插入 Map
  • 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的邊。

提出 Covisiblility Graph 的目的是以此來描述 KFs 之間的共視關系。但 Covisibility Graph 較為稠密,不便於全局優化,所以提出了 Essential Graph。從上圖可以看出,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 系列博文

ORB-SLAM2 系列博文


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM