ORB-SLAM2中LoopClosing線程主要流程梳理

LoopClosing線程主要工作是兩個:一個是對當前新到來的關鍵幀進行閉環檢測,看看之前的關鍵幀中哪個和當前關鍵幀形成閉環;另一個是糾正閉環,就是在檢測到閉環的時候要將當前關鍵幀和閉環關鍵幀的位姿拉到一起,形象點說就是進行融合(既然都存在閉環了,那肯定得合併啊)。

一、閉環檢測DetectLoop

1.從關鍵幀列表中獲取列表頭的關鍵幀,也就是獲取最新插入到LoopClosing線程的關鍵幀,並判斷當前關鍵幀是否距離上次關鍵幀閉環檢測的幀之間大於10幀,大於10幀才進行後邊的閉環檢測,否則將新的關鍵幀插入到關鍵幀數據庫中。


2.獲取當前關鍵幀和與其共視的所有關鍵幀詞袋向量比較的最小分值minScore;


3.在關鍵幀數據庫中查找和當前關鍵幀存在閉環的候選關鍵幀(DetectLoopCandidates)。步驟如下:
     1)獲取當前關鍵幀在共視圖中和他連接的關鍵幀,並遍歷查找這些關鍵幀當中的詞向量都在哪些關鍵幀中出現過,查到的共享詞向量的關鍵幀存放在lKFsSharingWords當中;
     2)遍歷lKFsSharingWords,統計候選幀中與pKF具有共同單詞最多的單詞數maxCommonWords;
     3)再次遍歷lKFsSharingWords,得到和當前關鍵幀共享單詞數大於0.8×maxCommonWords,並且和當前關鍵幀的BoW得分大於minScore的關鍵幀,存入lScoreAndMatch當中;
     4)遍歷lScoreAndMatch當中的關鍵幀,對其中每個關鍵幀計算和其共視關係最好的10個關鍵幀中的最高得分的關鍵幀和他們的累計分值bestAccScore,存入lAccScoreAndMatch當中;
     5)遍歷lAccScoreAndMatch,對其中每個關鍵幀判斷其得分大於0.75×bestAccScore的話,將該關鍵幀存入閉環候選幀spAlreadyAddedKF當中返回;


4.判斷連續性:一個關鍵幀和其所有的相連關鍵幀一起構成了一個關鍵幀組,判斷連續性的根據就是判斷當前關鍵幀組當中的關鍵幀是否在上一次的關鍵幀組中出現過足夠的幀數。
     1)遍歷閉環候選幀,將每一個候選幀和其所有相連的關鍵幀放在一個set集合當中,構成了當前的候選連續性關鍵幀組;
     2)遍歷上一次的連續性關鍵幀組,判斷當前的候選連續性關鍵幀組中的每一個關鍵幀是否在上一次的連續性關鍵幀組中出現過。
        如果出現過,則將該關鍵幀的連續性個數在上一次的基礎上加1存儲在nCurrentConsistency中,當nCurrentConsistency大於閾值3的時候並且還沒有足夠的連續性則認爲當前候選關鍵幀具有足夠的連續性,將其加入到mvpEnoughConsistentCandidates當中。
     3)mvpEnoughConsistentCandidates中有加入的關鍵幀,則認爲具有連續性。

     此時mvpEnoughConsistentCandidates就是檢測所得的閉環候選關鍵幀。


5.用當前的連續性共視關鍵幀組更新上一次的連續性共視關鍵幀組(mvConsistentGroups = vCurrentConsistentGroups;)。


6.將當前關鍵幀加入到關鍵幀數據庫當中。

二、計算相似變換ComputeSim3

sim3的引入:對於單目相機來說,具有尺度不確定性。如果在單目SLAM當中使用歐式變換SE3表示位姿,由於尺度不確定性和累積漂移的存在,整個運動過程中的尺度會發生變化,而SE3體現不出尺度的變化,所以此時就需要借用相似變換將尺度因子表達出來。對於空間中的一個點p,要投影到相機座標系當中,相似變換表達如下:

                                                                   {p}'=\begin{bmatrix} sR & t\\ 0^T& 1 \end{bmatrix}p=sRp+t.

相似變換的尺度s作用在p的3個座標上,相當於對p進行了一次縮放。相似變換對矩陣乘法構成羣,稱爲相似變換羣sim3。

以上引入描述來自高博視覺slam十四講當中。另外sim3計算也可以參考筆者之前的一篇博文:ORB-SLAM2代碼閱讀筆記(十):sim3求解

ComputeSim3流程如下:

1.遍歷候選閉環關鍵幀中每個關鍵幀,對每個候選關鍵幀和當前關鍵幀之間求解sim3。
      1)這裏先對每個候選關鍵幀和當前關鍵幀進行BOW搜索匹配,只有當匹配的特徵點數>=20的時候才爲該候選幀構建sim3求解器,否則剔除掉該候選幀;
      2)對1)中爲每個匹配成功的候選幀進行sim3迭代優化求解,根據求解出的s,R,t再次對當前關鍵幀和候選關鍵幀進行匹配(函數爲SearchBySim3);
      3)根據sim3求解結果構造當前關鍵幀到候選關鍵幀的sim3變換(這裏的尺度s是sim3求解出來的)gScm,並遍歷2)中的匹配點進行SIM3優化;
         如果優化後的inlier數>=20,則該候選幀就是匹配關鍵幀,並計算當前幀位姿經過sim3修正後的位姿(這裏構造閉環幀的sim3位姿gSmw時,尺度s爲1)mg2oScw = gScm*gSmw,至此也就計算出了當前關鍵幀的位姿;
         如果優化後的inlier數<20,則繼續遍歷下一個候選關鍵幀進行sim3變換求解;


