g2o初探

研究SLAM的同學應該對g2o並不陌生。用了一段時間之後,一直對其內部實現方式不太清楚,今天打算仔細研究一下。

首先祭出官方提供的g2o類層次結構圖。

g2o類層次結構圖

這個圖需要分塊來看。

左上角HyperGraph提供了頂點和邊構成的拓撲圖,它只關注圖的連接關係,不負責優化相關的工作。其派生類OptimizableGraph爲頂點和邊提供了可優化的功能。再往下是OptimizableGraph的派生類SparseOptimizer,顯然,對於構建的圖優化問題,SparseOptimizer提供了稀疏求解的方案,這也是SLAM能夠達到實時性所依賴的關鍵技術。以上,是優化器相關的部分。

再往下,優化器包含了一個OptimizationAlgorithm,這是優化算法的基類,優化器會調用該優化算法實現優化。右邊給出了優化算法的具體實現,OptimizationWithHessian包含了一系列基於Hessian矩陣求解增量方程的優化算法,包括OptimizationAlgorithmGaussNewtonOptimizationAlgorithmLevenbergOptimizationAlgorithmDogleg。不同的優化算法給出了不同的梯度下降策略,也就是說,用不同的方式找出增量的方向和大小,但迭代求解的本質是一樣的。

再往右,優化算法包含一個Solver,也就是求解器。不論使用了什麼優化算法,每次迭代都需要求解一個 H∆x=g 的增量方程,其中H是Hessian矩陣或其變體,∆x是待求的優化變量的更新量。那麼如何求解這個方程,就是Solver的工作了。在g2o中,只提供了一個實現類BlockSolver<>。所謂塊求解器,就是利用A矩陣的稀疏性,每個優化變量和誤差項都體現爲固定大小的矩陣塊,可以利用它的一些性質加速計算。在塊求解器中,包含了一個SparseBlockMatrix<T>LinearSolver,其實前者用來存放H矩陣的數據,後者用來指定具體的線性求解器。之所以叫線性求解器,是因爲增量方程是一個線性方程。g2o提供的線性求解器有三個,分別是LinearSolverCSparse<>LinearSolverCholmod<>LinearSolverPCG<>。它們之間的不同大概只是對矩陣求逆的方式不同,可能會有速度上的差異,但結果一定一致。

最後,右上角的一大部分是頂點和邊,這些比較容易理解,也是我們編程中接觸得最多的,這裏不再詳述。

分析完這個圖,基本上g2o的優化流程也就差不多清晰了。但有幾個關鍵的環節剛纔並沒有提到,而且我的理解也不敢保證沒有偏差,寫在下面和大家一起交流。

SLAM中有一個加速增量方程求解的方法,稱爲邊緣化。邊緣化是說,如果我們把待優化的相機位姿放在H矩陣的左上角,把待優化的路標點放在H矩陣的右下角,再把H矩陣分爲四塊,就可以對H的矩陣塊進行高斯消元,使得對相機位姿的求解不依賴於路標點。這種方法奏效的原因是因爲相機矩陣相比於路標點稀疏得多,因此相機矩陣塊求逆更容易。當然,具體的分析建議閱讀高翔的《視覺SLAM十四講》。這裏我們更關注g2o中的實現。邊緣化部分的操作在BlockSolver<>中,塊求解器會把對增量方程的求解分爲兩步,先求解相機位姿的增量,再求解路標點的增量。當然,每次求解增量仍然是調用內部的LinearSolver。思路很清晰,但g2o在這裏的實現卻有待商榷,塊求解器中根據頂點是否被邊緣化決定該頂點是位姿頂點還是路標點頂點,也就是說,它默認所有位姿頂點都不被邊緣化,所有路標點頂點都被邊緣化。假如你嘗試不邊緣化路標點頂點,或邊緣化位姿頂點,求解器都會報錯,這就限制了我們優化的靈活性。在我看來,這可能是g2o作者實現過程中的一個瑕疵。BlockSolver並沒有體現出其應有的抽象,它應該根據實際的頂點類型來決定如何實現邊緣化,而不是一股腦地認爲只有路標點應該被邊緣化。(注意,這裏提到的邊緣化只用於加速增量方程求解,不同於滑動窗口中的邊緣化。)

總體上看,我認爲g2o是一個結構良好的圖優化框架,它的類層次結構提供了很高的可擴展性。但遺憾的是,實際實現的功能並不多,很多類的派生類都只有一個,比如只有SparseOptimizer而沒有DenseOptimizer,只有OptimizationWithHessian而沒有OptimizationWithOthers,只有BlockSolver<>而沒有PlainSolver。以至於g2o只能用於求解視覺SLAM問題,應用範圍有些狹隘。但畢竟g2o沒有企業在背後支持,不像Ceres有谷歌撐腰,搞不好以後做SLAM的標配會變成Ceres吧,感覺有些可惜。

文末給出了一些詳細的參考資料,比本文更有價值,大家可以參考。

參考資料

《視覺SLAM十四講》 高翔
g2o學習——g2o整體框架 無人的回憶
g2o學習——頂點和邊之外的solver 無人的回憶
A General Framework for Graph Optimization R Kümmerle

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