目录
0.前言1.简述2.头文件3.源文件3.1. Run()3.2. ProcessNewKeyFrame()3.3. MapPointCulling()3.4. CreateNewMapPoints()3.5. SearchInNeighbors()3.6. KeyFrameCulling()
0.前言
注释代码已公开,欢迎交流~~ 注释代码已公开,欢迎交流 其他系列文章地址
1.简述
2.头文件
class LocalMapping
{
public:
LocalMapping(Map
* pMap
, const float bMonocular
);
void SetLoopCloser(LoopClosing
* pLoopCloser
);
void SetTracker(Tracking
* pTracker
);
void Run();
void InsertKeyFrame(KeyFrame
* pKF
);
void RequestStop();
void RequestReset();
bool Stop();
void Release();
bool isStopped();
bool stopRequested();
bool AcceptKeyFrames();
void SetAcceptKeyFrames(bool flag
);
bool SetNotStop(bool flag
);
void InterruptBA();
void RequestFinish();
bool isFinished();
int KeyframesInQueue(){
unique_lock
<std
::mutex
> lock(mMutexNewKFs
);
return mlNewKeyFrames
.size();
}
protected:
bool CheckNewKeyFrames();
void ProcessNewKeyFrame();
void CreateNewMapPoints();
void MapPointCulling();
void SearchInNeighbors();
void KeyFrameCulling();
cv
::Mat
ComputeF12(KeyFrame
* &pKF1
, KeyFrame
* &pKF2
);
cv
::Mat
SkewSymmetricMatrix(const cv
::Mat
&v
);
bool mbMonocular
;
void ResetIfRequested();
bool mbResetRequested
;
std
::mutex mMutexReset
;
bool CheckFinish();
void SetFinish();
bool mbFinishRequested
;
bool mbFinished
;
std
::mutex mMutexFinish
;
Map
* mpMap
;
LoopClosing
* mpLoopCloser
;
Tracking
* mpTracker
;
std
::list
<KeyFrame
*> mlNewKeyFrames
;
KeyFrame
* mpCurrentKeyFrame
;
std
::list
<MapPoint
*> mlpRecentAddedMapPoints
;
std
::mutex mMutexNewKFs
;
bool mbAbortBA
;
bool mbStopped
;
bool mbStopRequested
;
bool mbNotStop
;
std
::mutex mMutexStop
;
bool mbAcceptKeyFrames
;
std
::mutex mMutexAccept
;
};
3.源文件
3.1. Run()
void LocalMapping
::Run()
{
mbFinished
= false;
while(1)
{
SetAcceptKeyFrames(false);
if(CheckNewKeyFrames())
{
ProcessNewKeyFrame();
MapPointCulling();
CreateNewMapPoints();
if(!CheckNewKeyFrames())
{
SearchInNeighbors();
}
mbAbortBA
= false;
if(!CheckNewKeyFrames() && !stopRequested())
{
if(mpMap
->KeyFramesInMap()>2)
Optimizer
::LocalBundleAdjustment(mpCurrentKeyFrame
,&mbAbortBA
, mpMap
);
KeyFrameCulling();
}
mpLoopCloser
->InsertKeyFrame(mpCurrentKeyFrame
);
}
else if(Stop())
{
while(isStopped() && !CheckFinish())
{
usleep(3000);
}
if(CheckFinish())
break;
}
ResetIfRequested();
SetAcceptKeyFrames(true);
if(CheckFinish())
break;
usleep(3000);
}
SetFinish();
}
3.2. ProcessNewKeyFrame()
/**
* @brief 处理列表中的关键帧
*
* - 计算Bow,加速三角化新的MapPoints
* - 关联当前关键帧至MapPoints,并更新MapPoints的平均观测方向和观测距离范围
* - 插入关键帧,更新Covisibility图和Essential图,以及spanningtree
*/
void LocalMapping
::ProcessNewKeyFrame()
{
{
unique_lock
<mutex
> lock(mMutexNewKFs
);
mpCurrentKeyFrame
= mlNewKeyFrames
.front();
mlNewKeyFrames
.pop_front();
}
mpCurrentKeyFrame
->ComputeBoW();
const vector
<MapPoint
*> vpMapPointMatches
= mpCurrentKeyFrame
->GetMapPointMatches();
for(size_t i
=0; i
<vpMapPointMatches
.size(); i
++)
{
MapPoint
* pMP
= vpMapPointMatches
[i
];
if(pMP
)
{
if(!pMP
->isBad())
{
if(!pMP
->IsInKeyFrame(mpCurrentKeyFrame
))
{
pMP
->AddObservation(mpCurrentKeyFrame
, i
);
pMP
->UpdateNormalAndDepth();
pMP
->ComputeDistinctiveDescriptors();
}
else
{
mlpRecentAddedMapPoints
.push_back(pMP
);
}
}
}
}
mpCurrentKeyFrame
->UpdateConnections();
mpMap
->AddKeyFrame(mpCurrentKeyFrame
);
}
3.3. MapPointCulling()
// 剔除ProcessNewKeyFrame和CreateNewMapPoints函数中引入在mlpRecentAddedMapPoints的质量不好的MapPoints
void LocalMapping
::MapPointCulling()
{
list
<MapPoint
*>::iterator lit
= mlpRecentAddedMapPoints
.begin();
const unsigned long int nCurrentKFid
= mpCurrentKeyFrame
->mnId
;
int nThObs
;
if(mbMonocular
)
nThObs
= 2;
else
nThObs
= 3;
const int cnThObs
= nThObs
;
while(lit
!=mlpRecentAddedMapPoints
.end())
{
MapPoint
* pMP
= *lit
;
if(pMP
->isBad())
{
lit
= mlpRecentAddedMapPoints
.erase(lit
);
}
else if(pMP
->GetFoundRatio()<0.25f )
{
pMP
->SetBadFlag();
lit
= mlpRecentAddedMapPoints
.erase(lit
);
}
else if(((int)nCurrentKFid
-(int)pMP
->mnFirstKFid
)>=2 && pMP
->Observations()<=cnThObs
)
{
pMP
->SetBadFlag();
lit
= mlpRecentAddedMapPoints
.erase(lit
);
}
else if(((int)nCurrentKFid
-(int)pMP
->mnFirstKFid
)>=3)
lit
= mlpRecentAddedMapPoints
.erase(lit
);
else
lit
++;
}
}
3.4. CreateNewMapPoints()
/**
* 1.找出和当前关键帧共视程度前10/20(单目/双目RGBD)的关键帧
* 2.计算这些关键帧和当前关键帧的F矩阵;
* 3.在满足对级约束条件下,匹配关键帧之间的特征点,通过BOW加速匹配;
*/
void LocalMapping
::CreateNewMapPoints()
{
int nn
= 10;
if(mbMonocular
)
nn
=20;
const vector
<KeyFrame
*> vpNeighKFs
= mpCurrentKeyFrame
->GetBestCovisibilityKeyFrames(nn
);
ORBmatcher
matcher(0.6,false);
cv
::Mat Rcw1
= mpCurrentKeyFrame
->GetRotation();
cv
::Mat Rwc1
= Rcw1
.t();
cv
::Mat tcw1
= mpCurrentKeyFrame
->GetTranslation();
cv
::Mat
Tcw1(3,4,CV_32F
);
Rcw1
.copyTo(Tcw1
.colRange(0,3));
tcw1
.copyTo(Tcw1
.col(3));
cv
::Mat Ow1
= mpCurrentKeyFrame
->GetCameraCenter();
const float &fx1
= mpCurrentKeyFrame
->fx
;
const float &fy1
= mpCurrentKeyFrame
->fy
;
const float &cx1
= mpCurrentKeyFrame
->cx
;
const float &cy1
= mpCurrentKeyFrame
->cy
;
const float &invfx1
= mpCurrentKeyFrame
->invfx
;
const float &invfy1
= mpCurrentKeyFrame
->invfy
;
const float ratioFactor
= 1.5f*mpCurrentKeyFrame
->mfScaleFactor
;
int nnew
=0;
for(size_t i
=0; i
<vpNeighKFs
.size(); i
++)
{
if(i
>0 && CheckNewKeyFrames())
return;
KeyFrame
* pKF2
= vpNeighKFs
[i
];
cv
::Mat Ow2
= pKF2
->GetCameraCenter();
cv
::Mat vBaseline
= Ow2
-Ow1
;
const float baseline
= cv
::norm(vBaseline
);
if(!mbMonocular
)
{
if(baseline
<pKF2
->mb
)
continue;
}
else
{
const float medianDepthKF2
= pKF2
->ComputeSceneMedianDepth(2);
const float ratioBaselineDepth
= baseline
/medianDepthKF2
;
if(ratioBaselineDepth
<0.01)
continue;
}
cv
::Mat F12
= ComputeF12(mpCurrentKeyFrame
,pKF2
);
vector
<pair
<size_t
,size_t
> > vMatchedIndices
;
matcher
.SearchForTriangulation(mpCurrentKeyFrame
,pKF2
,F12
,vMatchedIndices
,false);
cv
::Mat Rcw2
= pKF2
->GetRotation();
cv
::Mat Rwc2
= Rcw2
.t();
cv
::Mat tcw2
= pKF2
->GetTranslation();
cv
::Mat
Tcw2(3,4,CV_32F
);
Rcw2
.copyTo(Tcw2
.colRange(0,3));
tcw2
.copyTo(Tcw2
.col(3));
const float &fx2
= pKF2
->fx
;
const float &fy2
= pKF2
->fy
;
const float &cx2
= pKF2
->cx
;
const float &cy2
= pKF2
->cy
;
const float &invfx2
= pKF2
->invfx
;
const float &invfy2
= pKF2
->invfy
;
const int nmatches
= vMatchedIndices
.size();
for(int ikp
=0; ikp
<nmatches
; ikp
++)
{
const int &idx1
= vMatchedIndices
[ikp
].first
;
const int &idx2
= vMatchedIndices
[ikp
].second
;
const cv
::KeyPoint
&kp1
= mpCurrentKeyFrame
->mvKeysUn
[idx1
];
const float kp1_ur
=mpCurrentKeyFrame
->mvuRight
[idx1
];
bool bStereo1
= kp1_ur
>=0;
const cv
::KeyPoint
&kp2
= pKF2
->mvKeysUn
[idx2
];
const float kp2_ur
= pKF2
->mvuRight
[idx2
];
bool bStereo2
= kp2_ur
>=0;
cv
::Mat xn1
= (cv
::Mat_
<float>(3,1) << (kp1
.pt
.x
-cx1
)*invfx1
, (kp1
.pt
.y
-cy1
)*invfy1
, 1.0);
cv
::Mat xn2
= (cv
::Mat_
<float>(3,1) << (kp2
.pt
.x
-cx2
)*invfx2
, (kp2
.pt
.y
-cy2
)*invfy2
, 1.0);
cv
::Mat ray1
= Rwc1
*xn1
;
cv
::Mat ray2
= Rwc2
*xn2
;
const float cosParallaxRays
= ray1
.dot(ray2
)/(cv
::norm(ray1
)*cv
::norm(ray2
));
float cosParallaxStereo
= cosParallaxRays
+1;
float cosParallaxStereo1
= cosParallaxStereo
;
float cosParallaxStereo2
= cosParallaxStereo
;
if(bStereo1
)
cosParallaxStereo1
= cos(2*atan2(mpCurrentKeyFrame
->mb
/2,mpCurrentKeyFrame
->mvDepth
[idx1
]));
else if(bStereo2
)
cosParallaxStereo2
= cos(2*atan2(pKF2
->mb
/2,pKF2
->mvDepth
[idx2
]));
cosParallaxStereo
= min(cosParallaxStereo1
,cosParallaxStereo2
);
cv
::Mat x3D
;
if(cosParallaxRays
<cosParallaxStereo
&& cosParallaxRays
>0 && (bStereo1
|| bStereo2
|| cosParallaxRays
<0.9998))
{
cv
::Mat
A(4,4,CV_32F
);
A
.row(0) = xn1
.at
<float>(0)*Tcw1
.row(2)-Tcw1
.row(0);
A
.row(1) = xn1
.at
<float>(1)*Tcw1
.row(2)-Tcw1
.row(1);
A
.row(2) = xn2
.at
<float>(0)*Tcw2
.row(2)-Tcw2
.row(0);
A
.row(3) = xn2
.at
<float>(1)*Tcw2
.row(2)-Tcw2
.row(1);
cv
::Mat w
,u
,vt
;
cv
::SVD
::compute(A
,w
,u
,vt
,cv
::SVD
::MODIFY_A
| cv
::SVD
::FULL_UV
);
x3D
= vt
.row(3).t();
if(x3D
.at
<float>(3)==0)
continue;
x3D
= x3D
.rowRange(0,3)/x3D
.at
<float>(3);
}
else if(bStereo1
&& cosParallaxStereo1
<cosParallaxStereo2
)
{
x3D
= mpCurrentKeyFrame
->UnprojectStereo(idx1
);
}
else if(bStereo2
&& cosParallaxStereo2
<cosParallaxStereo1
)
{
x3D
= pKF2
->UnprojectStereo(idx2
);
}
else
continue;
cv
::Mat x3Dt
= x3D
.t();
float z1
= Rcw1
.row(2).dot(x3Dt
)+tcw1
.at
<float>(2);
if(z1
<=0)
continue;
float z2
= Rcw2
.row(2).dot(x3Dt
)+tcw2
.at
<float>(2);
if(z2
<=0)
continue;
const float &sigmaSquare1
= mpCurrentKeyFrame
->mvLevelSigma2
[kp1
.octave
];
const float x1
= Rcw1
.row(0).dot(x3Dt
)+tcw1
.at
<float>(0);
const float y1
= Rcw1
.row(1).dot(x3Dt
)+tcw1
.at
<float>(1);
const float invz1
= 1.0/z1
;
if(!bStereo1
)
{
float u1
= fx1
*x1
*invz1
+cx1
;
float v1
= fy1
*y1
*invz1
+cy1
;
float errX1
= u1
- kp1
.pt
.x
;
float errY1
= v1
- kp1
.pt
.y
;
if((errX1
*errX1
+errY1
*errY1
)>5.991*sigmaSquare1
)
continue;
}
else
{
float u1
= fx1
*x1
*invz1
+cx1
;
float u1_r
= u1
- mpCurrentKeyFrame
->mbf
*invz1
;
float v1
= fy1
*y1
*invz1
+cy1
;
float errX1
= u1
- kp1
.pt
.x
;
float errY1
= v1
- kp1
.pt
.y
;
float errX1_r
= u1_r
- kp1_ur
;
if((errX1
*errX1
+errY1
*errY1
+errX1_r
*errX1_r
)>7.8*sigmaSquare1
)
continue;
}
const float sigmaSquare2
= pKF2
->mvLevelSigma2
[kp2
.octave
];
const float x2
= Rcw2
.row(0).dot(x3Dt
)+tcw2
.at
<float>(0);
const float y2
= Rcw2
.row(1).dot(x3Dt
)+tcw2
.at
<float>(1);
const float invz2
= 1.0/z2
;
if(!bStereo2
)
{
float u2
= fx2
*x2
*invz2
+cx2
;
float v2
= fy2
*y2
*invz2
+cy2
;
float errX2
= u2
- kp2
.pt
.x
;
float errY2
= v2
- kp2
.pt
.y
;
if((errX2
*errX2
+errY2
*errY2
)>5.991*sigmaSquare2
)
continue;
}
else
{
float u2
= fx2
*x2
*invz2
+cx2
;
float u2_r
= u2
- mpCurrentKeyFrame
->mbf
*invz2
;
float v2
= fy2
*y2
*invz2
+cy2
;
float errX2
= u2
- kp2
.pt
.x
;
float errY2
= v2
- kp2
.pt
.y
;
float errX2_r
= u2_r
- kp2_ur
;
if((errX2
*errX2
+errY2
*errY2
+errX2_r
*errX2_r
)>7.8*sigmaSquare2
)
continue;
}
cv
::Mat normal1
= x3D
-Ow1
;
float dist1
= cv
::norm(normal1
);
cv
::Mat normal2
= x3D
-Ow2
;
float dist2
= cv
::norm(normal2
);
if(dist1
==0 || dist2
==0)
continue;
const float ratioDist
= dist2
/dist1
;
const float ratioOctave
= mpCurrentKeyFrame
->mvScaleFactors
[kp1
.octave
]/pKF2
->mvScaleFactors
[kp2
.octave
];
if(ratioDist
*ratioFactor
<ratioOctave
|| ratioDist
>ratioOctave
*ratioFactor
)
continue;
MapPoint
* pMP
= new MapPoint(x3D
,mpCurrentKeyFrame
,mpMap
);
pMP
->AddObservation(mpCurrentKeyFrame
,idx1
);
pMP
->AddObservation(pKF2
,idx2
);
mpCurrentKeyFrame
->AddMapPoint(pMP
,idx1
);
pKF2
->AddMapPoint(pMP
,idx2
);
pMP
->ComputeDistinctiveDescriptors();
pMP
->UpdateNormalAndDepth();
mpMap
->AddMapPoint(pMP
);
mlpRecentAddedMapPoints
.push_back(pMP
);
nnew
++;
}
}
}
3.5. SearchInNeighbors()
检查并融合与当前关键帧共视程度高的帧重复的MapPoints
void LocalMapping
::SearchInNeighbors()
{
int nn
= 10;
if(mbMonocular
)
nn
=20;
const vector
<KeyFrame
*> vpNeighKFs
= mpCurrentKeyFrame
->GetBestCovisibilityKeyFrames(nn
);
vector
<KeyFrame
*> vpTargetKFs
;
for(vector
<KeyFrame
*>::const_iterator vit
=vpNeighKFs
.begin(), vend
=vpNeighKFs
.end(); vit
!=vend
; vit
++)
{
KeyFrame
* pKFi
= *vit
;
if(pKFi
->isBad() || pKFi
->mnFuseTargetForKF
== mpCurrentKeyFrame
->mnId
)
continue;
vpTargetKFs
.push_back(pKFi
);
pKFi
->mnFuseTargetForKF
= mpCurrentKeyFrame
->mnId
;
const vector
<KeyFrame
*> vpSecondNeighKFs
= pKFi
->GetBestCovisibilityKeyFrames(5);
for(vector
<KeyFrame
*>::const_iterator vit2
=vpSecondNeighKFs
.begin(), vend2
=vpSecondNeighKFs
.end(); vit2
!=vend2
; vit2
++)
{
KeyFrame
* pKFi2
= *vit2
;
if(pKFi2
->isBad() || pKFi2
->mnFuseTargetForKF
==mpCurrentKeyFrame
->mnId
|| pKFi2
->mnId
==mpCurrentKeyFrame
->mnId
)
continue;
vpTargetKFs
.push_back(pKFi2
);
}
}
ORBmatcher matcher
;
vector
<MapPoint
*> vpMapPointMatches
= mpCurrentKeyFrame
->GetMapPointMatches();
for(vector
<KeyFrame
*>::iterator vit
=vpTargetKFs
.begin(), vend
=vpTargetKFs
.end(); vit
!=vend
; vit
++)
{
KeyFrame
* pKFi
= *vit
;
matcher
.Fuse(pKFi
,vpMapPointMatches
);
}
vector
<MapPoint
*> vpFuseCandidates
;
vpFuseCandidates
.reserve(vpTargetKFs
.size()*vpMapPointMatches
.size());
for(vector
<KeyFrame
*>::iterator vitKF
=vpTargetKFs
.begin(), vendKF
=vpTargetKFs
.end(); vitKF
!=vendKF
; vitKF
++)
{
KeyFrame
* pKFi
= *vitKF
;
vector
<MapPoint
*> vpMapPointsKFi
= pKFi
->GetMapPointMatches();
for(vector
<MapPoint
*>::iterator vitMP
=vpMapPointsKFi
.begin(), vendMP
=vpMapPointsKFi
.end(); vitMP
!=vendMP
; vitMP
++)
{
MapPoint
* pMP
= *vitMP
;
if(!pMP
)
continue;
if(pMP
->isBad() || pMP
->mnFuseCandidateForKF
== mpCurrentKeyFrame
->mnId
)
continue;
pMP
->mnFuseCandidateForKF
= mpCurrentKeyFrame
->mnId
;
vpFuseCandidates
.push_back(pMP
);
}
}
matcher
.Fuse(mpCurrentKeyFrame
,vpFuseCandidates
);
vpMapPointMatches
= mpCurrentKeyFrame
->GetMapPointMatches();
for(size_t i
=0, iend
=vpMapPointMatches
.size(); i
<iend
; i
++)
{
MapPoint
* pMP
=vpMapPointMatches
[i
];
if(pMP
)
{
if(!pMP
->isBad())
{
pMP
->ComputeDistinctiveDescriptors();
pMP
->UpdateNormalAndDepth();
}
}
}
mpCurrentKeyFrame
->UpdateConnections();
}
3.6. KeyFrameCulling()
// 检测并剔除当前帧相邻的关键帧中冗余的关键帧
// 剔除的标准是:该关键帧的90%的MapPoints可以被其它至少3个关键帧观测到
void LocalMapping
::KeyFrameCulling()
{
vector
<KeyFrame
*> vpLocalKeyFrames
= mpCurrentKeyFrame
->GetVectorCovisibleKeyFrames();
for(vector
<KeyFrame
*>::iterator vit
=vpLocalKeyFrames
.begin(), vend
=vpLocalKeyFrames
.end(); vit
!=vend
; vit
++)
{
KeyFrame
* pKF
= *vit
;
if(pKF
->mnId
==0)
continue;
const vector
<MapPoint
*> vpMapPoints
= pKF
->GetMapPointMatches();
int nObs
= 3;
const int thObs
=nObs
;
int nRedundantObservations
=0;
int nMPs
=0;
for(size_t i
=0, iend
=vpMapPoints
.size(); i
<iend
; i
++)
{
MapPoint
* pMP
= vpMapPoints
[i
];
if(pMP
)
{
if(!pMP
->isBad())
{
if(!mbMonocular
)
{
if(pKF
->mvDepth
[i
]>pKF
->mThDepth
|| pKF
->mvDepth
[i
]<0)
continue;
}
nMPs
++;
if(pMP
->Observations()>thObs
)
{
const int &scaleLevel
= pKF
->mvKeysUn
[i
].octave
;
const map
<KeyFrame
*, size_t
> observations
= pMP
->GetObservations();
int nObs
=0;
for(map
<KeyFrame
*, size_t
>::const_iterator mit
=observations
.begin(), mend
=observations
.end(); mit
!=mend
; mit
++)
{
KeyFrame
* pKFi
= mit
->first
;
if(pKFi
==pKF
)
continue;
const int &scaleLeveli
= pKFi
->mvKeysUn
[mit
->second
].octave
;
if(scaleLeveli
<=scaleLevel
+1)
{
nObs
++;
if(nObs
>=thObs
)
break;
}
}
if(nObs
>=thObs
)
{
nRedundantObservations
++;
}
}
}
}
}
if(nRedundantObservations
>0.9*nMPs
)
pKF
->SetBadFlag();
}
}