逐个函数功能详细讲解ORB_SLAM2源码|ORB_SLAM2::System系统初始化
注意查看红框中的内容,对应的代码如下
构造函数成员初始化列表会对,头文件中的变量进行初始化。
创建对象的过程就是,就是在内存中开辟空间存储这些成员变量。
接下来我们看看系统构造函数System::System()都干了什么
初始化ORB-SLAM2的System系统类的实例化对象SLAM,并传入参数
初始化参数列表分别是:字典路径,参数文件路径,传感器类型,是否可视化
// Create SLAM system. It initializes all system threads and gets ready to process frames.
// 首先创建一个ORB_SLAM2的对象
ORB_SLAM2::System SLAM(argv[1],argv[2],ORB_SLAM2::System::RGBD,true);
//参数argv[1]:是DBOW词典的路径用于回环检测`path_to_vocabulary=ORB_SLAM2/Vocabulary/ORBvoc.txt`
//参数argv[2]:是相机参数文件`path_to_settings=ORB_SLAM2/Examples/ROS/ORB_SLAM2/src/d455.yaml`
//参数ORB_SLAM2::System::RGBD:是定义在头文件中的枚举类型,代表传感器的类型
//参数true:const bool类型的变量,代表不可更改的变量布尔变量,作用是是否打开显示窗口。
// Input sensor
enum eSensor{
MONOCULAR=0,
STEREO=1,
RGBD=2
};
首先调用的是ORB_SLAM2系统 System::System构造函数,然后根据参数判断传感器类型。
然后读取词典,主要代码实现在DBOW中,流程也是通过构造函数创建对象,然后对象调用函数进行读取。
然后创建地图,并将地图的对象传递给负责显示当前帧的显示窗口;
地图的对象和相机参数文件传递给负责地图的显示窗口。
创建Tracking对象mpTracker,传入的参数是上面创建好的
创建回环检测线程和对象
将局部建图线程对象传递给Tracking对象mpTracker
将回环检测对象传递给Tracking对象mpTracker
Tracking对象mpTracker传递给局部建图线程对象
将回环检测对象传递给局部建图线程对象
Tracking对象mpTracker传递给回环检测线程和对象
将局部建图线程对象传递给回环检测线程和对象
到此才完成ORB_SLAM2::System SLAM对象的创建
接下来详细看一下上面每一步创建的对象,执行相应的构造函数都做了那些工作,创建的对象如下图所示:
Tracking::Tracking(
System *pSys, //系统实例
ORBVocabulary* pVoc, //BOW字典
FrameDrawer *pFrameDrawer, //可视化帧
MapDrawer *pMapDrawer, //可视化地图点
Map *pMap, //地图
KeyFrameDatabase* pKFDB,
const string &strSettingPath, //配置文件路径
const int sensor): //传感器类型
mState(NO_IMAGES_YET),
mSensor(sensor),
mbOnlyTracking(false),
mbVO(false), //当前跟踪状态
mpORBVocabulary(pVoc),
mpKeyFrameDB(pKFDB),
mpInitializer(static_cast<Initializer*>(NULL)),
mpSystem(pSys),
mpViewer(NULL),
mpFrameDrawer(pFrameDrawer),
mpMapDrawer(pMapDrawer),
mpMap(pMap),
mnLastRelocFrameId(0)
{
// Load camera parameters from settings file
cv::FileStorage fSettings(strSettingPath, cv::FileStorage::READ);
float fx = fSettings["Camera.fx"];
float fy = fSettings["Camera.fy"];
float cx = fSettings["Camera.cx"];
float cy = fSettings["Camera.cy"];
// |fx 0 cx|
// K = |0 fy cy|
// |0 0 1 |
//相机内参矩阵
cv::Mat K = cv::Mat::eye(3,3,CV_32F);
K.at<float>(0,0) = fx;
K.at<float>(1,1) = fy;
K.at<float>(0,2) = cx;
K.at<float>(1,2) = cy;
K.copyTo(mK);
// 图像矫正系数
// [k1 k2 p1 p2 k3]
cv::Mat DistCoef(4,1,CV_32F);
DistCoef.at<float>(0) = fSettings["Camera.k1"];
DistCoef.at<float>(1) = fSettings["Camera.k2"];
DistCoef.at<float>(2) = fSettings["Camera.p1"];
DistCoef.at<float>(3) = fSettings["Camera.p2"];
const float k3 = fSettings["Camera.k3"];
//有些相机的畸变系数中会没有k3项
if(k3!=0)
{
DistCoef.resize(5);
DistCoef.at<float>(4) = k3;
}
DistCoef.copyTo(mDistCoef);
// 双目摄像头baseline * fx 50
mbf = fSettings["Camera.bf"];
// 帧率
float fps = fSettings["Camera.fps"];
if(fps==0)
fps=30;
// Max/Min Frames to insert keyframes and to check relocalisation
mMinFrames = 0;
mMaxFrames = fps;
// 1:RGB 0:BGR
int nRGB = fSettings["Camera.RGB"];
mbRGB = nRGB;
// Load ORB parameters
// 每一帧提取的特征点数 1000
int nFeatures = fSettings["ORBextractor.nFeatures"];
// 图像建立金字塔时的变化尺度 1.2
float fScaleFactor = fSettings["ORBextractor.scaleFactor"];
// 尺度金字塔的层数 8
int nLevels = fSettings["ORBextractor.nLevels"];
// 提取fast特征点的默认阈值 20
int fIniThFAST = fSettings["ORBextractor.iniThFAST"];
// 如果默认阈值提取不出足够fast特征点,则使用最小阈值 8
int fMinThFAST = fSettings["ORBextractor.minThFAST"];
mpORBextractorLeft = new ORBextractor(
nFeatures,
fScaleFactor,
nLevels,
fIniThFAST,
fMinThFAST);
if(sensor==System::STEREO)
mpORBextractorRight = new ORBextractor(nFeatures,fScaleFactor,nLevels,fIniThFAST,fMinThFAST);
if(sensor==System::MONOCULAR)
mpIniORBextractor = new ORBextractor(2*nFeatures,fScaleFactor,nLevels,fIniThFAST,fMinThFAST);
if(sensor==System::STEREO || sensor==System::RGBD)
{
// 判断一个3D点远/近的阈值 mbf * 35 / fx
// ThDepth其实就是表示基线长度的多少倍
mThDepth = mbf*(float)fSettings["ThDepth"]/fx;
cout << endl << "Depth Threshold (Close/Far Points): " << mThDepth << endl;
}
if(sensor==System::RGBD)
{
// 深度相机disparity转化为depth时的因子
mDepthMapFactor = fSettings["DepthMapFactor"];
if(fabs(mDepthMapFactor)<1e-5)
mDepthMapFactor=1;
else
mDepthMapFactor = 1.0f/mDepthMapFactor;
}
}