2021SC@SDUSC
目錄
1.前言
這一部分代碼量巨大,查閱了很多資料結合來看的代碼,將分為以下部分進行分析
單幀優化局部地圖優化全局優化尺度與重力優化sim3優化地圖回環優化地圖融合優化
下面給出逐步注釋分析
2.代碼分析
LoopClosing::DetectAndReffineSim3FromLastKF使用
1投2, 2投1這么來 只優化g2oS12
int Optimizer::OptimizeSim3(KeyFrame
*pKF1
, KeyFrame
*pKF2
, vector
<MapPoint
*> &vpMatches1
, g2o
::Sim3
&g2oS12
, const float th2
,const bool bFixScale
, Eigen
::Matrix
<double, 7, 7> &mAcumHessian
, const bool bAllPoints
)
{g2o
::SparseOptimizer optimizer
;g2o
::BlockSolverX
::LinearSolverType
*linearSolver
;linearSolver
= new g2o
::LinearSolverDense
<g2o
::BlockSolverX
::PoseMatrixType
>();g2o
::BlockSolverX
*solver_ptr
= new g2o
::BlockSolverX(linearSolver
);g2o
::OptimizationAlgorithmLevenberg
*solver
= new g2o
::OptimizationAlgorithmLevenberg(solver_ptr
);optimizer
.setAlgorithm(solver
);const cv
::Mat R1w
= pKF1
->GetRotation();const cv
::Mat t1w
= pKF1
->GetTranslation();const cv
::Mat R2w
= pKF2
->GetRotation();const cv
::Mat t2w
= pKF2
->GetTranslation();ORB_SLAM3
::VertexSim3Expmap
*vSim3
= new ORB_SLAM3::VertexSim3Expmap();vSim3
->_fix_scale
= bFixScale
;vSim3
->setEstimate(g2oS12
);vSim3
->setId(0);vSim3
->setFixed(false);vSim3
->pCamera1
= pKF1
->mpCamera
;vSim3
->pCamera2
= pKF2
->mpCamera
;optimizer
.addVertex(vSim3
);const int N
= vpMatches1
.size();const vector
<MapPoint
*> vpMapPoints1
= pKF1
->GetMapPointMatches();vector
<ORB_SLAM3
::EdgeSim3ProjectXYZ
*> vpEdges12
; vector
<ORB_SLAM3
::EdgeInverseSim3ProjectXYZ
*> vpEdges21
; vector
<size_t
> vnIndexEdge
;vector
<bool> vbIsInKF2
;vnIndexEdge
.reserve(2 * N
);vpEdges12
.reserve(2 * N
);vpEdges21
.reserve(2 * N
);vbIsInKF2
.reserve(2 * N
);const float deltaHuber
= sqrt(th2
);int nCorrespondences
= 0;int nBadMPs
= 0; int nInKF2
= 0; int nOutKF2
= 0; int nMatchWithoutMP
= 0; vector
<int> vIdsOnlyInKF2
;for (int i
= 0; i
< N
; i
++){if (!vpMatches1
[i
])continue;MapPoint
*pMP1
= vpMapPoints1
[i
];MapPoint
*pMP2
= vpMatches1
[i
];const int id1
= 2 * i
+ 1;const int id2
= 2 * (i
+ 1);const int i2
= get
<0>(pMP2
->GetIndexInKeyFrame(pKF2
));cv
::Mat P3D1c
; cv
::Mat P3D2c
; if (pMP1
&& pMP2
){if (!pMP1
->isBad() && !pMP2
->isBad()){g2o
::VertexSBAPointXYZ
*vPoint1
= new g2o
::VertexSBAPointXYZ();cv
::Mat P3D1w
= pMP1
->GetWorldPos();P3D1c
= R1w
* P3D1w
+ t1w
;vPoint1
->setEstimate(Converter::toVector3d(P3D1c
)); vPoint1
->setId(id1
);vPoint1
->setFixed(true);optimizer
.addVertex(vPoint1
);g2o
::VertexSBAPointXYZ
*vPoint2
= new g2o
::VertexSBAPointXYZ();cv
::Mat P3D2w
= pMP2
->GetWorldPos();P3D2c
= R2w
* P3D2w
+ t2w
;vPoint2
->setEstimate(Converter::toVector3d(P3D2c
)); vPoint2
->setId(id2
);vPoint2
->setFixed(true);optimizer
.addVertex(vPoint2
);}else{nBadMPs
++;continue;}}else{nMatchWithoutMP
++;if (!pMP2
->isBad()){g2o
::VertexSBAPointXYZ
*vPoint2
= new g2o
::VertexSBAPointXYZ();cv
::Mat P3D2w
= pMP2
->GetWorldPos();P3D2c
= R2w
* P3D2w
+ t2w
;vPoint2
->setEstimate(Converter::toVector3d(P3D2c
));vPoint2
->setId(id2
);vPoint2
->setFixed(true);optimizer
.addVertex(vPoint2
);vIdsOnlyInKF2
.push_back(id2
);}continue;}if (i2
< 0 && !bAllPoints
) {Verbose::PrintMess(" Remove point -> i2: " + to_string(i2
) + "; bAllPoints: " + to_string(bAllPoints
), Verbose
::VERBOSITY_DEBUG
);continue;}if (P3D2c
.at
<float>(2) < 0){Verbose::PrintMess("Sim3: Z coordinate is negative", Verbose
::VERBOSITY_DEBUG
);continue;}nCorrespondences
++;Eigen
::Matrix
<double, 2, 1> obs1
;const cv
::KeyPoint
&kpUn1
= pKF1
->mvKeysUn
[i
];obs1
<< kpUn1
.pt
.x
, kpUn1
.pt
.y
;ORB_SLAM3
::EdgeSim3ProjectXYZ
*e12
= new ORB_SLAM3::EdgeSim3ProjectXYZ();e12
->setVertex(0, dynamic_cast<g2o
::OptimizableGraph
::Vertex
*>(optimizer
.vertex(id2
))); e12
->setVertex(1, dynamic_cast<g2o
::OptimizableGraph
::Vertex
*>(optimizer
.vertex(0))); e12
->setMeasurement(obs1
);const float &invSigmaSquare1
= pKF1
->mvInvLevelSigma2
[kpUn1
.octave
];e12
->setInformation(Eigen
::Matrix2d::Identity() * invSigmaSquare1
);g2o
::RobustKernelHuber
*rk1
= new g2o
::RobustKernelHuber
;e12
->setRobustKernel(rk1
);rk1
->setDelta(deltaHuber
);optimizer
.addEdge(e12
);Eigen
::Matrix
<double, 2, 1> obs2
;cv
::KeyPoint kpUn2
;bool inKF2
;if (i2
>= 0){kpUn2
= pKF2
->mvKeysUn
[i2
];obs2
<< kpUn2
.pt
.x
, kpUn2
.pt
.y
;inKF2
= true;nInKF2
++; }else {float invz
= 1 / P3D2c
.at
<float>(2);float x
= P3D2c
.at
<float>(0) * invz
;float y
= P3D2c
.at
<float>(1) * invz
;obs2
<< x
, y
;kpUn2
= cv
::KeyPoint(cv
::Point2f(x
, y
), pMP2
->mnTrackScaleLevel
);inKF2
= false;nOutKF2
++;}ORB_SLAM3
::EdgeInverseSim3ProjectXYZ
*e21
= new ORB_SLAM3::EdgeInverseSim3ProjectXYZ();e21
->setVertex(0, dynamic_cast<g2o
::OptimizableGraph
::Vertex
*>(optimizer
.vertex(id1
)));e21
->setVertex(1, dynamic_cast<g2o
::OptimizableGraph
::Vertex
*>(optimizer
.vertex(0)));e21
->setMeasurement(obs2
);float invSigmaSquare2
= pKF2
->mvInvLevelSigma2
[kpUn2
.octave
];e21
->setInformation(Eigen
::Matrix2d::Identity() * invSigmaSquare2
);g2o
::RobustKernelHuber
*rk2
= new g2o
::RobustKernelHuber
;e21
->setRobustKernel(rk2
);rk2
->setDelta(deltaHuber
);optimizer
.addEdge(e21
);vpEdges12
.push_back(e12
);vpEdges21
.push_back(e21
);vnIndexEdge
.push_back(i
);vbIsInKF2
.push_back(inKF2
);}optimizer
.initializeOptimization();optimizer
.optimize(5);int nBad
= 0;int nBadOutKF2
= 0;for (size_t i
= 0; i
< vpEdges12
.size(); i
++){ORB_SLAM3
::EdgeSim3ProjectXYZ
*e12
= vpEdges12
[i
];ORB_SLAM3
::EdgeInverseSim3ProjectXYZ
*e21
= vpEdges21
[i
];if (!e12
|| !e21
)continue;if (e12
->chi2() > th2
|| e21
->chi2() > th2
){size_t idx
= vnIndexEdge
[i
];vpMatches1
[idx
] = static_cast<MapPoint
*>(NULL);optimizer
.removeEdge(e12
);optimizer
.removeEdge(e21
);vpEdges12
[i
] = static_cast<ORB_SLAM3
::EdgeSim3ProjectXYZ
*>(NULL);vpEdges21
[i
] = static_cast<ORB_SLAM3
::EdgeInverseSim3ProjectXYZ
*>(NULL);nBad
++;if (!vbIsInKF2
[i
]){nBadOutKF2
++;}continue;}e12
->setRobustKernel(0);e21
->setRobustKernel(0);}int nMoreIterations
;if (nBad
> 0)nMoreIterations
= 10;elsenMoreIterations
= 5;if (nCorrespondences
- nBad
< 10)return 0;optimizer
.initializeOptimization();optimizer
.optimize(nMoreIterations
);int nIn
= 0;mAcumHessian
= Eigen
::MatrixXd::Zero(7, 7);for (size_t i
= 0; i
< vpEdges12
.size(); i
++){ORB_SLAM3
::EdgeSim3ProjectXYZ
*e12
= vpEdges12
[i
];ORB_SLAM3
::EdgeInverseSim3ProjectXYZ
*e21
= vpEdges21
[i
];if (!e12
|| !e21
)continue;e12
->computeError();e21
->computeError();if (e12
->chi2() > th2
|| e21
->chi2() > th2
){size_t idx
= vnIndexEdge
[i
];vpMatches1
[idx
] = static_cast<MapPoint
*>(NULL);}else{nIn
++;}}g2o
::VertexSim3Expmap
*vSim3_recov
= static_cast<g2o
::VertexSim3Expmap
*>(optimizer
.vertex(0));g2oS12
= vSim3_recov
->estimate();return nIn
;
}
總結
以上是生活随笔為你收集整理的【SLAM学习笔记】10-ORB_SLAM3关键源码分析⑧ Optimizer(五)sim3优化的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。