ORB-SLAM2代码详解03: 地图点MapPoint_ncepu_Chen的博客-CSDN博客_orbslam地图点
地图点是三维点,有唯一的id,不同帧的特征点可能对应同一个三维点。
地图点的世界坐标保存在mWorldPos中,它与关键帧的观测关系则保存在mObservations中。其中mObservations是一个key-value
结构,key
为观测到的某个关键帧,value
为当前地图点在该关键帧中的索引,这个索引是该关键帧里面的一个成员变量mvpMapPoints中的索引。mObservations中的nObs
记录了当前地图点被多少个关键帧相机观测到了(单目关键帧每次观测算1
个相机,双目/RGBD帧每次观测算2
个相机)
观测尺度
平均观测距离:mfMinDistance和mfMaxDistance
特征点的观测距离与图像金字塔中的层数线性相关,平均观测距离的上下限由成员变量mfMinDistance和mfMaxDistance表示
mfMaxDistance
表示若地图点匹配在某特征提取器图像金字塔第7
层上的某特征点时的观测距离值mfMinDistance
表示若地图点匹配在某特征提取器图像金字塔第0
层上的某特征点时的观测距离值
更新平均观测方向和距离updateNormalAndDepth()
平均观测方向是根据mObservations
中所有观测到本地图点的关键帧取平均得到的,平均观测距离是根据参考关键帧得到的
构造函数中,创建该地图点的参考帧被设为参考关键帧.
若当前地图点对参考关键帧的观测被删除,则取第一个观测到当前地图点的关键帧做参考关键帧.
void MapPoint::UpdateNormalAndDepth() {
// step1. 获取地图点相关信息
map<KeyFrame *, size_t> observations;
KeyFrame *pRefKF;
cv::Mat Pos;
{
unique_lock<mutex> lock1(mMutexFeatures);
unique_lock<mutex> lock2(mMutexPos);
observations = mObservations;
pRefKF = mpRefKF;
Pos = mWorldPos.clone();
}
// step2. 根据观测到当前地图点的关键帧取平均计算平均观测方向
cv::Mat normal = cv::Mat::zeros(3, 1, CV_32F);
int n = 0;
for (KeyFrame *pKF : observations.begin()) {
normal = normal + normali / cv::norm(mWorldPos - pKF->GetCameraCenter());
n++;
}
// step3. 根据参考帧计算平均观测距离
cv::Mat PC = Pos - pRefKF->GetCameraCenter();
const float dist = cv::norm(PC);
const int level = pRefKF->mvKeysUn[observations[pRefKF]].octave;
const float levelScaleFactor = pRefKF->mvScaleFactors[level];
const int nLevels = pRefKF->mnScaleLevels;
{
unique_lock<mutex> lock3(mMutexPos);
mfMaxDistance = dist * levelScaleFactor;
mfMinDistance = mfMaxDistance / pRefKF->mvScaleFactors[nLevels - 1];
mNormalVector = normal / n;
}
}
当地图点本身或关键帧对该地图点的观测发生变化,就应该调用函数UpdateNormalAndDepth()
更新其观测尺度和方向信息.
地图点的特征描述子
一个地图点对应多个不同关键帧的特征点,所以将地图点的特征描述子定义为所有观测关键帧中描述子的中位数,该描述子与其他所有描述子的中值距离最小
通过比较地图点的描述子和图片特征点的描述子,可以实现3D-2D的匹配。
地图点的删除(先标记,再删除)
地图点的替换(先标记当前地图点,将替换后的地图点叠加,再实际上删除当前地图点)
MapPoint生命周期
创建MapPoint:
1. Tracking初始化
2. Tracking创建新的关键帧,新关键帧会带来新的地图点
3. Tracking恒速跟踪模型中产生临时地图点,仅用于跟踪,不进入地图。
4. LocalMapping中将当前关键帧与前一关键帧基尼下嗯匹配,生成新的地图点。
删除MapPoint:
1. LocalMapping中删除坏点
2. 当地图点对关键帧的观测少于2个,无法三角化,删除
替换MapPoint:
LoopClosing闭环矫正