system函数为整个算法的入口,包括所有线程的开辟,各个模块的初始化,及其摄像机类型的选择;
//构建函数
/*
input:
字典, 类型(mono,rgbd,stereo),参数,mapfile, 是否导入地图
*/
System::System(const string strVocFile, const eSensor sensor, ORBParameters& parameters,
const std::string & map_file, bool load_map): // map serialization addition
mSensor(sensor), mbReset(false),mbActivateLocalizationMode(false), mbDeactivateLocalizationMode(false),
map_file(map_file), load_map(load_map)
system构造函数参数包括离线训练的词袋字典文件名,camera类型,ORB特征点提取参数,也可以增加已知地图纯定位功能。
//Load ORB Vocabulary
cout << endl << "Loading ORB Vocabulary." << endl;
// 创建字典
mpVocabulary = new ORBVocabulary();
//try to load from the binary file,导入2进制文件
bool bVocLoad = mpVocabulary->loadFromBinFile(strVocFile+".bin");
原始开源代码调用词典为txt文本,众所周知读入txt的文本的速度十分耗时,导致slam启动较慢。已有人将其改进为bin文件存储和读取,以此可提高启动速度。
// begin map serialization addition
// load serialized map
// 是否载入已有地图
if (load_map && LoadMap(map_file)) {
std::cout << "Using loaded map with " << mpMap->MapPointsInMap() << " points\n" << std::endl;
}
else {
// 新建地图,则需创建一个空的地图对象,
//Create KeyFrame Database
// 初始化关键帧数据对象,主要存储字典里包含的值,用于重定位和闭环
mpKeyFrameDatabase = new KeyFrameDatabase(*mpVocabulary);
//Create the Map
// 创建map数据,应该是特征点和对应的keypose
mpMap = new Map();
}
// end map serialization addition
orb-slam2开始slam时需创建一个新的空的map对象。同时更为重要创建一个KeyFrameDatabase对象,此对象用于存储关键帧的在词典中的词袋向量,后续的闭环和重定位也是基于此词袋数据进行搜索匹配。
//Initialize the Tracking thread
//(it will live in the main thread of execution, the one that called this constructor)
// 初始化前端线程
mpTracker = new Tracking(this, mpVocabulary, mpFrameDrawer,
mpMap, mpKeyFrameDatabase, mSensor, parameters);
初始化三个线程中tracking线程;
//Initialize the Local Mapping thread and launch
// 初始化建图线程
mpLocalMapper = new LocalMapping(mpMap, mSensor==MONOCULAR);
mptLocalMapping = new thread(&ORB_SLAM2::LocalMapping::Run,mpLocalMapper);
初始化三个线程中Local Mapping线程;
//Initialize the Loop Closing thread and launch
// 初始化闭环线程
mpLoopCloser = new LoopClosing(mpMap, mpKeyFrameDatabase, mpVocabulary, mSensor!=MONOCULAR);
mptLoopClosing = new thread(&ORB_SLAM2::LoopClosing::Run, mpLoopCloser);
初始化三个线程中loop closing线程;
//Set pointers between threads
// 三个线程间存在联系
mpTracker->SetLocalMapper(mpLocalMapper);
mpTracker->SetLoopClosing(mpLoopCloser);
mpLocalMapper->SetTracker(mpTracker);
mpLocalMapper->SetLoopCloser(mpLoopCloser);
mpLoopCloser->SetTracker(mpTracker);
mpLoopCloser->SetLocalMapper(mpLocalMapper);
currently_localizing_only_ = false;
}
由于三个线程需要存在联系,没有采用的全局同一变量进行共享,而是将每个线程都可访问另外两个其他线程;
void System::TrackMonocular(const cv::Mat &im, const double ×tamp)
单目入口参数仅有一个mat图像入口和对应时间戳;
// 是否更改纯定位模式
if(mbActivateLocalizationMode)
{
mpLocalMapper->RequestStop();
// Wait until Local Mapping has effectively stopped
while(!mpLocalMapper->isStopped())
{
std::this_thread::sleep_for(std::chrono::microseconds(1000));
}
mpTracker->InformOnlyTracking(true);
mbActivateLocalizationMode = false;
}
// 取消重定位
if(mbDeactivateLocalizationMode)
{
mpTracker->InformOnlyTracking(false);
mpLocalMapper->Release();
mbDeactivateLocalizationMode = false;
}
orbslam支持纯定位模式,当已有图时(可以外部读入的地图,也可是刚刚新建的地图),可不再更新地图,仅输出定位。在slam过程中支持动态模式切换;
if(mbReset)
{
mpTracker->Reset();
mbReset = false;
}
支持slam过程中重新reset整个SLAM,即重新开始slam。
// 开始slam,传入图像,输出位姿
cv::Mat Tcw = mpTracker->GrabImageMonocular(im,timestamp);
开启单目跟踪功能;
双目摄像机入口
void System::TrackStereo(const cv::Mat &imLeft, const cv::Mat &imRight, const double ×tamp)
rgbd 摄像机入口
void System::TrackRGBD(const cv::Mat &im, const cv::Mat &depthmap, const double ×tamp)
三种摄像机slam入口初始化基本一致,主要区别在图片类型不一样。