距離寫上一片文章已經也過去一段時間了,對之前看過的程序竟是如此陌生,還好在此做注,現在開始看新的線程:LocalMapping
系統有一個map,這個線程就是用來管理這個地圖的,這個地圖在跟蹤線程中被初始化,在ORBSlam2的Tracking線程中,進行相機狀態初始化的時候,當使用對極約束時,求解了第一幀和第二幀之間的單應矩陣和基本矩陣,並通過三角測量得到兩幀匹配點的三維位置之后,使用了全局BA算法進行了一次細致的位姿優化。再是在locaomapping線程中,不斷得向地圖里插入關鍵幀,然后利用插入的關鍵幀及其相連關鍵幀及地圖點進行局部BA優化。
LocalMapping作用是將Tracking中送來的關鍵幀放在mlNewKeyFrame列表中;處理新關鍵幀,地圖點檢查剔除,生成新地圖點,Local BA,關鍵幀剔除。主要工作在於維護局部地圖,也就是SLAM中的Mapping。
LocalMapping線程主要的工作就是通過不斷的加入新KeyFrame和新地圖點,剔除冗余KeyFrame和冗余地圖點,來維護一個穩定的KeyFrame集合,從而可以進行后面的LoopClosing操作。
所以這個線程只是維護地圖,沒有進行全局優化。
我們知道。線程聲明之后就從Run函數開始出發
Function1:LocalMapping::Run()
只要系統沒有停止,那么就一直開始執行以下的任務:
Function1.1:SetAcceptKeyFrames(false)
告訴Tracking,LocalMapping正處於繁忙狀態, LocalMapping線程處理的關鍵幀都是Tracking線程發過的,在LocalMapping線程還沒有處理完關鍵幀之前Tracking線程最好不要發送太快。
判斷等待處理的關鍵幀列表不為空。
Function1.2: ProcessNewKeyFrame()
取出等待關鍵幀,該幀就是處理的當前幀。 計算該關鍵幀特征點的Bow映射關系。跟蹤局部地圖過程中新匹配上的MapPoints和當前關鍵幀綁定(在TrackLocalMap函數中將局部地圖中的MapPoints與當前幀進行了匹配, 但沒有對這些匹配上的MapPoints與當前幀進行關聯),即如果是非當前幀生成的MapPoints,那么就為當前幀在tracking過程跟蹤到的MapPoints更新屬性,包括為該MapPoint添加觀測,說明能夠為當前幀觀測到,獲得該點的平均觀測方向和觀測距離范圍, 加入關鍵幀后,更新3d點的最佳描述子,最后是更新關鍵幀間的連接關系,Covisibility圖和Essential圖(tree),將該關鍵幀插入到地圖中。
由於單目不直接生成一些新的地圖點,所以就用不到剔除MapPoints。
Function1.3: CreateNewMapPoints
相機運動過程中和共視程度比較高的關鍵幀通過三角化恢復出一些MapPoints。
如果在等待處理的關鍵幀列表為空。
Function1.4: SearchInNeighbors
檢查並融合當前關鍵幀與相鄰幀(兩級相鄰)重復的MapPoints,在單目中,一級相鄰幀為其連接關系的前20幀,二級相鄰幀為各個一級相鄰幀相鄰程度最高的5幀。將當前幀的MapPoints分別與一級二級相鄰幀(的MapPoints)進 行融合,將一級二級相鄰幀的MapPoints分別與當前幀(的MapPoints)進行融合,融合就是指一個3D的地圖點轉換為關鍵幀坐標系下,然后反變換為像素坐標,在一定的半徑范圍內找出描述子距離跟3D的地圖點最近 的特征點id,並找到該特征點對應的MapPoint,然后比較兩個MapPoint的可被觀測的次數多,勝者替代對方,完成融合。最后更新當前幀MapPoints的描述子,深度,觀測主方向等屬性,更新當前幀的MapPoints后更新與 其它幀的連接關系。
Function1.5: SLocalBundleAdjustment
這是進行和當前幀相連的關鍵幀及MapPoint做局部BA優化,而不是整個地圖庫去做全局的優化。在這部分我一直誤解是所謂的后端全局地圖的優化,但現在的想法是他只不過是為了幫助更加精確得去維護一個地圖庫,即讓庫里的關鍵幀的位姿是優化后的。
Function1.6: KeyFrameCulling
對當前幀與其共視的關鍵幀進行剔除,90%以上的MapPoint能被其他共視關鍵幀所觀測到,那么該幀就會被剔除。
Function1.7: mpLoopCloser->InsertKeyFrame(mpCurrentKeyFrame)
現在處理的當前幀是跟蹤線程送進來的,經過LocalMapping線程送到進行后面的mlploopKeyFrameQueue進行下一個線程的操作。