2.獲取當前關鍵幀的匹配閉環關鍵幀及其相連關鍵幀對應的地圖點。將這些地圖點通過上面優化得到的Sim3(位姿mScw) 變換投影到當前關鍵幀進行匹配SearchByProjection:
     如果匹配點數>=40,則判定當前關鍵幀和閉環候選關鍵幀存在閉環關係;
     如果匹配點數<40,則判定當前關鍵這暖和閉環候選幀之間沒有閉環關係;


注意,在LoopClosing::ComputeSim3()函數中一共進行了下面三次特徵點匹配:
 1.第一次匹配
int nmatches = matcher.SearchByBoW(mpCurrentKF,pKF,vvpMapPointMatches[i]);
這裏主要是通過SearchByBow搜索當前關鍵幀mpCurrentKF中和閉環候選幀pKF匹配的地圖點,BoW通過將單詞聚類到樹結構node的方法,這樣可以加快搜索匹配速度,vvpMapPointMatches[i]用於存儲當前關鍵幀和候選關鍵幀之間匹配的地圖點。
 
2.第二次匹配
  matcher.SearchBySim3(mpCurrentKF,pKF,vpMapPointMatches,s,R,t,7.5);
  使用sim3求出來的s,R,t通過SearchBySim3得到更多匹配。
 
3.第三次匹配
matcher.SearchByProjection(mpCurrentKF, mScw, mvpLoopMapPoints, mvpCurrentMatchedPoints,10);
這裏得到的當前關鍵幀中匹配上閉環關鍵幀共視地圖點(mvpCurrentMatchedPoints)將用於後面CorrectLoop時當時關鍵幀地圖點的衝突融合,
到這裏不僅確保了當前關鍵幀與閉環幀之間匹配度高, 而且保證了閉環幀的共視圖中的地圖點和當前幀的特徵點匹配度更高,說明該閉環幀是正確的。


三、閉環校正CorrectLoop

1.暫停LocalMapping線程,防止其在閉環校正階段向LoopClosing線程中插入新的關鍵幀;
2.停止全局BA優化線程運行;
3.更新當前關鍵幀與其共視的其他關鍵幀之間的連接關係UpdateConnections;
4.得到當前關鍵幀和與其連接的共視關鍵幀組,並通過當前關鍵幀的sim3位姿計算出與其相連接的共視關鍵幀的閉環優化後的sim3位姿;
5.利用4中所得的調整過的和當前關鍵幀相連的所有關鍵幀的sim3位姿來更新每個關鍵幀相對應的地圖點的3D座標和深度等信息;
6.根據關鍵幀的SIM3位姿構造出歐式變換SE3,也就是關鍵幀的位姿,並更新關鍵幀的位姿和連接關係;
7.更新當前關鍵幀當中的地圖點,或者將經過sim3位姿糾正過的地圖點加入到當前關鍵幀當中。
   前置理解事項:
        第一次匹配:通過BoW比較進行匹配;
        第二次匹配:在第一次匹配的基礎上,根據匹配點進行sim3優化求解後,再根據sim3所求的旋轉R、平移t和尺度s再次進行當前關鍵幀和閉環候選幀之間的匹配SearchBySim3,並再次進行優化;
        第三次匹配:使用第二次匹配完優化後的當前關鍵幀和閉環候選幀之間的SIM3變換再次進行匹配matcher.SearchByProjection;
   通過以上三次匹配後,所得的匹配點是質量最高的,畢竟每次匹配和優化後都會剔除一些outlier。在閉環校正當中使用這些匹配點進行地圖點融合,也就是用這些地圖點替換掉當前關鍵幀。
       
   用投影匹配上的經過SIM3計算糾正過位姿的地圖點更新當前關鍵幀(也就是存在閉環的關鍵幀)中對應的地圖點;
   如果當前關鍵幀中沒有與之對應的地圖點,則將這些經過SIM3計算糾正過位姿的地圖點加入當前關鍵幀當中,並更新該地圖點的觀測幀和描述子;

8.地圖點進行融合SearchAndFuse:
  這裏是使用閉環匹配關鍵幀和其共視關鍵幀當中的地圖點來更新當前關鍵幀的共視關鍵幀中相匹配的地圖點。
  當前關鍵幀的共視關鍵幀中沒有的地圖點,則直接進行添加;有的則直接用閉環匹配關鍵幀和其共視關鍵幀當中對應的地圖點進行更新。
  這樣就完成了地圖點的融合。

9.優化EseentialGraph:Optimizer::OptimizeEssentialGraph
  EseentialGraph其實就是當前地圖中所有的關鍵幀、所有的地圖點組成的圖,那麼這裏其實就是一個大的圖優化。
  只不過在這裏邊優化的時候要區分當前關鍵幀、和當前關鍵幀形成的閉環關鍵幀、當前關鍵幀的共視關鍵幀、和閉環關鍵幀有共視關係的關鍵幀。
  如果關鍵幀的位姿在sim3求解的時候已經求出來了,則使用sim3求解所得的位姿。圖的頂點都是關鍵幀,邊分爲正常邊(normal edge)和閉環邊(loop edge),
  用優化所得的關鍵幀的sim3變換恢復出SE3,並對關鍵幀中相應的地圖點更新其3D座標和深度信息。
 

10.將當前關鍵幀添加到匹配的閉環關鍵幀的閉環邊中。
   將與當前關鍵幀形成閉環的關鍵幀添加到當前關鍵幀的閉環邊中;

11.啓動一個線程進行全局優化RunGlobalBundleAdjustment。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章