orb slam2 代码解析1
程序员文章站
2024-03-25 19:08:28
...
orb slam 2 代码解析1
orb slam 2 是一个完整的SLAM系统,包括了 VO,跟踪,及回环,是一种基于单目稀疏特征点的slam系统,使用orb 特征 作为视觉slam的特征点,有以下的特点。
- 使用ORB特征,实时性好
- 使用词袋模型进行回环检测,g2o图优化
- 支持多种传感器 单目、双目、RGB-D
- 支持ROS
我们主要是看看其中的代码实现。
git clone https://github.com/stevenlovegrove/Pangolin.git #下载代码
安装过程忽略,可自行搜索教程
打开下载代码的路径,主要有以下文件夹
- camke_modules #cmake 相关项,搜索需要的库
- Examples # 使用示例,包括ros下的示例,注意orbslam2主要代码编译之后只是生成库orb_slam2的动态库
- include # 主实现代码头文件
- src #实现代码
- Thirdparty #第三方依赖库,源码下载及编译
- Vocabulary #词袋模型
根据这个文件组织结构,代码阅读课从示例代码开始
决定预先看单目实现代码,我们挑选 /Examples/Monocular/mono_kitti.cc 文件作为解析的范例代码,看文件名就知道这个示例是使用kitti 数据集,而不需要使用真正的摄像头。
void LoadImages(const string &strSequence, vector<string> &vstrImageFilenames,
vector<double> &vTimestamps); //前置声明一个图像加载函数,实现在最后,主要实现读取文件路径及名称到vstrImageFilenames 里
接下来,我们看下main函数,看下整个系统的运行流程,(只挑选核心代码,精简所有主功能无关代码)
LoadImages(string(argv[3]), vstrImageFilenames, vTimestamps); //加载文件名称
ORB_SLAM2::System SLAM(argv[1],argv[2],ORB_SLAM2::System::MONOCULAR,true); //orb slam 核心管理类,所有功能都在这里实现
cv::Mat im;
for(int ni=0; ni<nImages; ni++) //根据路径一张张读图像
{
im = cv::imread(vstrImageFilenames[ni],CV_LOAD_IMAGE_UNCHANGED); //读图
// Pass the image to the SLAM system
SLAM.TrackMonocular(im,tframe); //跟踪及解析每张图
}
SLAM.Shutdown(); //关闭slam,释放资源,锁等
SLAM.SaveKeyFrameTrajectoryTUM("KeyFrameTrajectory.txt"); /存取关键帧,主要存储信息为关键帧的 R t矩阵 R转换为四元数表示
至此,我们看完了,处理流程,但由于主要的处理均在TrackMonocular函数中,所以我们需要再去分析 TrackMonocular 函数的实现,也即去看System.cc文件。
要阅读system文件,可先看头文件,了解大体的数据结构及功能,再看详细的代码实现,我们阅读代码的目的一般有以下几个
- 分析问题的整体解决及结构
- 关注实现过程的语言技巧及细节
- 关注算法实现思路
- 用来对原有库进行某种修改或扩展
对于orb_slam 这样的库,更重要的是算法实现和整体工程解决思路,所以我们更关注1,3点,第4点也可以关注,我们也会在其中分析如果需要修改时,可以怎么去实现相关功能
//System.h 简化版(数据结构部分,函数下回分解)
class System
{
public:
enum eSensor{
MONOCULAR=0, //传感器类型,单目,双目,RGBD
STEREO=1,
RGBD=2
};
public:
System(const string &strVocFile, const string &strSettingsFile, const eSensor sensor, const bool bUseViewer = true);
cv::Mat TrackStereo(const cv::Mat &imLeft, const cv::Mat &imRight, const double ×tamp);
cv::Mat TrackRGBD(const cv::Mat &im, const cv::Mat &depthmap, const double ×tamp);
cv::Mat TrackMonocular(const cv::Mat &im, const double ×tamp);
void ActivateLocalizationMode();
void DeactivateLocalizationMode();
bool MapChanged();
void Reset();
void Shutdown();
void SaveTrajectoryTUM(const string &filename);
void SaveKeyFrameTrajectoryTUM(const string &filename);
void SaveTrajectoryKITTI(const string &filename);
int GetTrackingState();
std::vector<MapPoint*> GetTrackedMapPoints();
std::vector<cv::KeyPoint> GetTrackedKeyPointsUn();
private:
eSensor mSensor; //传感器类型定义
ORBVocabulary* mpVocabulary; //词袋模型,用于位置识别和特征匹配
KeyFrameDatabase* mpKeyFrameDatabase; //关键帧数据结构,使用vector<keyframe*> 实现,存储关键帧
Map* mpMap; //地图 存储 mappoint keyframe 所有的指针
Tracking* mpTracker; //关键类,跟踪帧,并估计变换和相机位置,确定是否为关键帧,创建新的mappoint 并且当跟踪失败时重新定位
LocalMapping* mpLocalMapper; //局部地图,管理局部地图并执行局部BA(优化)
LoopClosing* mpLoopCloser; //回环检测,对每一个新的关键帧进行回环搜索,如果发现有回环则在新线程执行图优化和全局BA
Viewer* mpViewer;//绘制地图和当前相机位置
FrameDrawer* mpFrameDrawer; //帧绘制
MapDrawer* mpMapDrawer;//地图绘制
// System threads: Local Mapping, Loop Closing, Viewer.
// The Tracking thread "lives" in the main execution thread that creates the System object.
std::thread* mptLocalMapping; //关键实现,orb采用三线程并行处理,提高实时性能,此为局部绘图线程
std::thread* mptLoopClosing; //回环检测及处理线程
std::thread* mptViewer; //展示线程,绘制相关交互界面线程
// 使用三个锁和一些标志位实现 资源分配及调度 重置/ 模式改变/跟踪
std::mutex mMutexReset;
bool mbReset;
std::mutex mMutexMode;
bool mbActivateLocalizationMode;
bool mbDeactivateLocalizationMode;
int mTrackingState;
std::vector<MapPoint*> mTrackedMapPoints;
std::vector<cv::KeyPoint> mTrackedKeyPointsUn;
std::mutex mMutexState;
};
至此,本次简单分析就到这里啦。