LocalMapping作用是將Tracking中送來的關鍵幀放在mlNewKeyFrame列表中;處理新關鍵幀,地圖點檢查剔除,生成新地圖點,Local BA,關鍵幀剔除。主要工作在於維護局部地圖,也就是SLAM中的Mapping。
1. 處理新關鍵幀:ProcessNewKeyFrame()
做了三件事:
a. 計算當前關鍵幀Bow,便於后面三角化恢復新地圖點;
b. 將TrackLocalMap中跟蹤局部地圖匹配上的地圖點綁定到當前關鍵幀(在Tracking線程中只是通過匹配進行局部地圖跟蹤,優化當前關鍵幀姿態),也就是在graph中加入當前關鍵幀作為node,並更新edge。而CreateNewMapPoint()中則通過當前關鍵幀,在局部地圖中添加與新的地圖點;
c. 更新加入當前關鍵幀之后關鍵幀之間的連接關系,包括更新Covisibility圖和Essential圖(最小生成樹spanning tree,共視關系好的邊subset of edges from covisibility graph with high covisibility (θ=100), 閉環邊)。
2. 對於ProcessNewKeyFrame和CreateNewMapPoints中最近添加的MapPoints進行檢查剔除:MapPointCulling()
候選待檢查地圖點存放在mlpRecentAddedMapPoints,滿足兩個條件之一就被剔除:
1. 跟蹤(匹配上)到該地圖點的普通幀幀數(IncreaseFound)<應該觀測到該地圖點的普通幀數量(25%*IncreaseVisible):該地圖點雖在視野范圍內,但很少被普通幀檢測到。
2. 從添加該地圖點的關鍵幀算起的初始三個關鍵幀,第一幀不算,后面兩幀看到該地圖點的幀數,對於單目<=2,對於雙目和RGBD<=3;因此在地圖點剛建立的階段,要求比較嚴格,很容易被剔除;而且單目的要求更嚴格,需要三幀都看到。若從添加該地圖點的關鍵幀算起,一共有了大於三個關鍵幀,還存在列表中,則說明該地圖點是高質量的,從檢查列表中去掉。
一旦經過了這樣比較嚴格的篩選,地圖點只有在觀測到它的關鍵幀<3時才會被剔除,這主要發生在關鍵幀被剔除(90%以上匹配點可以被其他幀觀察到);或者局部捆集優化時,將地圖點歸為外點從觀測中剔除了的情況。因此地圖點中的外點是比較少的,所以整套ORB-SLAM中除了重定位和閉環很少去使用RANSAC。
ORB-SLAM中關鍵幀和地圖點的加入和刪除秉承的是送入嚴出的標准,因此在提高了定位建圖准確性的前提下又很好地限制了計算量,可以用於large scale的場景。
3. 根據當前關鍵幀恢復出一些新的地圖點,不包括和當前關鍵幀匹配的局部地圖點(已經在ProcessNewKeyFrame中處理),注意理解與前面兩步的先后關系,先處理新關鍵幀與局部地圖點之間的關系,然后對局部地圖點進行檢查,最后再通過新關鍵幀恢復心的局部地圖點:CreateNewMapPoints()
--- 對Tracking中送來的每一幀關鍵幀執行上述過程,直到mlNewKeyFrame為空。
3'. SearchInNeighbors()
更新並融合當前關鍵幀以及兩級相連(共視關鍵幀及其共視關鍵幀)的關鍵幀的地圖點。
4. LocalBundleAdjustment()
5. KeyFrameCulling
局部關鍵幀剔除
void LocalMapping::KeyFrameCulling();
候選的pKF是LocalMapping中當前處理的關鍵幀的共視關鍵幀,不包括第一幀關鍵幀與當前關鍵幀。遍歷pKF中的地圖點的觀測:
const map<KeyFrame*, size_t> observations = pMP->GetObservations();
若有不少於3幀被觀測到(需要滿足觀測尺度不大於或近似於在pKF中的尺度),則記錄下。若pKF中90%以上的地圖點能夠被其他關鍵幀觀測到,也就是說,該關鍵幀的存在提供的地圖點觀測信息有限,則將其刪除!