從編譯運行orbslam2說起


從編譯運行orbslam2說起

0.基礎

  "0.基礎"而不是"0基礎",把它放在1的前面,用0來強調做某件事之前必須已經完成某事的概念.正所謂磨刀不誤砍柴工,如果你不想浪費3個小時坎坷的去砍柴,那最好老老實實花上1個小時磨好刀.
  本文面向具有cmake,linux shell,ROS基礎的SLAM研究者.請讀者自行學習以下知識:

  • robot SLAM基礎與orbslam2簡介
  • cmake基礎
  • linux與linux shell基礎
  • ROS基礎

1.編譯

第三方庫的安裝或現場編譯

  首先orbslam2作為一個大型程序,並不是完全自己造的輪子,而是在一些非核心的地方使用了第三方庫的.學計算機的都知道如果自己程序使用了第三方庫,編譯時需要找到頭文件,鏈接時需要找到庫文件.大型程序的構建過程也是一樣的,orblsam2需要找到第三方庫的頭文件和庫文件,這個交給cmake來處理,我們重點來談談它的第三方庫.這又分為兩個種:

  1. 直接使用第三方庫.在orbslam2中就是OpenCV,Pangolin等.這一部分必須事先已經正確安裝到系統中了
  2. 對第三方庫做了修改的.在orbslam2中就是g2o,dbow等.這一部分必須由作者提供修改后的源碼,現場編譯

  為了說明這點,我們可以查看工程的CMakeLists.txt文件

target_link_libraries(${PROJECT_NAME}
${OpenCV_LIBS}
${EIGEN3_LIBS}
${Pangolin_LIBRARIES}
${PROJECT_SOURCE_DIR}/Thirdparty/DBoW2/lib/libDBoW2.so
${PROJECT_SOURCE_DIR}/Thirdparty/g2o/lib/libg2o.so
)

  從上面代碼可以看出,程序鏈接了5個庫,其中OpenCV,EIGEN3,Pangolin來自系統中,DBoW2和g2o來自現場編譯后生成的庫文件.故我們在構建orbslam等大型工程時,不是一上來就編譯,而是要先解決依賴.這里略去第三方庫的安裝和編譯方法.

編譯核心API庫

  當所有依賴的庫文件和頭文件都准備就緒,就可以開始編譯orbslam了.接着看CMakeLists.txt:

add_library(${PROJECT_NAME} SHARED
src/System.cc
src/Tracking.cc
src/LocalMapping.cc
src/LoopClosing.cc
src/ORBextractor.cc
src/ORBmatcher.cc
src/FrameDrawer.cc
src/Converter.cc
src/MapPoint.cc
src/KeyFrame.cc
src/Map.cc
src/MapDrawer.cc
src/Optimizer.cc
src/PnPsolver.cc
src/Frame.cc
src/KeyFrameDatabase.cc
src/Sim3Solver.cc
src/Initializer.cc
src/Viewer.cc
)

  注意到作者的源碼都編譯成了一個動態庫,根據cmake的命名規則,應該是一個叫libORB_SLAM2.so的文件.但是為什么不直接編譯可執行程序?非要多此一舉地搞一個動態庫?其實不然,之所以這樣做出於兩點原因:

  1. 大型程序的編寫都是OOP,眾所周知OOP的優點有很多:便於分析,設計,編碼,維護.這樣說很抽象,簡單舉幾個例子:
    • 例子1:小明編寫了一個幾萬行的main.cpp,然后他崩潰了.后來他用OO思想設計了類,在main.cpp中調用,程序縮減到百行
    • 例子2:小明要編寫3個單獨的VO,回環,優化程序,他建立了三個大型工程,然后他崩潰了.后來他用OO思想設計了類,寫了3個程序調用這些類,再后來他創造性的把三個模塊整合,寫出了完整的slam程序
    • 例子3:小明編寫了一個單目slam程序,老板要求他再寫一個雙目的,他又得重新造輪子了,所以他依然崩潰了,后來他用OO思想設計了類,在已有程序中增加了一個雙目類,成功完成了雙目slam程序
  2. 封裝成核心API庫,便於發布給其他開發者使用

  封裝成核心API庫是一種有益之法,尤其是當你自己需要構建大型程序時,讀者可自行體會.

編譯作者提供的demo,並將其鏈接到上面生成的核心API庫

再往下看,cmake就開始編譯作者提供的demo了.作者提供了4個200來行左右的demo源程序,分別是rgbd_tum.cc,stereo_kitti.cc,mono_tum.cc,mono_kitti.cc

# Build examples

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Examples/RGB-D)

add_executable(rgbd_tum
Examples/RGB-D/rgbd_tum.cc)
target_link_libraries(rgbd_tum ${PROJECT_NAME})

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Examples/Stereo)

add_executable(stereo_kitti
Examples/Stereo/stereo_kitti.cc)
target_link_libraries(stereo_kitti ${PROJECT_NAME})

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Examples/Monocular)

add_executable(mono_tum
Examples/Monocular/mono_tum.cc)
target_link_libraries(mono_tum ${PROJECT_NAME})

