ORB_SLAM2程序入口(System.cc)
程序入口
??ORB_SLAM2的程序入口為src/System.cc。在CMakeList.txt中可知,ORB_SLAM2的可執行程序為:
Examples/Stereo/stereo_kitti.cc等。
add_executable(stereo_kitti
Examples/Stereo/stereo_kitti.cc)
target_link_libraries(stereo_kitti ${PROJECT_NAME})add_executable(stereo_euroc
Examples/Stereo/stereo_euroc.cc)
target_link_libraries(stereo_euroc ${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})add_executable(mono_euroc
Examples/Monocular/mono_euroc.cc)
target_link_libraries(mono_euroc ${PROJECT_NAME})
??在Examples/Stereo/stereo_kitti.cc程序中可見:argc===4,即在命令行中輸入的四部分:1)可執行程序。2)詞典。3)配置文件。4)數據集。
./Examples/Stereo/stereo_kitti Vocabulary/ORBvoc.txt ./Examples/Stereo/KITTI00-02.yaml /home/dk/桌面/kitti/00
??接下來,筆者以./Examples/Monocular/EuRoC_TImeStamps/mono_kitti.cc為例。因為其包含單目初始化,比較經典。
?
讀取圖片的路徑+名稱、時間戳
??首先使用LoadImages函數獲得左右目圖像以及時間戳。
?
初始化整個系統
??而后調用ORB_SLAM2::System的構造函數初始化整個系統。
?
主循環
??調用SLAM.TrackMonocular處理每一幀輸入的圖片。如果處理一幀所用時間小于兩幀之間實際拍攝所間隔時間,則用usleep函數停頓相應時間再進行下一輪循環。
double ttrack= std::chrono::duration_cast<std::chrono::duration<double> >(t2 - t1).count();vTimesTrack[ni]=ttrack;// Wait to load the next framedouble T=0;if(ni<nImages-1)T = vTimestamps[ni+1]-tframe;else if(ni>0)T = tframe-vTimestamps[ni-1];if(ttrack<T)usleep((T-ttrack)*1e6);
?
終止
??結束所有線程,計算出平均每幀的運行時間,并保存關鍵幀的位姿信息。
// 結束所有線程SLAM.Shutdown();// 統計時間sort(vTimesTrack.begin(),vTimesTrack.end());float totaltime = 0;for(int ni=0; ni<nImages; ni++){totaltime+=vTimesTrack[ni];}cout << "-------" << endl << endl;cout << "median tracking time: " << vTimesTrack[nImages/2] << endl;cout << "mean tracking time: " << totaltime/nImages << endl;// 保存關鍵幀位姿信息SLAM.SaveKeyFrameTrajectoryTUM("KeyFrameTrajectory.txt");
?
?
System.cc
??主程序的實現文件。在其中聲明了界面信息,導入了關鍵幀數據庫,開啟了三個線程(追蹤線程、局部建圖線程、回環檢測線程)。
構造函數
//系統的構造函數,將會啟動其他的線程
System::System(const string &strVocFile, //詞典文件路徑const string &strSettingsFile, //配置文件路徑const eSensor sensor, //傳感器類型const bool bUseViewer): //是否使用可視化界面mSensor(sensor), //初始化傳感器類型mpViewer(static_cast<Viewer*>(NULL)), //空。。。對象指針? TODO mbReset(false), //無復位標志mbActivateLocalizationMode(false), //沒有這個模式轉換標志mbDeactivateLocalizationMode(false) //沒有這個模式轉換標志
(1)strVocFile為詞典路徑:Vocabulary路徑下的ORBvoc.txt。
(2)strSettingsFile:配置文件路徑,即Examples目錄下的yaml文件。其中包含一些配置信息,如相機的內參,特征點的提取數量,圖像金字塔的信息等。
(3)sensor:傳感器的類型,在system.h中有設置。
// 單目、雙目、RGB-Denum eSensor{MONOCULAR=0,STEREO=1,RGBD=2};
(4)bUseViewer:是否使用可視化界面,即運行ORB_SLAM2中的運行界面。
?
界面的聲明信息
// Output welcome messagecout << endl <<"ORB-SLAM2 Copyright (C) 2014-2016 Raul Mur-Artal, University of Zaragoza." << endl <<"This program comes with ABSOLUTELY NO WARRANTY;" << endl <<"This is free software, and you are welcome to redistribute it" << endl <<"under certain conditions. See LICENSE.txt." << endl << endl;// 輸出當前傳感器類型cout << "Input sensor was set to: ";if(mSensor==MONOCULAR)cout << "Monocular" << endl;else if(mSensor==STEREO)cout << "Stereo" << endl;else if(mSensor==RGBD)cout << "RGB-D" << endl;//Check settings filecv::FileStorage fsSettings(strSettingsFile.c_str(), //將配置文件名轉換成為字符串cv::FileStorage::READ); //只讀//如果打開失敗,就輸出調試信息if(!fsSettings.isOpened()){cerr << "Failed to open settings file at: " << strSettingsFile << endl;//然后退出exit(-1);}//Load ORB Vocabularycout << endl << "Loading ORB Vocabulary. This could take a while..." << endl;//建立一個新的ORB字典mpVocabulary = new ORBVocabulary();//獲取字典加載狀態bool bVocLoad = mpVocabulary->loadFromTextFile(strVocFile);//如果加載失敗,就輸出調試信息if(!bVocLoad){cerr << "Wrong path to vocabulary. " << endl;cerr << "Falied to open at: " << strVocFile << endl;//然后退出exit(-1);}//否則則說明加載成功cout << "Vocabulary loaded!" << endl << endl;
?
構建關鍵幀數據庫
??ORB_SLAM2是基于關鍵幀優化的SLAM系統,因此需要一個關鍵幀數據庫。
??關鍵幀數據庫類在KeyFrameDatabase.h中定義,主要包含訓練好的詞典,以及單詞的出現情況與關鍵幀索引間的聯系。
??該庫在重定位和回環檢測時被使用,用于檢測與當前幀最相似的關鍵幀。
mpKeyFrameDatabase = new KeyFrameDatabase(*mpVocabulary);
?
初始化地圖與繪制器
??初始化一個地圖類,主要包含該地圖中的關鍵幀和路標點。
??構造繪圖變量,用于繪制可視化界面(包括關鍵幀與路標點)。
mpMap = new Map();
mpFrameDrawer = new FrameDrawer(mpMap);
mpMapDrawer = new MapDrawer(mpMap, strSettingsFile);
?
開啟三個線程
??開啟三個線程:Tracking、LocalMapping、LoopClosing。(三者之間應該有個溝通,否則數據會紊亂)
??其中Tracking為主線程(初始化追蹤線程),LocalMapping、LoopClosing為子線程。子線程的運行函數分別為:&ORB_SLAM2::LocalMapping::Run、&ORB_SLAM2::LoopClosing::Run。使用thread加入到子線程中。根據輸入的參數bUseViewer決定是否啟動可視化線程。
mpTracker = new Tracking(this, //現在還不是很明白為什么這里還需要一個this指針 TODO mpVocabulary, //字典mpFrameDrawer, //幀繪制器mpMapDrawer, //地圖繪制器mpMap, //地圖mpKeyFrameDatabase, //關鍵幀地圖strSettingsFile, //設置文件路徑mSensor); //傳感器類型iomanip//初始化局部建圖線程并運行//Initialize the Local Mapping thread and launchmpLocalMapper = new LocalMapping(mpMap, //指定使iomanipmSensor==MONOCULAR); // TODO 為什么這個要設置成為MONOCULAR???//運行這個局部建圖線程mptLocalMapping = new thread(&ORB_SLAM2::LocalMapping::Run, //這個線程會調用的函數mpLocalMapper); //這個調用函數的參數//Initialize the Loop Closing thread and launchiomanipmpLoopCloser = new LoopClosing(mpMap, //地圖mpKeyFrameDatabase, //關鍵幀數據庫mpVocabulary, //ORB字典mSensor!=MONOCULAR); //當前的傳感器是否是單目//創建回環檢測線程mptLoopClosing = new thread(&ORB_SLAM2::LoopClosing::Run, //線程的主函數mpLoopCloser); //該函數的參數if(bUseViewer){//如果指定了,程序的運行過程中需要運行可視化部分//新建viewermpViewer = new Viewer(this, //又是這個mpFrameDrawer, //幀繪制器mpMapDrawer, //地圖繪制器mpTracker, //追蹤器strSettingsFile); //配置文件的訪問路徑//新建viewer線程mptViewer = new thread(&Viewer::Run, mpViewer);//給運動追蹤器設置其查看器mpTracker->SetViewer(mpViewer);}
?
建立各個線程間的聯系
//設置進程間的指針mpTracker->SetLocalMapper(mpLocalMapper);mpTracker->SetLoopClosing(mpLoopCloser);mpLocalMapper->SetTracker(mpTracker);mpLocalMapper->SetLoopCloser(mpLoopCloser);mpLoopCloser->SetTracker(mpTracker);mpLoopCloser->SetLocalMapper(mpLocalMapper);
?
?
處理單目相機傳入的每一幀圖片
判斷系統的模式是否發生了改變
cv::Mat System::TrackMonocular(const cv::Mat &im, const double ×tamp)
??主循環中的函數System::TrackMonocular。
(1)判斷系統的模式是否發生了變化。即激活定位模式和關閉定位模式。
(2)如果開啟定位模式,則關閉局部建圖線程,且標志位 置為true。
(3)如果關閉定位模式,則開啟局部建圖線程,且標志位 置為false。
if(mbActivateLocalizationMode){mpLocalMapper->RequestStop();// Wait until Local Mapping has effectively stoppedwhile(!mpLocalMapper->isStopped()){usleep(1000);}// 局部地圖關閉以后,只進行追蹤的線程,只計算相機的位姿,沒有對局部地圖進行更新// 設置mbOnlyTracking為真mpTracker->InformOnlyTracking(true);// 關閉線程可以使得別的線程得到更多的資源mbActivateLocalizationMode = false;}// 如果mbDeactivateLocalizationMode是true,局部地圖線程就被釋放, 關鍵幀從局部地圖中刪除.if(mbDeactivateLocalizationMode){mpTracker->InformOnlyTracking(false);mpLocalMapper->Release();mbDeactivateLocalizationMode = false;}
?
判斷是否需要重置
??當重定位失敗之后,系統無法定位,此時需要重置。
unique_lock<mutex> lock(mMutexReset);if(mbReset){mpTracker->Reset();mbReset = false;}
?
計算位姿
??計算相機位姿(相對于世界坐標的位姿變換),
cv::Mat Tcw = mpTracker->GrabImageMonocular(im,timestamp);
?
更新系統變量
??包括更新系統的跟蹤狀態(mTrackingState),當前幀的路標點(mTrackedMapPoints),當前幀的特征點(mTrackedKeyPointsUn)。
?
?
保存相機軌跡
??以數據集的格式保存相機軌跡。使用當前幀相對于參考關鍵幀的轉換+參考關鍵幀相對于第一個關鍵幀的轉換計算出當前幀相對于第一個關鍵幀(世界坐標)的轉換。
void System::SaveTrajectoryTUM(const string &filename)
總結
以上是生活随笔為你收集整理的ORB_SLAM2程序入口(System.cc)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ORB_SLAM2源码:ORBmatch
- 下一篇: 不能上河图是谁画的呢?