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,
194 bool adjustPosesWithConstraints)
const 196 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);
203 std::set<int> nextPoses;
204 nextPoses.insert(fromId);
205 std::multimap<int, int> biLinks;
206 for(std::multimap<int, Link>::const_iterator iter=linksIn.begin(); iter!=linksIn.end(); ++iter)
208 if(iter->second.from() != iter->second.to())
210 if(
graph::findLink(biLinks, iter->second.from(), iter->second.to()) == biLinks.end())
212 biLinks.insert(std::make_pair(iter->second.from(), iter->second.to()));
213 biLinks.insert(std::make_pair(iter->second.to(), iter->second.from()));
218 while(nextPoses.size())
220 int currentId = *nextPoses.rbegin();
221 nextPoses.erase(*nextPoses.rbegin());
225 posesOut.insert(std::make_pair(currentId, posesIn.find(currentId)->second));
228 for(std::multimap<int, Link>::const_iterator pter=linksIn.find(currentId); pter!=linksIn.end() && pter->first==currentId; ++pter)
232 linksOut.insert(*pter);
237 for(std::multimap<int, int>::const_iterator iter=biLinks.find(currentId); iter!=biLinks.end() && iter->first==currentId; ++iter)
239 int toId = iter->second;
242 std::multimap<int, Link>::const_iterator kter =
graph::findLink(linksIn, currentId, toId);
243 if(nextPoses.find(toId) == nextPoses.end())
247 if(adjustPosesWithConstraints)
252 if(kter->second.from()==currentId)
254 t = kter->second.transform();
258 t = kter->second.transform().
inverse();
260 posesOut.insert(std::make_pair(toId, (posesOut.at(currentId) * t).to3DoF()));
264 Transform t = posesOut.at(currentId) * (kter->second.from()==currentId?kter->second.transform():kter->second.transform().inverse());
265 posesOut.insert(std::make_pair(toId, t));
270 posesOut.insert(*posesIn.find(toId));
273 for(std::multimap<int, Link>::const_iterator pter=linksIn.find(toId); pter!=linksIn.end() && pter->first==toId; ++pter)
277 linksOut.insert(*pter);
281 nextPoses.insert(toId);
287 if(kter->second.to() < 0)
290 linksOut.insert(std::make_pair(kter->second.to(), kter->second.inverse()));
294 linksOut.insert(*kter);
301 UDEBUG(
"OUT: poses=%d links=%d", (
int)posesOut.size(), (int)linksOut.size());
343 const std::map<int, Transform> & poses,
344 const std::multimap<int, Link> & constraints,
345 std::list<std::map<int, Transform> > * intermediateGraphes,
347 int * iterationsDone)
349 std::map<int, Transform> incGraph;
350 std::multimap<int, Link> incGraphLinks;
351 incGraph.insert(*poses.begin());
353 std::multimap<int, Link> constraintsCpy = constraints;
354 UDEBUG(
"Incremental optimization... poses=%d constraints=%d", (
int)poses.size(), (int)constraints.size());
355 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
357 incGraph.insert(*iter);
358 bool hasLoopClosure =
false;
359 for(std::multimap<int, Link>::iterator jter=constraintsCpy.lower_bound(iter->first); jter!=constraintsCpy.end() && jter->first==iter->first; ++jter)
361 UDEBUG(
"%d: %d -> %d type=%d", iter->first, jter->second.from(), jter->second.to(), jter->second.type());
365 incGraph.insert(std::make_pair(jter->second.to(), incGraph.at(iter->first) * jter->second.transform()));
366 incGraphLinks.insert(*jter);
370 if(!
uContains(incGraph, jter->second.to()) && jter->second.to() > iter->first)
373 constraintsCpy.insert(std::make_pair(jter->second.to(), jter->second.inverse()));
378 incGraphLinks.insert(*jter);
379 hasLoopClosure =
true;
385 incGraph = this->
optimize(incGraph.begin()->first, incGraph, incGraphLinks);
388 UWARN(
"Failed incremental optimization... last pose added is %d", iter->first);
392 UDEBUG(
"Iteration %d/%d %s", ++i, (
int)poses.size(), hasLoopClosure?
"*":
"");
394 if(!incGraph.empty() && incGraph.size() == poses.size())
396 UASSERT(incGraphLinks.size() == constraints.size());
398 incGraph.at(rootId) = poses.at(rootId);
399 return this->
optimize(rootId, incGraph, incGraphLinks, intermediateGraphes, finalError, iterationsDone);
402 UDEBUG(
"Failed incremental optimization");
403 return std::map<int, Transform>();
408 const std::map<int, Transform> & poses,
409 const std::multimap<int, Link> & edgeConstraints,
410 std::list<std::map<int, Transform> > * intermediateGraphes,
412 int * iterationsDone)
426 const std::map<int, Transform> & poses,
427 const std::multimap<int, Link> & constraints,
428 cv::Mat & outputCovariance,
429 std::list<std::map<int, Transform> > * intermediateGraphes,
431 int * iterationsDone)
433 UERROR(
"Optimizer %d doesn't implement optimize() method.", (
int)this->
type());
434 return std::map<int, Transform>();
439 const std::map<int, Transform> & poses,
440 const std::multimap<int, Link> & links,
441 const std::map<
int, std::vector<CameraModel> > & models,
442 std::map<int, cv::Point3f> & points3DMap,
443 const std::map<
int, std::map<int, FeatureBA> > & wordReferences,
444 std::set<int> * outliers)
446 UERROR(
"Optimizer %d doesn't implement optimizeBA() method.", (
int)this->
type());
447 return std::map<int, Transform>();
452 const std::map<int, Transform> & posesIn,
453 const std::multimap<int, Link> & links,
454 const std::map<int, Signature> & signatures,
455 std::map<int, cv::Point3f> & points3DMap,
456 std::map<
int, std::map<int, FeatureBA> > & wordReferences,
457 bool rematchFeatures)
460 std::map<int, std::vector<CameraModel> > multiModels;
461 std::map<int, Transform> poses;
462 for(std::map<int, Transform>::const_iterator iter=posesIn.lower_bound(1); iter!=posesIn.end(); ++iter)
465 std::vector<CameraModel> models;
468 const SensorData & s = signatures.at(iter->first).sensorData();
492 UERROR(
"Missing calibration for node %d", iter->first);
493 return std::map<int, Transform>();
498 UERROR(
"Did not find node %d in cache", iter->first);
499 return std::map<int, Transform>();
502 multiModels.insert(std::make_pair(iter->first, models));
509 return optimizeBA(rootId, poses, links, multiModels, points3DMap, wordReferences);
514 const std::map<int, Transform> & poses,
515 const std::multimap<int, Link> & links,
516 const std::map<int, Signature> & signatures,
517 bool rematchFeatures)
519 std::map<int, cv::Point3f> points3DMap;
520 std::map<int, std::map<int, FeatureBA> > wordReferences;
521 return optimizeBA(rootId, poses, links, signatures, points3DMap, wordReferences, rematchFeatures);
527 std::map<int, cv::Point3f> & points3DMap,
528 const std::map<
int, std::map<int, FeatureBA> > & wordReferences,
529 std::set<int> * outliers)
531 std::map<int, Transform> poses;
533 poses.insert(std::make_pair(link.
to(), link.
transform()));
534 std::multimap<int, Link> links;
535 links.insert(std::make_pair(link.
from(), link));
536 std::map<int, std::vector<CameraModel> > models;
537 std::vector<CameraModel> tmp;
538 tmp.push_back(model);
539 models.insert(std::make_pair(link.
from(), tmp));
540 models.insert(std::make_pair(link.
to(), tmp));
541 poses =
optimizeBA(link.
from(), poses, links, models, points3DMap, wordReferences, outliers);
542 if(poses.size() == 2)
544 return poses.rbegin()->second;
554 bool operator() (
const cv::KeyPoint&
lhs,
const cv::KeyPoint& rhs)
const 556 return lhs.pt.x < rhs.pt.x || (lhs.pt.x == rhs.pt.x && lhs.pt.y < rhs.pt.y);
561 const std::map<int, Transform> & poses,
562 const std::multimap<int, Link> & links,
563 const std::map<int, Signature> & signatures,
564 std::map<int, cv::Point3f> & points3DMap,
565 std::map<
int, std::map<int, FeatureBA> > & wordReferences,
566 bool rematchFeatures)
568 UDEBUG(
"rematchFeatures=%d", rematchFeatures?1:0);
570 int edgeWithWordsAdded = 0;
571 std::map<int, std::map<cv::KeyPoint, int, KeyPointCompare> > frameToWordMap;
572 for(std::multimap<int, Link>::const_iterator iter=links.lower_bound(1); iter!=links.end(); ++iter)
574 Link link = iter->second;
575 if(link.
to() < link.
from())
579 if(link.
to() != link.
from() &&
592 UERROR(
"No camera models found");
598 for(std::multimap<int, Link>::const_iterator jter=links.find(sTo.
id());
602 sTo = signatures.at(jter->second.to());
611 regParam.insert(
ParametersPair(Parameters::kVisEstimationType(),
"1"));
612 regParam.insert(
ParametersPair(Parameters::kVisPnPReprojError(),
"5"));
613 regParam.insert(
ParametersPair(Parameters::kVisMinInliers(),
"6"));
614 regParam.insert(
ParametersPair(Parameters::kVisCorNNDR(),
"0.6"));
635 (int)sFrom.
getWords().size() == signatures.at(link.
from()).getWordsDescriptors().rows)
641 (int)sTo.
getWords().size() == signatures.at(link.
to()).getWordsDescriptors().rows)
649 for(
unsigned int i=0; i<info.
inliersIDs.size(); ++i)
652 cv::Point3f p = sFrom.
getWords3()[indexFrom];
662 std::map<int, std::map<cv::KeyPoint, int, KeyPointCompare> >::iterator fromIter = frameToWordMap.find(sFrom.
id());
663 std::map<int, std::map<cv::KeyPoint, int, KeyPointCompare> >::iterator toIter = frameToWordMap.find(sTo.
id());
664 bool fromAlreadyAdded =
false;
665 bool toAlreadyAdded =
false;
666 if( fromIter != frameToWordMap.end() &&
667 fromIter->second.find(ptFrom) != fromIter->second.end())
669 wordId = fromIter->second.at(ptFrom);
670 fromAlreadyAdded =
true;
672 if( toIter != frameToWordMap.end() &&
673 toIter->second.find(ptTo) != toIter->second.end())
675 wordId = toIter->second.at(ptTo);
676 toAlreadyAdded =
true;
681 wordId = ++wordCount;
682 wordReferences.insert(std::make_pair(wordId, std::map<int, FeatureBA>()));
688 UASSERT(wordReferences.find(wordId) != wordReferences.end());
689 UASSERT(points3DMap.find(wordId) != points3DMap.end());
692 if(!fromAlreadyAdded)
694 cv::Mat descriptorFrom;
704 cameraIndex = int(ptFrom.pt.x / subImageWidth);
705 ptFrom.pt.x = ptFrom.pt.x - (subImageWidth*float(cameraIndex));
720 wordReferences.at(wordId).insert(std::make_pair(sFrom.
id(),
FeatureBA(ptFrom, depth, descriptorFrom, cameraIndex)));
721 frameToWordMap.insert(std::make_pair(sFrom.
id(), std::map<cv::KeyPoint, int, KeyPointCompare>()));
722 frameToWordMap.at(sFrom.
id()).insert(std::make_pair(ptFrom, wordId));
727 cv::Mat descriptorTo;
738 cameraIndex = int(ptTo.pt.x / subImageWidth);
739 ptTo.pt.x = ptTo.pt.x - (subImageWidth*float(cameraIndex));
746 const cv::Point3f & pt = sTo.
getWords3()[indexTo];
758 wordReferences.at(wordId).insert(std::make_pair(sTo.
id(),
FeatureBA(ptTo, depth, descriptorTo, cameraIndex)));
759 frameToWordMap.insert(std::make_pair(sTo.
id(), std::map<cv::KeyPoint, int, KeyPointCompare>()));
760 frameToWordMap.at(sTo.
id()).insert(std::make_pair(ptTo, wordId));
764 ++edgeWithWordsAdded;
768 UWARN(
"Not enough inliers (%d) between %d and %d", info.
inliersIDs.size(), sFrom.
id(), sTo.
id());
774 UDEBUG(
"Added %d words (edges with words=%d/%d)", wordCount, edgeWithWordsAdded, links.size());
777 UERROR(
"No links found for BA?!");
779 else if(wordCount == 0)
781 UERROR(
"No words added for BA?!");
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
Transform computeTransformationMod(Signature &from, Signature &to, Transform guess=Transform::getIdentity(), RegistrationInfo *info=0) const
const cv::Size & imageSize() 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())
std::multimap< int, Link >::iterator RTABMAP_EXP findLink(std::multimap< int, Link > &links, int from, int to, bool checkBothWays=true, Link::Type type=Link::kUndef)
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
std::pair< std::string, std::string > ParametersPair
const cv::Mat & getWordsDescriptors() const
const std::vector< StereoCameraModel > & stereoCameraModels() const
std::map< std::string, std::string > ParametersMap
const std::vector< cv::Point3f > & getWords3() const
Basic mathematics functions.
std::vector< int > inliersIDs
Some conversion functions.
virtual std::map< int, Transform > optimizeBA(int rootId, const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const std::map< int, std::vector< CameraModel > > &models, std::map< int, cv::Point3f > &points3DMap, const std::map< int, std::map< int, FeatureBA > > &wordReferences, std::set< int > *outliers=0)
static bool isAvailable(Optimizer::Type type)
float gravitySigma() 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)
const std::vector< CameraModel > & cameraModels() const
virtual void parseParameters(const ParametersMap ¶meters)
bool landmarksIgnored() 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 Transform & localTransform() const
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, bool adjustPosesWithConstraints=true) const
bool uContains(const std::list< V > &list, const V &value)
virtual Type type() const =0
SensorData & sensorData()
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)
const Transform & transform() const
bool priorsIgnored() const
static Optimizer * create(const ParametersMap ¶meters)
const std::multimap< int, int > & getWords() const