mCurrentFrame = Frame(
mImGray,
timestamp,
mpORBextractorLeft, //正常运行的时的ORB特征点提取器,提取指定数目特征点
mpORBVocabulary,
mK,
mDistCoef,
mbf,
mThDepth);
/*
* @brief 用参考关键帧的地图点来对当前普通帧进行跟踪
*
* Step 1:将当前普通帧的描述子转化为BoW向量
* Step 2:通过词袋BoW加速当前帧与参考帧之间的特征点匹配
* Step 3: 将上一帧的位姿态作为当前帧位姿的初始值
* Step 4: 通过优化3D-2D的重投影误差来获得位姿
* Step 5:剔除优化后的匹配点中的外点
* @return 如果匹配数超10,返回true
*
*/
bool Tracking::TrackReferenceKeyFrame()
{
第一步:初始化MonocularInitialization();
if(!mCurrentFrame.mTcw.empty())
{
// 计算相对姿态Tcr = Tcw * Twr, Twr = Trw^-1
cv::Mat Tcr = mCurrentFrame.mTcw*mCurrentFrame.mpReferenceKF->GetPoseInverse();
//保存各种状态
mlRelativeFramePoses.push_back(Tcr);
mlpReferences.push_back(mpReferenceKF);
mlFrameTimes.push_back(mCurrentFrame.mTimeStamp);
mlbLost.push_back(mState==LOST);
}
bool Tracking::Relocalization()
{// Step 1:计算当前帧特征点的词袋向量
Step 2:用词袋找到与当前帧相似的候选关键帧
Step 3:遍历所有的候选关键帧,通过词袋进行快速匹配,用匹配结果初始化PnP Solver
Step 4: 通过一系列操作,直到找到能够匹配上的关键帧
bool Tracking::TrackWithMotionModel()
{
...
// Step 4:利用3D-2D投影关系,优化当前帧位姿
Optimizer::PoseOptimization(&mCurrentFrame);
Tracking的构造函数,需要系统的指针,BOW字典指针,关键帧词代库指针,
配置文件路径,传感器类型
绘图器指针:帧、地图点,地图句柄
///构造函数
Tracking::Tracking(
System *pSys, //系统实例
ORBVocabulary* pVoc, //BOW字典
FrameDrawer *pFrameDrawer, //帧绘制器
MapDrawer *pMapDrawer, //地图点绘制器
Map *pMap, //地图句柄
KeyFrameDatabase* pKFDB, //关键帧产生的词袋数据库
const string &strSettingPath, //配置文件路径
const int sensor):
构造函数继承了一个叫System类的指针,pSys指针的内容的public变量和函数可以被Tracking访问,比如mpSystem->Reset();
System* mpSystem;//指向系统实例的指针
mpSystem(pSys),
this指向当前对象的地址
Tracking::Tracking(
System *pSys, //系统实例
const int sensor): //传感器类型
mSensor(sensor),
mpSystem(pSys),
{
}
在Tracking头文件中有protected:私有成员变量System* mpSystem;,在Tracking.cc文件中有构造函数Tracking::Tracking(System *pSys):mpSystem(pSys){},将mpSystem初始化为传入的指针pSys,是什么时候传入的呢?在System.cc文件中有mpTracker = new Tracking(this);这个this就是System的构造函数。
Tracking类有哪些变量?
跟踪状态类型,eTrackingState
enum eTrackingState{
SYSTEM_NOT_READY=-1, //系统没有准备好的状态,一般就是在启动后加载配置文件和词典文件时候的状态
NO_IMAGES_YET=0, //当前无图像
NOT_INITIALIZED=1, //有图像但是没有完成初始化
OK=2, //正常时候的工作状态
LOST=3 //系统已经跟丢了的状态
};
eTrackingState mState;///跟踪状态
eTrackingState mLastProcessedState;///上一帧的跟踪状态.这个变量在绘制当前帧的时候会被使用到
int mSensor;//传感器类型,这个在创建系统时,会传入
Frame类
Frame mCurrentFrame;//下面是双目创建一个mCurrentFrame
mCurrentFrame = Frame(
mImGray, //左目图像
imGrayRight, //右目图像
timestamp, //时间戳
mpORBextractorLeft, //左目特征提取器
mpORBextractorRight, //右目特征提取器
mpORBVocabulary, //字典
mK, //内参矩阵
mDistCoef, //去畸变参数
mbf, //基线长度
mThDepth); //远点,近点的区分阈值
Frame mInitialFrame;//一般这个初始化帧就是mInitialFrame = Frame(mCurrentFrame);
Frame mLastFrame;//差不多的来历mLastFrame = Frame(mCurrentFrame);
KeyFrame* mpLastKeyFrame;//上一关键帧
KeyFrame* mpReferenceKF;//参考关键帧
mCurrentFrame.mpReferenceKF = mpReferenceKF;
// 将最新的关键帧作为当前帧的参考关键帧
list<KeyFrame*> mlpReferences;//参考关键帧
std::vector<KeyFrame*> mvpLocalKeyFrames;//局部关键帧集合
在特征匹配(Feature Matching)的过程中,可以通过比较关键帧和当前帧之间的特征点来确定它们之间的关系。在相机追踪中,可以通过运动估计(Motion Estimation)和特征重投影(Feature Re-projection)来估计当前帧与关键帧之间的相对位姿关系。在回环检测中,可以通过比较关键帧和当前帧之间的相似性来检测是否有回环出现。在Tracking.cc中有判断当前帧是否需要插入关键帧
/**
* @brief 判断当前帧是否需要插入关键帧
*
* Step 1:纯VO模式下不插入关键帧,如果局部地图被闭环检测使用,则不插入关键帧
* Step 2:如果距离上一次重定位比较近,或者关键帧数目超出最大限制,不插入关键帧
* Step 3:得到参考关键帧跟踪到的地图点数量
* Step 4:查询局部地图管理器是否繁忙,也就是当前能否接受新的关键帧
* Step 5:对于双目或RGBD摄像头,统计可以添加的有效地图点总数 和 跟踪到的地图点数量
* Step 6:决策是否需要插入关键帧
* @return true 需要
* @return false 不需要
*/
bool Tracking::NeedNewKeyFrame()
{
cv::Mat
代表了一个多维的数值矩阵
cv::Mat mImGray;
cv::Mat mK;//相机内参数矩阵
cv::Mat mDistCoef;//相机去畸变参数
cv::Mat mVelocity;
list<cv::Mat> mlRelativeFramePoses;
std::vector<cv::Point2f> mvbPrevMatched;
std::vector<cv::Point3f> mvIniP3D;
数组容器
std::vector<int>
是一个可以自动调整大小的数组容器
std::vector<int> mvIniLastMatches;
std::vector<int> mvIniMatches;
bool mbOnlyTracking;
bool mbVO;
bool mbRGB;
list<bool> mlbLost;
Tracking类有哪些函数?
不需要参数的函数
void Reset();
void Track();
void StereoInitialization();
void CheckReplacedInLastFrame();
void UpdateLastFrame();