74 int optimizerTypeInt = Parameters::defaultOptimizerStrategy();
75 Parameters::parse(parameters, Parameters::kOptimizerStrategy(), optimizerTypeInt);
82 "RTAB-Map is not built with any graph optimization approach!");
88 UWARN(
"TORO optimizer not available. GTSAM will be used instead.");
93 UWARN(
"TORO optimizer not available. g2o will be used instead.");
98 UWARN(
"TORO optimizer not available. ceres will be used instead.");
106 UWARN(
"g2o optimizer not available. GTSAM will be used instead.");
111 UWARN(
"g2o optimizer not available. TORO will be used instead.");
116 UWARN(
"g2o optimizer not available. ceres will be used instead.");
124 UWARN(
"GTSAM optimizer not available. g2o will be used instead.");
129 UWARN(
"GTSAM optimizer not available. TORO will be used instead.");
134 UWARN(
"GTSAM optimizer not available. ceres will be used instead.");
142 UWARN(
"CVSBA optimizer not available. g2o will be used instead.");
150 UWARN(
"Ceres optimizer not available. gtsam will be used instead.");
155 UWARN(
"Ceres optimizer not available. g2o will be used instead.");
160 UWARN(
"Ceres optimizer not available. TORO will be used instead.");
190 const std::map<int, Transform> & posesIn,
191 const std::multimap<int, Link> & linksIn,
192 std::map<int, Transform> & posesOut,
193 std::multimap<int, Link> & linksOut)
const
195 UDEBUG(
"IN: fromId=%d poses=%d links=%d priorsIgnored=%d landmarksIgnored=%d", fromId, (
int)posesIn.size(), (
int)linksIn.size(),
priorsIgnored()?1:0,
landmarksIgnored()?1:0);
202 std::set<int> nextPoses;
203 nextPoses.insert(fromId);
204 std::multimap<int, std::pair<int, Link::Type> > biLinks;
205 for(std::multimap<int, Link>::const_iterator
iter=linksIn.begin();
iter!=linksIn.end(); ++
iter)
207 if(
iter->second.from() !=
iter->second.to())
211 biLinks.insert(std::make_pair(
iter->second.from(), std::make_pair(
iter->second.to(),
iter->second.type())));
212 biLinks.insert(std::make_pair(
iter->second.to(), std::make_pair(
iter->second.from(),
iter->second.type())));
217 while(nextPoses.size())
219 int currentId = *nextPoses.rbegin();
220 nextPoses.erase(*nextPoses.rbegin());
224 posesOut.insert(std::make_pair(currentId, posesIn.find(currentId)->second));
227 for(std::multimap<int, Link>::const_iterator pter=linksIn.find(currentId); pter!=linksIn.end() && pter->first==currentId; ++pter)
231 linksOut.insert(*pter);
236 for(std::multimap<
int, std::pair<int, Link::Type> >::const_iterator
iter=biLinks.find(currentId);
iter!=biLinks.end() &&
iter->first==currentId; ++
iter)
238 int toId =
iter->second.first;
242 std::multimap<int, Link>::const_iterator kter =
graph::findLink(linksIn, currentId, toId,
true,
type);
243 if(nextPoses.find(toId) == nextPoses.end())
247 const Transform & poseToIn = posesIn.at(toId);
248 Transform t = kter->second.from()==currentId?kter->second.transform():kter->second.transform().inverse();
253 posesOut.insert(std::make_pair(toId, (posesOut.at(currentId) *
t).to3DoF()));
257 posesOut.insert(std::make_pair(toId, (posesOut.at(currentId) *
t).to4DoF()));
262 posesOut.insert(std::make_pair(toId, posesOut.at(currentId)*
t));
266 for(std::multimap<int, Link>::const_iterator pter=linksIn.find(toId); pter!=linksIn.end() && pter->first==toId; ++pter)
270 linksOut.insert(*pter);
274 nextPoses.insert(toId);
278 if(
graph::findLink(linksOut, currentId, toId,
true, kter->second.type()) == linksOut.end())
280 if(kter->second.to() < 0)
283 linksOut.insert(std::make_pair(kter->second.to(), kter->second.inverse()));
287 linksOut.insert(*kter);
294 UDEBUG(
"OUT: poses=%d links=%d", (
int)posesOut.size(), (
int)linksOut.size());
297 Optimizer::Optimizer(
int iterations,
bool slam2d,
bool covarianceIgnored,
double epsilon,
bool robust,
bool priorsIgnored,
bool landmarksIgnored,
float gravitySigma) :
298 iterations_(iterations),
300 covarianceIgnored_(covarianceIgnored),
303 priorsIgnored_(priorsIgnored),
304 landmarksIgnored_(landmarksIgnored),
305 gravitySigma_(gravitySigma)
310 iterations_(
Parameters::defaultOptimizerIterations()),
312 covarianceIgnored_(
Parameters::defaultOptimizerVarianceIgnored()),
313 epsilon_(
Parameters::defaultOptimizerEpsilon()),
314 robust_(
Parameters::defaultOptimizerRobust()),
315 priorsIgnored_(
Parameters::defaultOptimizerPriorsIgnored()),
316 landmarksIgnored_(
Parameters::defaultOptimizerLandmarksIgnored()),
317 gravitySigma_(
Parameters::defaultOptimizerGravitySigma())
336 const std::map<int, Transform> & poses,
337 const std::multimap<int, Link> & constraints,
338 std::list<std::map<int, Transform> > * intermediateGraphes,
340 int * iterationsDone)
342 std::map<int, Transform> incGraph;
343 std::multimap<int, Link> incGraphLinks;
344 incGraph.insert(*poses.begin());
346 std::multimap<int, Link> constraintsCpy = constraints;
347 UDEBUG(
"Incremental optimization... poses=%d constraints=%d", (
int)poses.size(), (
int)constraints.size());
348 for(std::map<int, Transform>::const_iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
350 incGraph.insert(*
iter);
351 bool hasLoopClosure =
false;
352 for(std::multimap<int, Link>::iterator jter=constraintsCpy.lower_bound(
iter->first); jter!=constraintsCpy.end() && jter->first==
iter->first; ++jter)
354 UDEBUG(
"%d: %d -> %d type=%d",
iter->first, jter->second.from(), jter->second.to(), jter->second.type());
358 incGraph.insert(std::make_pair(jter->second.to(), incGraph.at(
iter->first) * jter->second.transform()));
359 incGraphLinks.insert(*jter);
363 if(!
uContains(incGraph, jter->second.to()) && jter->second.to() >
iter->first)
366 constraintsCpy.insert(std::make_pair(jter->second.to(), jter->second.inverse()));
371 incGraphLinks.insert(*jter);
372 hasLoopClosure =
true;
378 incGraph = this->
optimize(incGraph.begin()->first, incGraph, incGraphLinks);
381 UWARN(
"Failed incremental optimization... last pose added is %d",
iter->first);
385 UDEBUG(
"Iteration %d/%d %s", ++
i, (
int)poses.size(), hasLoopClosure?
"*":
"");
387 if(!incGraph.empty() && incGraph.size() == poses.size())
389 UASSERT(incGraphLinks.size() == constraints.size());
391 incGraph.at(rootId) = poses.at(rootId);
392 return this->
optimize(rootId, incGraph, incGraphLinks, intermediateGraphes, finalError, iterationsDone);
395 UDEBUG(
"Failed incremental optimization");
396 return std::map<int, Transform>();
401 const std::map<int, Transform> & poses,
402 const std::multimap<int, Link> & edgeConstraints,
403 std::list<std::map<int, Transform> > * intermediateGraphes,
405 int * iterationsDone)
419 const std::map<int, Transform> & poses,
420 const std::multimap<int, Link> & constraints,
421 cv::Mat & outputCovariance,
422 std::list<std::map<int, Transform> > * intermediateGraphes,
424 int * iterationsDone)
426 UERROR(
"Optimizer %d doesn't implement optimize() method.", (
int)this->
type());
427 return std::map<int, Transform>();
432 const std::map<int, Transform> & poses,
433 const std::multimap<int, Link> & links,
434 const std::map<
int, std::vector<CameraModel> > & models,
435 std::map<int, cv::Point3f> & points3DMap,
436 const std::map<
int, std::map<int, FeatureBA> > & wordReferences,
437 std::set<int> * outliers)
439 UERROR(
"Optimizer %d doesn't implement optimizeBA() method.", (
int)this->
type());
440 return std::map<int, Transform>();
445 const std::map<int, Transform> & posesIn,
446 const std::multimap<int, Link> & links,
447 const std::map<int, Signature> & signatures,
448 std::map<int, cv::Point3f> & points3DMap,
449 std::map<
int, std::map<int, FeatureBA> > & wordReferences,
450 bool rematchFeatures)
453 std::map<int, std::vector<CameraModel> > multiModels;
454 std::map<int, Transform> poses;
455 for(std::map<int, Transform>::const_iterator
iter=posesIn.lower_bound(1);
iter!=posesIn.end(); ++
iter)
458 std::vector<CameraModel> models;
462 if(
s.cameraModels().size() >= 1 &&
s.cameraModels().at(0).isValidForProjection())
464 models =
s.cameraModels();
466 else if(!
s.stereoCameraModels().empty() &&
s.stereoCameraModels()[0].isValidForProjection())
468 for(
size_t i=0;
i<
s.stereoCameraModels().
size(); ++
i)
478 model.localTransform(),
479 -
s.stereoCameraModels()[
i].baseline()*
model.fx(),
485 UERROR(
"Missing calibration for node %d",
iter->first);
486 return std::map<int, Transform>();
491 UERROR(
"Did not find node %d in cache",
iter->first);
492 return std::map<int, Transform>();
495 multiModels.insert(std::make_pair(
iter->first, models));
502 return optimizeBA(rootId, poses, links, multiModels, points3DMap, wordReferences);
507 const std::map<int, Transform> & poses,
508 const std::multimap<int, Link> & links,
509 const std::map<int, Signature> & signatures,
510 bool rematchFeatures)
512 std::map<int, cv::Point3f> points3DMap;
513 std::map<int, std::map<int, FeatureBA> > wordReferences;
514 return optimizeBA(rootId, poses, links, signatures, points3DMap, wordReferences, rematchFeatures);
520 std::map<int, cv::Point3f> & points3DMap,
521 const std::map<
int, std::map<int, FeatureBA> > & wordReferences,
522 std::set<int> * outliers)
524 std::map<int, Transform> poses;
526 poses.insert(std::make_pair(link.
to(), link.
transform()));
527 std::multimap<int, Link> links;
528 links.insert(std::make_pair(link.
from(), link));
529 std::map<int, std::vector<CameraModel> > models;
530 std::vector<CameraModel> tmp;
531 tmp.push_back(
model);
532 models.insert(std::make_pair(link.
from(), tmp));
533 models.insert(std::make_pair(link.
to(), tmp));
534 poses =
optimizeBA(link.
from(), poses, links, models, points3DMap, wordReferences, outliers);
535 if(poses.size() == 2)
537 return poses.rbegin()->second;
549 return lhs.pt.x < rhs.pt.x || (
lhs.pt.x == rhs.pt.x &&
lhs.pt.y < rhs.pt.y);
554 const std::map<int, Transform> & poses,
555 const std::multimap<int, Link> & links,
556 const std::map<int, Signature> & signatures,
557 std::map<int, cv::Point3f> & points3DMap,
558 std::map<
int, std::map<int, FeatureBA> > & wordReferences,
559 bool rematchFeatures)
561 UDEBUG(
"rematchFeatures=%d", rematchFeatures?1:0);
563 int edgeWithWordsAdded = 0;
564 std::map<int, std::map<cv::KeyPoint, int, KeyPointCompare> > frameToWordMap;
565 for(std::multimap<int, Link>::const_iterator
iter=links.lower_bound(1);
iter!=links.end(); ++
iter)
568 if(link.
to() < link.
from())
572 if(link.
to() != link.
from() &&
585 UERROR(
"No camera models found");
591 for(std::multimap<int, Link>::const_iterator jter=links.find(sTo.
id());
595 sTo = signatures.at(jter->second.to());
604 regParam.insert(
ParametersPair(Parameters::kVisEstimationType(),
"1"));
605 regParam.insert(
ParametersPair(Parameters::kVisPnPReprojError(),
"5"));
606 regParam.insert(
ParametersPair(Parameters::kVisMinInliers(),
"6"));
607 regParam.insert(
ParametersPair(Parameters::kVisCorNNDR(),
"0.6"));
619 UDEBUG(
"%d->%d, inliers=%d",sFrom.
id(), sTo.
id(), (
int)
info.inliersIDs.size());
628 (
int)sFrom.
getWords().size() == signatures.at(link.
from()).getWordsDescriptors().rows)
634 (
int)sTo.
getWords().size() == signatures.at(link.
to()).getWordsDescriptors().rows)
642 for(
unsigned int i=0;
i<
info.inliersIDs.size(); ++
i)
644 int indexFrom = sFrom.
getWords().lower_bound(
info.inliersIDs[
i])->second;
649 int indexTo = sTo.
getWords().lower_bound(
info.inliersIDs[
i])->second;
655 std::map<int, std::map<cv::KeyPoint, int, KeyPointCompare> >
::iterator fromIter = frameToWordMap.find(sFrom.
id());
656 std::map<int, std::map<cv::KeyPoint, int, KeyPointCompare> >
::iterator toIter = frameToWordMap.find(sTo.
id());
657 bool fromAlreadyAdded =
false;
658 bool toAlreadyAdded =
false;
659 if( fromIter != frameToWordMap.end() &&
660 fromIter->second.find(ptFrom) != fromIter->second.end())
662 wordId = fromIter->second.at(ptFrom);
663 fromAlreadyAdded =
true;
665 if( toIter != frameToWordMap.end() &&
666 toIter->second.find(ptTo) != toIter->second.end())
668 wordId = toIter->second.at(ptTo);
669 toAlreadyAdded =
true;
674 wordId = ++wordCount;
675 wordReferences.insert(std::make_pair(wordId, std::map<int, FeatureBA>()));
681 UASSERT(wordReferences.find(wordId) != wordReferences.end());
682 UASSERT(points3DMap.find(wordId) != points3DMap.end());
685 if(!fromAlreadyAdded)
687 cv::Mat descriptorFrom;
697 cameraIndex =
int(ptFrom.pt.x / subImageWidth);
698 ptFrom.pt.x = ptFrom.pt.x - (subImageWidth*
float(cameraIndex));
713 wordReferences.at(wordId).insert(std::make_pair(sFrom.
id(),
FeatureBA(ptFrom, depth, descriptorFrom, cameraIndex)));
714 frameToWordMap.insert(std::make_pair(sFrom.
id(), std::map<cv::KeyPoint, int, KeyPointCompare>()));
715 frameToWordMap.at(sFrom.
id()).insert(std::make_pair(ptFrom, wordId));
720 cv::Mat descriptorTo;
731 cameraIndex =
int(ptTo.pt.x / subImageWidth);
732 ptTo.pt.x = ptTo.pt.x - (subImageWidth*
float(cameraIndex));
739 const cv::Point3f & pt = sTo.
getWords3()[indexTo];
751 wordReferences.at(wordId).insert(std::make_pair(sTo.
id(),
FeatureBA(ptTo, depth, descriptorTo, cameraIndex)));
752 frameToWordMap.insert(std::make_pair(sTo.
id(), std::map<cv::KeyPoint, int, KeyPointCompare>()));
753 frameToWordMap.at(sTo.
id()).insert(std::make_pair(ptTo, wordId));
757 ++edgeWithWordsAdded;
761 UWARN(
"Not enough inliers (%d) between %d and %d",
info.inliersIDs.size(), sFrom.
id(), sTo.
id());
767 UDEBUG(
"Added %d words (edges with words=%d/%d)", wordCount, edgeWithWordsAdded, links.size());
770 UERROR(
"No links found for BA?!");
772 else if(wordCount == 0)
774 UERROR(
"No words added for BA?!");