mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-12 14:30:19 +08:00
Add/Refine/SBA: create Registration only once to avoid internal initialization for every link refined, added or rematched (e.g., SuperPoint or SuperGlue).
This commit is contained in:
@@ -149,14 +149,16 @@ public:
|
||||
const std::map<int, Signature> & signatures,
|
||||
std::map<int, cv::Point3f> & points3DMap,
|
||||
std::map<int, std::map<int, FeatureBA> > & wordReferences, // <ID words, IDs frames + keypoint/depth/descriptor>
|
||||
bool rematchFeatures = false);
|
||||
bool rematchFeatures = false,
|
||||
const ParametersMap & registrationParameters = ParametersMap());
|
||||
|
||||
std::map<int, Transform> optimizeBA(
|
||||
int rootId,
|
||||
const std::map<int, Transform> & poses,
|
||||
const std::multimap<int, Link> & links,
|
||||
const std::map<int, Signature> & signatures,
|
||||
bool rematchFeatures = false);
|
||||
bool rematchFeatures = false,
|
||||
const ParametersMap & registrationParameters = ParametersMap());
|
||||
|
||||
Transform optimizeBA(
|
||||
const Link & link,
|
||||
@@ -172,7 +174,8 @@ public:
|
||||
std::map<int, cv::Point3f> & points3DMap,
|
||||
std::map<int, std::map<int, FeatureBA > > & wordReferences, // <ID words, IDs frames + keypoint/depth/descriptor>
|
||||
bool rematchFeatures = false,
|
||||
bool useLinkTransformAsGuess = false);
|
||||
bool useLinkTransformAsGuess = false,
|
||||
ParametersMap registrationParameters = ParametersMap());
|
||||
|
||||
protected:
|
||||
Optimizer(
|
||||
|
||||
+16
-12
@@ -447,7 +447,8 @@ std::map<int, Transform> Optimizer::optimizeBA(
|
||||
const std::map<int, Signature> & signatures,
|
||||
std::map<int, cv::Point3f> & points3DMap,
|
||||
std::map<int, std::map<int, FeatureBA> > & wordReferences,
|
||||
bool rematchFeatures)
|
||||
bool rematchFeatures,
|
||||
const ParametersMap & registrationParameters)
|
||||
{
|
||||
UDEBUG("");
|
||||
std::map<int, std::vector<CameraModel> > multiModels;
|
||||
@@ -497,7 +498,7 @@ std::map<int, Transform> Optimizer::optimizeBA(
|
||||
}
|
||||
|
||||
// compute correspondences
|
||||
this->computeBACorrespondences(poses, links, signatures, points3DMap, wordReferences, rematchFeatures);
|
||||
this->computeBACorrespondences(poses, links, signatures, points3DMap, wordReferences, rematchFeatures, false, registrationParameters);
|
||||
|
||||
return optimizeBA(rootId, poses, links, multiModels, points3DMap, wordReferences);
|
||||
}
|
||||
@@ -507,11 +508,12 @@ std::map<int, Transform> Optimizer::optimizeBA(
|
||||
const std::map<int, Transform> & poses,
|
||||
const std::multimap<int, Link> & links,
|
||||
const std::map<int, Signature> & signatures,
|
||||
bool rematchFeatures)
|
||||
bool rematchFeatures,
|
||||
const ParametersMap & registrationParameters)
|
||||
{
|
||||
std::map<int, cv::Point3f> points3DMap;
|
||||
std::map<int, std::map<int, FeatureBA> > wordReferences;
|
||||
return optimizeBA(rootId, poses, links, signatures, points3DMap, wordReferences, rematchFeatures);
|
||||
return optimizeBA(rootId, poses, links, signatures, points3DMap, wordReferences, rematchFeatures, registrationParameters);
|
||||
}
|
||||
|
||||
Transform Optimizer::optimizeBA(
|
||||
@@ -557,11 +559,20 @@ void Optimizer::computeBACorrespondences(
|
||||
std::map<int, cv::Point3f> & points3DMap,
|
||||
std::map<int, std::map<int, FeatureBA> > & wordReferences,
|
||||
bool rematchFeatures,
|
||||
bool useLinkTransformAsGuess)
|
||||
bool useLinkTransformAsGuess,
|
||||
ParametersMap registrationParameters)
|
||||
{
|
||||
UDEBUG("rematchFeatures=%d", rematchFeatures?1:0);
|
||||
int wordCount = 0;
|
||||
int edgeWithWordsAdded = 0;
|
||||
|
||||
// Some defaults if not provided
|
||||
registrationParameters.insert(ParametersPair(Parameters::kVisEstimationType(), "1"));
|
||||
registrationParameters.insert(ParametersPair(Parameters::kVisPnPReprojError(), "5"));
|
||||
registrationParameters.insert(ParametersPair(Parameters::kVisMinInliers(), "6"));
|
||||
registrationParameters.insert(ParametersPair(Parameters::kVisCorNNDR(), "0.6"));
|
||||
RegistrationVis reg(registrationParameters);
|
||||
|
||||
std::map<int, std::map<cv::KeyPoint, int, KeyPointCompare> > frameToWordMap; // <FrameId, <Keypoint, wordId> >
|
||||
for(std::multimap<int, Link>::const_iterator iter=links.lower_bound(1); iter!=links.end(); ++iter)
|
||||
{
|
||||
@@ -601,13 +612,6 @@ void Optimizer::computeBACorrespondences(
|
||||
sTo.getWords().size() &&
|
||||
sFrom.getWords3().size())
|
||||
{
|
||||
ParametersMap regParam;
|
||||
regParam.insert(ParametersPair(Parameters::kVisEstimationType(), "1"));
|
||||
regParam.insert(ParametersPair(Parameters::kVisPnPReprojError(), "5"));
|
||||
regParam.insert(ParametersPair(Parameters::kVisMinInliers(), "6"));
|
||||
regParam.insert(ParametersPair(Parameters::kVisCorNNDR(), "0.6"));
|
||||
RegistrationVis reg(regParam);
|
||||
|
||||
if(!rematchFeatures)
|
||||
{
|
||||
sFrom.setWordsDescriptors(cv::Mat());
|
||||
|
||||
@@ -65,6 +65,8 @@ class ExportCloudsDialog;
|
||||
class EditDepthArea;
|
||||
class EditMapArea;
|
||||
class LinkRefiningDialog;
|
||||
class Registration;
|
||||
class RegistrationIcp;
|
||||
|
||||
class RTABMAP_GUI_EXPORT DatabaseViewer : public QMainWindow
|
||||
{
|
||||
@@ -202,8 +204,8 @@ private:
|
||||
void updateLoopClosuresSlider(int from = 0, int to = 0);
|
||||
void updateCovariances(const QList<Link> & links);
|
||||
void refineLinks(const QList<Link> & links);
|
||||
void refineConstraint(int from, int to, bool silent);
|
||||
bool addConstraint(int from, int to, bool silent, bool silentlyUseOptimizedGraphAsGuess = false);
|
||||
void refineConstraint(int from, int to, Registration * reg, RegistrationIcp * regIcp, bool silent);
|
||||
bool addConstraint(int from, int to, Registration * reg, bool silent, bool silentlyUseOptimizedGraphAsGuess = false);
|
||||
void exportPoses(int format);
|
||||
void exportGPS(int format);
|
||||
|
||||
|
||||
@@ -4263,6 +4263,8 @@ void DatabaseViewer::detectMoreLoopClosures()
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<Registration> reg(Registration::create(ui_->parameters_toolbox->getParameters()));
|
||||
|
||||
for(int n=0; n<iterations; ++n)
|
||||
{
|
||||
UINFO("iteration %d/%d", n+1, iterations);
|
||||
@@ -4310,7 +4312,7 @@ void DatabaseViewer::detectMoreLoopClosures()
|
||||
delta.getNorm() >= ui_->doubleSpinBox_detectMore_radiusMin->value())
|
||||
{
|
||||
checkedLoopClosures.insert(std::make_pair(from, to));
|
||||
if(addConstraint(from, to, true, useOptimizedGraphAsGuess))
|
||||
if(addConstraint(from, to, reg.get(), true, useOptimizedGraphAsGuess))
|
||||
{
|
||||
UINFO("Added new loop closure between %d and %d.", from, to);
|
||||
++added;
|
||||
@@ -4568,13 +4570,16 @@ void DatabaseViewer::refineLinks(const QList<Link> & links)
|
||||
progressDialog->setMinimumWidth(800);
|
||||
progressDialog->show();
|
||||
|
||||
RegistrationIcp regProximity(ui_->parameters_toolbox->getParameters());
|
||||
std::shared_ptr<Registration> reg(Registration::create(ui_->parameters_toolbox->getParameters()));
|
||||
|
||||
for(int i=0; i<links.size(); ++i)
|
||||
{
|
||||
int from = links[i].from();
|
||||
int to = links[i].to();
|
||||
if(from > 0 && to > 0)
|
||||
{
|
||||
this->refineConstraint(links[i].from(), links[i].to(), true);
|
||||
this->refineConstraint(links[i].from(), links[i].to(), reg.get(), ®Proximity, true);
|
||||
progressDialog->appendText(tr("Refined link %1->%2 (%3/%4)").arg(from).arg(to).arg(i+1).arg(links.size()));
|
||||
}
|
||||
else
|
||||
@@ -7140,7 +7145,7 @@ void DatabaseViewer::sliderIterationsValueChanged(int value)
|
||||
}
|
||||
if(!allNodesAreInWM)
|
||||
{
|
||||
ui_->graphViewer->updatePosterior(colors, 1, 1);
|
||||
ui_->graphViewer->updateNodeColorByValue("In WM", colors, 1, false, 1);
|
||||
}
|
||||
}
|
||||
QGraphicsRectItem * rectScaleItem = 0;
|
||||
@@ -8085,10 +8090,12 @@ void DatabaseViewer::refineConstraint()
|
||||
{
|
||||
int from = ids_.at(ui_->horizontalSlider_A->value());
|
||||
int to = ids_.at(ui_->horizontalSlider_B->value());
|
||||
refineConstraint(from, to, false);
|
||||
RegistrationIcp regProximity(ui_->parameters_toolbox->getParameters());
|
||||
std::shared_ptr<Registration> reg(Registration::create(ui_->parameters_toolbox->getParameters()));
|
||||
refineConstraint(from, to, reg.get(), ®Proximity, false);
|
||||
}
|
||||
|
||||
void DatabaseViewer::refineConstraint(int from, int to, bool silent)
|
||||
void DatabaseViewer::refineConstraint(int from, int to, Registration * reg, RegistrationIcp * regProximity, bool silent)
|
||||
{
|
||||
UDEBUG("%d -> %d", from, to);
|
||||
bool switchedIds = false;
|
||||
@@ -8361,8 +8368,7 @@ void DatabaseViewer::refineConstraint(int from, int to, bool silent)
|
||||
fromScan.is2d()?Transform(0,0,fromScan.localTransform().z(),0,0,0):Transform::getIdentity()));
|
||||
|
||||
toS = new Signature(assembledData);
|
||||
RegistrationIcp registrationIcp(parameters);
|
||||
transform = registrationIcp.computeTransformationMod(*fromS, *toS, currentLink.transform(), &info);
|
||||
transform = regProximity->computeTransformationMod(*fromS, *toS, currentLink.transform(), &info);
|
||||
if(!transform.isNull())
|
||||
{
|
||||
// local scan matching proximity detection should have higher variance (see Rtabmap::process())
|
||||
@@ -8380,7 +8386,6 @@ void DatabaseViewer::refineConstraint(int from, int to, bool silent)
|
||||
}
|
||||
|
||||
bool reextractVisualFeatures = uStr2Bool(parameters.at(Parameters::kRGBDLoopClosureReextractFeatures()));
|
||||
Registration * reg = Registration::create(parameters);
|
||||
if( reg->isScanRequired() ||
|
||||
reg->isUserDataRequired() ||
|
||||
reextractVisualFeatures ||
|
||||
@@ -8477,8 +8482,6 @@ void DatabaseViewer::refineConstraint(int from, int to, bool silent)
|
||||
transform = reg->computeTransformationMod(*toS, *fromS, t.isNull()?t:t.inverse(), &info);
|
||||
switchedIds = true;
|
||||
}
|
||||
|
||||
delete reg;
|
||||
}
|
||||
UINFO("(%d ->%d) Registration time: %f s", currentLink.from(), currentLink.to(), timer.ticks());
|
||||
|
||||
@@ -8610,11 +8613,14 @@ void DatabaseViewer::addConstraint()
|
||||
{
|
||||
int from = ids_.at(ui_->horizontalSlider_A->value());
|
||||
int to = ids_.at(ui_->horizontalSlider_B->value());
|
||||
addConstraint(from, to, false);
|
||||
std::shared_ptr<Registration> reg(Registration::create(ui_->parameters_toolbox->getParameters()));
|
||||
addConstraint(from, to, reg.get(), false);
|
||||
}
|
||||
|
||||
bool DatabaseViewer::addConstraint(int from, int to, bool silent, bool silentlyUseOptimizedGraphAsGuess)
|
||||
bool DatabaseViewer::addConstraint(int from, int to, Registration * reg, bool silent, bool silentlyUseOptimizedGraphAsGuess)
|
||||
{
|
||||
UASSERT(reg);
|
||||
|
||||
bool switchedIds = false;
|
||||
if(from == to)
|
||||
{
|
||||
@@ -8641,7 +8647,6 @@ bool DatabaseViewer::addConstraint(int from, int to, bool silent, bool silentlyU
|
||||
UASSERT(!containsLink(linksRefined_, from, to));
|
||||
|
||||
ParametersMap parameters = ui_->parameters_toolbox->getParameters();
|
||||
Registration * reg = Registration::create(parameters);
|
||||
|
||||
bool loopCovLimited = Parameters::defaultRGBDLoopCovLimited();
|
||||
Parameters::parse(parameters, Parameters::kRGBDLoopCovLimited(), loopCovLimited);
|
||||
@@ -8823,7 +8828,6 @@ bool DatabaseViewer::addConstraint(int from, int to, bool silent, bool silentlyU
|
||||
{
|
||||
t = reg->computeTransformationMod(*fromS, *toS, guess, &info);
|
||||
}
|
||||
delete reg;
|
||||
UDEBUG("");
|
||||
|
||||
if(!t.isNull())
|
||||
|
||||
@@ -6623,6 +6623,8 @@ void MainWindow::postProcessing(
|
||||
odomMaxInf = graph::getMaxOdomInf(_currentLinksMap);
|
||||
}
|
||||
|
||||
std::shared_ptr<Registration> registration(Registration::create(parameters));
|
||||
|
||||
UASSERT(iterations>0);
|
||||
for(int n=0; n<iterations && !_progressCanceled; ++n)
|
||||
{
|
||||
@@ -6703,7 +6705,6 @@ void MainWindow::postProcessing(
|
||||
{
|
||||
uInsert(parameters, ParametersPair(Parameters::kRegStrategy(), "2"));
|
||||
}
|
||||
Registration * registration = Registration::create(parameters);
|
||||
|
||||
if(reextractFeatures)
|
||||
{
|
||||
@@ -6735,7 +6736,6 @@ void MainWindow::postProcessing(
|
||||
Parameters::kRGBDLoopClosureReextractFeatures().c_str());
|
||||
}
|
||||
transform = registration->computeTransformation(signatureFrom, signatureTo, Transform(), &info);
|
||||
delete registration;
|
||||
if(!transform.isNull())
|
||||
{
|
||||
//optimize the graph to see if the new constraint is globally valid
|
||||
@@ -7023,7 +7023,13 @@ void MainWindow::postProcessing(
|
||||
uInsert(parametersSBA, std::make_pair(Parameters::kOptimizerIterations(), uNumber2Str(sbaIterations)));
|
||||
uInsert(parametersSBA, std::make_pair(Parameters::kg2oPixelVariance(), uNumber2Str(sbaVariance)));
|
||||
Optimizer * sbaOptimizer = Optimizer::create(sbaType, parametersSBA);
|
||||
std::map<int, Transform> newPoses = sbaOptimizer->optimizeBA(optimizedPoses.begin()->first, optimizedPoses, linksOut, _cachedSignatures.toStdMap(), sbaRematchFeatures);
|
||||
std::map<int, Transform> newPoses = sbaOptimizer->optimizeBA(
|
||||
optimizedPoses.begin()->first,
|
||||
optimizedPoses,
|
||||
linksOut,
|
||||
_cachedSignatures.toStdMap(),
|
||||
sbaRematchFeatures,
|
||||
parametersSBA);
|
||||
delete sbaOptimizer;
|
||||
if(newPoses.size())
|
||||
{
|
||||
|
||||
@@ -119,7 +119,7 @@ int main(int argc, char * argv[])
|
||||
|
||||
printf("Global bundle adjustment...\n");
|
||||
Optimizer * optimizer = Optimizer::create(Optimizer::kTypeG2O, parameters);
|
||||
optimizedPoses = optimizer->optimizeBA(optimizedPoses.lower_bound(1)->first, optimizedPoses, links, nodes, true);
|
||||
optimizedPoses = optimizer->optimizeBA(optimizedPoses.lower_bound(1)->first, optimizedPoses, links, nodes, true, parameters);
|
||||
delete optimizer;
|
||||
printf("Global bundle adjustment... done (%fs).\n", timer.ticks());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user