add_executable(mono_kitti
Examples/Monocular/mono_kitti.cc)
target_link_libraries(mono_kitti ${PROJECT_NAME})

總共生成了4個demo程序,先編譯,后link到前面生成的核心API庫上.

2.運行

  程序的運行並不像我們在使用win時的那么簡單,因為程序具有專業性,不具備相關專業基礎知識的人往往會在各種錯誤提示中浪費自己的時間.但總的來說也是有規律可循的,其實也簡單,僅僅是提供程序運行所必要的數據和配置文件即可.推薦大家保持良好的習慣,閱讀官方提供的運行說明.了解程序運行所需要的數據和配置,事先將其准備好,然后按照作者的教程運行.orbslam2的運行略.

3.練習:編譯運行作者提供的基於ros的demo

  請注意,以上的程序是普通的桌面程序,是直接利用驅動來讀取相機數據的,下面編譯基於ros的demo,當然這部分也是略

4.報錯

  軟件工程是個系統工程,一個小問題也會造成大錯誤.所以報錯是件很平常的事.即使是對於老手.面對報錯,我們應該

  1. 首先心態上要放平穩
  2. 其次要仔細查看錯誤提示,冷靜地做邏輯分析
  3. 最后要善用google,你要相信自己不是特殊的,你踩過的坑別人肯定也踩過

5.啟發

  如果看完一篇文章,沒有收獲,純屬浪費時間;如果看完一篇文章,能解決另一個問題,那么起碼不虧;如果看完一篇文章,能解決一類問題,你才叫正真的賺到了.讀到這里,如果你覺得沒有收獲,請關閉頁面,不要再浪費你自己的時間.如果你現在覺得學習了一些經驗技巧,那么就可以繼續了.

6.提高:重新啟程,觸類旁通

  你可以嘗試編譯運行較新的DSO,這里我們來試試高翔博士基於orbslam2改寫的orbslam2帶點雲程序

1

首先下載源碼.看過說明之后大概有了了解,但仍然不甚明了,不知orbslam2_modified.zip與ORB_SLAM2_modifiedy文件夾有什么異同.這是我遇到的第一個問題,詳細查看了ORB_SLAM2_modifiedy下的文件,確實有修改,且第三方庫完整,決定編譯這個文件夾.

2

接着照例查看CMakeLists.txt,其內容基本與orbslam相同,但是從邏輯上講應該增加點雲庫的,這里我們先不管它.然后查看build.sh的安裝腳本,過程也是與orbslam2大同小異,只是最后多了一個詞典轉換程序(提供),用於講詞典轉換成二進制的.經過查看之后,得出的結論是,編譯過程基本相似,改動主要在代碼層面.

3

通過剛才的文件查看,發現一些潛在問題,就是build文件夾已經存在,甚至第三方庫已經編譯成功.若干demo的可執行程序已經編譯出來了.表面上看是撿了便宜,不用編譯了,其實這樣是會帶來許多麻煩的.為什么這么說?

  1. cmake過的build文件夾內含有編譯信息,記錄了文件絕對路徑,你下載下來,接着make,會報錯說找不到文件.這時應該刪除build,重新cmake
  2. 已經在別人的機器上編譯好的程序或庫,在自己的機器上很有可能是不能運行的,尤其是這些程序需要動態庫的情況下,會出現一堆找不到各種動態庫

4

  • 開始編譯第三方庫,用make clean清理已經生成的,刪除build,重新編譯dbow和g2o兩個庫,成功.
  • 開始編譯核心API庫和demo,編譯錯誤,找不到pcl的一個頭文件,印證了前面的邏輯推理,在CMakeLists.txt中加pcl,繼續編譯,成功.
  • 開始編譯基於ros的demo,出現錯誤,提示出現相同文件.因為我機器上編譯過orbslam2的基於ros的demo,所以可能是ros包重復.把原來的包移個位置,繼續編譯,成功.

5

  • 最終選擇運行基於ros的rgbddemo程序,先確認數據與配置,詞典位置,相機參數文件位置,以及最重要的訂閱的話題,核對發布的話題,與rgbddemo中訂閱的話題是否一致,發現不一致,修改源程序的話題訂閱,重新編譯,通過.
  • ok,萬事俱備,先開一個發布kinect數據的launch,然后運行rgbddemo程序,最終效果如下所示:



7.沉思

  走到這里,你已經會編譯運行各種開源slam項目了,也許你是付出很多時間精力,學習各種cmake,shell教程,被各種報錯折磨,但是我還是要打擊你一下,構建開源項目是最基本的工程素養,外面隨便一個工程師都會.到目前為止我們只是編譯別人的工程,跑跑別人的代碼.

  • 但是你的ideal在哪兒?這是研究者之於工程師最本質的區別,你不僅要有工程師的能力,還要有創新的思維.
  • 在程序員,大學生,工程師泛濫的年代,作為研究生的你如何脫引而出,創造價值?
  • ......


免責聲明!

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



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