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, int> biLinks;
205 for(std::multimap<int, Link>::const_iterator iter=linksIn.begin(); iter!=linksIn.end(); ++iter)
207 if(iter->second.from() != iter->second.to())
209 if(
graph::findLink(biLinks, iter->second.from(), iter->second.to()) == biLinks.end())
211 biLinks.insert(std::make_pair(iter->second.from(), iter->second.to()));
212 biLinks.insert(std::make_pair(iter->second.to(), iter->second.from()));
217 while(nextPoses.size())
219 int fromId = *nextPoses.rbegin();
220 nextPoses.erase(*nextPoses.rbegin());
224 posesOut.insert(std::make_pair(fromId, posesIn.find(fromId)->second));
227 for(std::multimap<int, Link>::const_iterator pter=linksIn.find(fromId); pter!=linksIn.end() && pter->first==fromId; ++pter)
231 linksOut.insert(*pter);
236 for(std::multimap<int, int>::const_iterator iter=biLinks.find(fromId); iter!=biLinks.end() && iter->first==fromId; ++iter)
238 int toId = iter->second;
241 std::multimap<int, Link>::const_iterator kter =
graph::findLink(linksIn, fromId, toId);
242 if(nextPoses.find(toId) == nextPoses.end())
249 if(kter->second.from()==fromId)
251 t = kter->second.transform();
255 t = kter->second.transform().
inverse();
257 posesOut.insert(std::make_pair(toId, (posesOut.at(fromId) * t).to3DoF()));
261 Transform t = posesOut.at(fromId) * (kter->second.from()==fromId?kter->second.transform():kter->second.transform().inverse());
262 posesOut.insert(std::make_pair(toId, t));
265 for(std::multimap<int, Link>::const_iterator pter=linksIn.find(toId); pter!=linksIn.end() && pter->first==toId; ++pter)
269 linksOut.insert(*pter);
273 nextPoses.insert(toId);
279 if(kter->second.to() < 0)
282 linksOut.insert(std::make_pair(kter->second.to(), kter->second.inverse()));
286 linksOut.insert(*kter);
293 UDEBUG(
"OUT: poses=%d links=%d", (
int)posesOut.size(), (int)linksOut.size());
335 const std::map<int, Transform> & poses,
336 const std::multimap<int, Link> & constraints,
337 std::list<std::map<int, Transform> > * intermediateGraphes,
339 int * iterationsDone)
341 std::map<int, Transform> incGraph;
342 std::multimap<int, Link> incGraphLinks;
343 incGraph.insert(*poses.begin());
345 std::multimap<int, Link> constraintsCpy = constraints;
346 UDEBUG(
"Incremental optimization... poses=%d constraints=%d", (
int)poses.size(), (int)constraints.size());
347 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
349 incGraph.insert(*iter);
350 bool hasLoopClosure =
false;
351 for(std::multimap<int, Link>::iterator jter=constraintsCpy.lower_bound(iter->first); jter!=constraintsCpy.end() && jter->first==iter->first; ++jter)
353 UDEBUG(
"%d: %d -> %d type=%d", iter->first, jter->second.from(), jter->second.to(), jter->second.type());
357 incGraph.insert(std::make_pair(jter->second.to(), incGraph.at(iter->first) * jter->second.transform()));
358 incGraphLinks.insert(*jter);
362 if(!
uContains(incGraph, jter->second.to()) && jter->second.to() > iter->first)
365 constraintsCpy.insert(std::make_pair(jter->second.to(), jter->second.inverse()));
370 incGraphLinks.insert(*jter);
371 hasLoopClosure =
true;
377 incGraph = this->
optimize(incGraph.begin()->first, incGraph, incGraphLinks);
380 UWARN(
"Failed incremental optimization... last pose added is %d", iter->first);
384 UDEBUG(
"Iteration %d/%d %s", ++i, (
int)poses.size(), hasLoopClosure?
"*":
"");
386 if(!incGraph.empty() && incGraph.size() == poses.size())
388 UASSERT(incGraphLinks.size() == constraints.size());
390 incGraph.at(rootId) = poses.at(rootId);
391 return this->
optimize(rootId, incGraph, incGraphLinks, intermediateGraphes, finalError, iterationsDone);
394 UDEBUG(
"Failed incremental optimization");
395 return std::map<int, Transform>();
400 const std::map<int, Transform> & poses,
401 const std::multimap<int, Link> & edgeConstraints,
402 std::list<std::map<int, Transform> > * intermediateGraphes,
404 int * iterationsDone)
418 const std::map<int, Transform> & poses,
419 const std::multimap<int, Link> & constraints,
420 cv::Mat & outputCovariance,
421 std::list<std::map<int, Transform> > * intermediateGraphes,
423 int * iterationsDone)
425 UERROR(
"Optimizer %d doesn't implement optimize() method.", (
int)this->
type());
426 return std::map<int, Transform>();
431 const std::map<int, Transform> & poses,
432 const std::multimap<int, Link> & links,
433 const std::map<int, CameraModel> & models,
434 std::map<int, cv::Point3f> & points3DMap,
435 const std::map<
int, std::map<int, FeatureBA> > & wordReferences,
436 std::set<int> * outliers)
438 UERROR(
"Optimizer %d doesn't implement optimizeBA() method.", (
int)this->
type());
439 return std::map<int, Transform>();
444 const std::map<int, Transform> & posesIn,
445 const std::multimap<int, Link> & links,
446 const std::map<int, Signature> & signatures,
447 std::map<int, cv::Point3f> & points3DMap,
448 std::map<
int, std::map<int, FeatureBA> > & wordReferences,
449 bool rematchFeatures)
452 std::map<int, CameraModel> models;
453 std::map<int, Transform> poses;
454 for(std::map<int, Transform>::const_iterator iter=posesIn.lower_bound(1); iter!=posesIn.end(); ++iter)
460 if(signatures.at(iter->first).sensorData().cameraModels().size() == 1 && signatures.at(iter->first).sensorData().cameraModels().at(0).isValidForProjection())
462 model = signatures.at(iter->first).sensorData().cameraModels()[0];
464 else if(signatures.at(iter->first).sensorData().stereoCameraModel().isValidForProjection())
466 model = signatures.at(iter->first).sensorData().stereoCameraModel().left();
475 -signatures.at(iter->first).sensorData().stereoCameraModel().baseline()*model.
fx());
477 else if(signatures.at(iter->first).sensorData().cameraModels().size() > 1)
479 UERROR(
"Multi-cameras (%d) is not supported (id=%d).",
480 signatures.at(iter->first).sensorData().cameraModels().size(),
482 return std::map<int, Transform>();
486 UERROR(
"Missing calibration for node %d", iter->first);
487 return std::map<int, Transform>();
492 UERROR(
"Did not find node %d in cache", iter->first);
493 return std::map<int, Transform>();
498 models.insert(std::make_pair(iter->first, model));
505 return optimizeBA(rootId, poses, links, models, points3DMap, wordReferences);
510 const std::map<int, Transform> & poses,
511 const std::multimap<int, Link> & links,
512 const std::map<int, Signature> & signatures,
513 bool rematchFeatures)
515 std::map<int, cv::Point3f> points3DMap;
516 std::map<int, std::map<int, FeatureBA> > wordReferences;
517 return optimizeBA(rootId, poses, links, signatures, points3DMap, wordReferences, rematchFeatures);
523 std::map<int, cv::Point3f> & points3DMap,
524 const std::map<
int, std::map<int, FeatureBA> > & wordReferences,
525 std::set<int> * outliers)
527 std::map<int, Transform> poses;
529 poses.insert(std::make_pair(link.
to(), link.
transform()));
530 std::multimap<int, Link> links;
531 links.insert(std::make_pair(link.
from(), link));
532 std::map<int, CameraModel> models;
533 models.insert(std::make_pair(link.
from(), model));
534 models.insert(std::make_pair(link.
to(), model));
535 poses =
optimizeBA(link.
from(), poses, links, models, points3DMap, wordReferences, outliers);
536 if(poses.size() == 2)
538 return poses.rbegin()->second;
548 bool operator() (
const cv::KeyPoint&
lhs,
const cv::KeyPoint& rhs)
const 550 return lhs.pt.x < rhs.pt.x || (lhs.pt.x == rhs.pt.x && lhs.pt.y < rhs.pt.y);
555 const std::map<int, Transform> & poses,
556 const std::multimap<int, Link> & links,
557 const std::map<int, Signature> & signatures,
558 std::map<int, cv::Point3f> & points3DMap,
559 std::map<
int, std::map<int, FeatureBA> > & wordReferences,
560 bool rematchFeatures)
564 int edgeWithWordsAdded = 0;
565 std::map<int, std::map<cv::KeyPoint, int, KeyPointCompare> > frameToWordMap;
566 for(std::multimap<int, Link>::const_iterator iter=links.lower_bound(1); iter!=links.end(); ++iter)
568 Link link = iter->second;
569 if(link.
to() < link.
from())
573 if(link.
to() != link.
from() &&
584 for(std::multimap<int, Link>::const_iterator jter=links.find(sTo.
id());
588 sTo = signatures.at(jter->second.to());
597 regParam.insert(
ParametersPair(Parameters::kVisEstimationType(),
"1"));
598 regParam.insert(
ParametersPair(Parameters::kVisPnPReprojError(),
"5"));
599 regParam.insert(
ParametersPair(Parameters::kVisMinInliers(),
"6"));
600 regParam.insert(
ParametersPair(Parameters::kVisCorNNDR(),
"0.6"));
621 (int)sFrom.
getWords().size() == signatures.at(link.
from()).getWordsDescriptors().rows)
627 (int)sTo.
getWords().size() == signatures.at(link.
to()).getWordsDescriptors().rows)
635 for(
unsigned int i=0; i<info.
inliersIDs.size(); ++i)
638 cv::Point3f p = sFrom.
getWords3()[indexFrom];
648 std::map<int, std::map<cv::KeyPoint, int, KeyPointCompare> >::iterator fromIter = frameToWordMap.find(sFrom.
id());
649 std::map<int, std::map<cv::KeyPoint, int, KeyPointCompare> >::iterator toIter = frameToWordMap.find(sTo.
id());
650 bool fromAlreadyAdded =
false;
651 bool toAlreadyAdded =
false;
652 if( fromIter != frameToWordMap.end() &&
653 fromIter->second.find(ptFrom) != fromIter->second.end())
655 wordId = fromIter->second.at(ptFrom);
656 fromAlreadyAdded =
true;
658 if( toIter != frameToWordMap.end() &&
659 toIter->second.find(ptTo) != toIter->second.end())
661 wordId = toIter->second.at(ptTo);
662 toAlreadyAdded =
true;
667 wordId = ++wordCount;
668 wordReferences.insert(std::make_pair(wordId, std::map<int, FeatureBA>()));
671 points3DMap.insert(std::make_pair(wordId, p));
675 UASSERT(wordReferences.find(wordId) != wordReferences.end());
676 UASSERT(points3DMap.find(wordId) != points3DMap.end());
679 if(!fromAlreadyAdded)
681 cv::Mat descriptorFrom;
687 wordReferences.at(wordId).insert(std::make_pair(sFrom.
id(),
FeatureBA(ptFrom, p.x, descriptorFrom)));
688 frameToWordMap.insert(std::make_pair(sFrom.
id(), std::map<cv::KeyPoint, int, KeyPointCompare>()));
689 frameToWordMap.at(sFrom.
id()).insert(std::make_pair(ptFrom, wordId));
694 cv::Mat descriptorTo;
704 const cv::Point3f & pt = sTo.
getWords3()[indexTo];
710 wordReferences.at(wordId).insert(std::make_pair(sTo.
id(),
FeatureBA(ptTo, depth, descriptorTo)));
711 frameToWordMap.insert(std::make_pair(sTo.
id(), std::map<cv::KeyPoint, int, KeyPointCompare>()));
712 frameToWordMap.at(sTo.
id()).insert(std::make_pair(ptTo, wordId));
716 ++edgeWithWordsAdded;
720 UWARN(
"Not enough inliers (%d) between %d and %d", info.
inliersIDs.size(), sFrom.
id(), sTo.
id());
726 UDEBUG(
"Added %d words (edges with words=%d/%d)", wordCount, edgeWithWordsAdded, links.size());
bool priorsIgnored() const
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
float gravitySigma() const
Optimizer(int iterations=Parameters::defaultOptimizerIterations(), bool slam2d=Parameters::defaultRegForce3DoF(), bool covarianceIgnored=Parameters::defaultOptimizerVarianceIgnored(), double epsilon=Parameters::defaultOptimizerEpsilon(), bool robust=Parameters::defaultOptimizerRobust(), bool priorsIgnored=Parameters::defaultOptimizerPriorsIgnored(), bool landmarksIgnored=Parameters::defaultOptimizerLandmarksIgnored(), float gravitySigma=Parameters::defaultOptimizerGravitySigma())
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
virtual std::map< int, Transform > optimizeBA(int rootId, const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const std::map< int, CameraModel > &models, std::map< int, cv::Point3f > &points3DMap, const std::map< int, std::map< int, FeatureBA > > &wordReferences, std::set< int > *outliers=0)
Transform computeTransformationMod(Signature &from, Signature &to, Transform guess=Transform::getIdentity(), RegistrationInfo *info=0) const
std::pair< std::string, std::string > ParametersPair
std::map< std::string, std::string > ParametersMap
Basic mathematics functions.
std::vector< int > inliersIDs
Some conversion functions.
static bool isAvailable(Optimizer::Type type)
const Transform & transform() const
const std::vector< cv::KeyPoint > & getWordsKpts() const
#define UASSERT(condition)
Wrappers of STL for convenient functions.
std::map< int, Transform > optimizeIncremental(int rootId, const std::map< int, Transform > &poses, const std::multimap< int, Link > &constraints, std::list< std::map< int, Transform > > *intermediateGraphes=0, double *finalError=0, int *iterationsDone=0)
bool landmarksIgnored() const
virtual void parseParameters(const ParametersMap ¶meters)
const std::multimap< int, int > & getWords() const
#define UASSERT_MSG(condition, msg_str)
std::map< int, Transform > optimize(int rootId, const std::map< int, Transform > &poses, const std::multimap< int, Link > &constraints, std::list< std::map< int, Transform > > *intermediateGraphes=0, double *finalError=0, int *iterationsDone=0)
void setWordsDescriptors(const cv::Mat &descriptors)
const cv::Mat & getWordsDescriptors() const
bool uContains(const std::list< V > &list, const V &value)
void getConnectedGraph(int fromId, const std::map< int, Transform > &posesIn, const std::multimap< int, Link > &linksIn, std::map< int, Transform > &posesOut, std::multimap< int, Link > &linksOut) const
bool isValidForProjection() const
virtual Type type() const =0
const std::vector< cv::Point3f > & getWords3() const
std::multimap< int, Link >::iterator RTABMAP_EXP findLink(std::multimap< int, Link > &links, int from, int to, bool checkBothWays=true)
ULogger class and convenient macros.
void computeBACorrespondences(const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const std::map< int, Signature > &signatures, std::map< int, cv::Point3f > &points3DMap, std::map< int, std::map< int, FeatureBA > > &wordReferences, bool rematchFeatures=false)
static Optimizer * create(const ParametersMap ¶meters)
const Transform & localTransform() const