ORB-SLAM2代码笔记(五):MapPoint
MapPoint
主要的成员变量
-
long unsigned int mnId; 地图点的Global id
-
static long unsigned int nNextId;
-
const long int mnFirstKFid; 创建该MapPoint的关键帧ID
如果是从帧中创建的话,会将普通帧的id存放于这里 -
const long int mnFirstFrame; 创建该MapPoint的帧ID(即每一关键帧有一个帧ID)
-
int nObs;被观测到的次数
用于跟踪的变量
-
float mTrackProjX; 当前地图点投影到某帧上后的坐标
-
float mTrackProjY; 当前地图点投影到某帧上后的坐标
-
float mTrackProjXR; 当前地图点投影到某帧上后的坐标(右目)
-
int mnTrackScaleLevel; 所处的尺度, 由其他的类进行操作
-
float mTrackViewCos; 被追踪到时,那帧相机看到当前地图点的视角
-
long unsigned int mnFuseCandidateForKF; 在局部建图线程中使用,表示被用来进行地图点融合的关键帧(存储的是这个关键帧的id)
-
long unsigned int mnLoopPointForKF;如果这个地图点对应的关键帧参与到了回环检测的过程中,那么在回环检测过程中已经使用了这个关键帧修正只有的位姿来修正了这个地图点,那么这个标志位置位
-
cv::Mat mPosGBA;全局BA优化后(如果当前地图点参加了的话),这里记录优化后的位姿
-
long unsigned int mnBAGlobalForKF;如果当前点的位姿参与到了全局BA优化,那么这个变量记录了那个引起全局BA的"当前关键帧"的id
-
static std::mutex mGlobalMutex;全局BA中对当前点进行操作的时候使用的互斥量
-
cv::Mat mWorldPos;MapPoint在世界坐标系下的坐标
-
std::map<KeyFrame*,size_t> mObservations; 观测到该MapPoint的KF和该MapPoint在KF中的索引
-
cv::Mat mNormalVector;该MapPoint平均观测方向(目前不知道是做什么的)
-
cv::Mat mDescriptor;每个3D点也有一个descriptor如果MapPoint与很多帧图像特征点对应(由keyframe来构造时),那么距离其它描述子的平均距离最小的描述子是最佳描述子;MapPoint只与一帧的图像特征点对应(由frame来构造时),那么这个特征点的描述子就是该3D点的描述子 (泡泡机器人的公开课里面有提到),通过 ComputeDistinctiveDescriptors() 得到的最优描述子
-
KeyFrame* mpRefKF;生成它的关键帧
-
Map* mpMap;所属的地图
-
std::mutex mMutexPos;对当前地图点位姿进行操作的时候的互斥量
-
std::mutex mMutexFeatures;对当前地图点的特征信息进行操作的时候的互斥量
-
其他
int mnVisible;
int mnFound;
bool mbBad;
MapPoint* mpReplaced;
float mfMinDistance;
float mfMaxDistance;
成员函数:
- 构造MapPoint分两种:参考帧是关键帧或参考帧是普通帧
// 参考帧是关键帧,该地图点将于许多帧关键帧对应,建立关键帧之间的共视关系
MapPoint::MapPoint(const cv::Mat &Pos, KeyFrame *pRefKF, Map* pMap)
// 参考帧是普通帧,该地图点只与当前普通帧的特征点对应
MapPoint::MapPoint(const cv::Mat &Pos, Map* pMap, Frame* pFrame, const int &idxF)
- void MapPoint::AddObservation(KeyFrame* pKF, size_t idx)添加观测
mObservations[pKF]=idx;添加观测
分成单目和双目两种清空添加观测,单目时观测次数加1,双目时观测次数加2. - void MapPoint::EraseObservation(KeyFrame* pKF) 删除某个关键帧对当前地图点的观测
先减少观测次数,还是分成单目和双目两种,和添加的时候类似
然后删除:mObservations.erase(pKF);
如果该keyFrame是参考帧,该Frame被删除后重新指定关键字
if(mpRefKF==pKF)
mpRefKF=mObservations.begin()->first;
当观测到该点的相机数目少于2时,丢弃该点:SetBadFlag()
- void MapPoint::SetBadFlag()告知可以观测到该MapPoint的Frame,该MapPoint已被删除
把mObservations转存到obs,然后mObservations.clear();
遍历obs告诉关键帧该MapPoint被删了 - void MapPoint::Replace(MapPoint* pMP)
当前地图点(this),替换成pMp。主要使用在闭环时,调整地图点和关键帧,建立新的关系:
设置当前地图点为坏点
mbBad=true;
关键帧将联系的this替换成pMap:
pKF->ReplaceMapPointMatch(mit->second, pMP);// KeyFrame中mit->second索引对应的地图点,用pMP替换掉原来的this
pMP->AddObservation(pKF,mit->second);// pMp地图点添加观测关键帧
-
void MapPoint::ComputeDistinctiveDescriptors()计算描述子
- 获取所有观测
observations=mObservations;
- 遍历所有观测,获取对应特征点描述子
- 计算描述子两两之间的距离
std::vector<std::vector<float> > Distances; Distances.resize(N, vector<float>(N, 0)); for (size_t i = 0; i<N; i++) { //和自己的距离当然是0 Distances[i][i]=0; for(size_t j=i+1;j<N;j++) { int distij = ORBmatcher::DescriptorDistance(vDescriptors[i],vDescriptors[j]); Distances[i][j]=distij; Distances[j][i]=distij; } }
- 计算每个描述子到其他描述子之间距离的中值
- 找到最小的中值 ,MapPoint描述子就是最小距离中值的描述子
-
void MapPoint::UpdateNormalAndDepth()
更新平均观测方向以及观测距离范围 -
int MapPoint::PredictScale(const float ¤tDist, KeyFrame* pKF)
在进行投影匹配的时候会给定特征点的搜索范围,考虑到处于不同尺度(也就是距离相机远近,位于图像金字塔中不同图层)的特征点受到相机旋转的影响不同,
因此会希望距离相机近的点的搜索范围更大一点,距离相机更远的点的搜索范围更小一点,所以要在这里,根据点到关键帧/帧的距离来估计它在当前的关键帧/帧中,
会大概处于哪个尺度
float ratio;
{
unique_lock<mutex> lock(mMutexPos);
ratio = mfMaxDistance/currentDist;
}
// 同时取log线性化
int nScale = ceil(log(ratio)/pKF->mfLogScaleFactor);
if(nScale<0)
nScale = 0;
else if(nScale>=pKF->mnScaleLevels)
nScale = pKF->mnScaleLevels-1;
return nScale;