29 #include "rtabmap/core/Version.h"
63 #include <mrpt/poses/CPose3DPDFGaussian.h>
66 #include <pcl/search/kdtree.h>
67 #include <pcl/filters/crop_box.h>
68 #include <pcl/io/pcd_io.h>
69 #include <pcl/common/common.h>
70 #include <pcl/TextureMesh.h>
75 #define LOG_F "LogF.txt"
76 #define LOG_I "LogI.txt"
78 #define GRAPH_FILE_NAME "Graph.dot"
95 _publishStats(
Parameters::defaultRtabmapPublishStats()),
96 _publishLastSignatureData(
Parameters::defaultRtabmapPublishLastSignature()),
97 _publishPdf(
Parameters::defaultRtabmapPublishPdf()),
98 _publishLikelihood(
Parameters::defaultRtabmapPublishLikelihood()),
99 _publishRAMUsage(
Parameters::defaultRtabmapPublishRAMUsage()),
100 _computeRMSE(
Parameters::defaultRtabmapComputeRMSE()),
101 _saveWMState(
Parameters::defaultRtabmapSaveWMState()),
102 _maxTimeAllowed(
Parameters::defaultRtabmapTimeThr()),
103 _maxMemoryAllowed(
Parameters::defaultRtabmapMemoryThr()),
104 _loopThr(
Parameters::defaultRtabmapLoopThr()),
105 _loopRatio(
Parameters::defaultRtabmapLoopRatio()),
106 _aggressiveLoopThr(
Parameters::defaultRGBDAggressiveLoopThr()),
107 _virtualPlaceLikelihoodRatio(
Parameters::defaultRtabmapVirtualPlaceLikelihoodRatio()),
108 _maxLoopClosureDistance(
Parameters::defaultRGBDMaxLoopClosureDistance()),
109 _verifyLoopClosureHypothesis(
Parameters::defaultVhEpEnabled()),
110 _maxRetrieved(
Parameters::defaultRtabmapMaxRetrieved()),
111 _maxLocalRetrieved(
Parameters::defaultRGBDMaxLocalRetrieved()),
112 _maxRepublished(
Parameters::defaultRtabmapMaxRepublished()),
113 _rawDataKept(
Parameters::defaultMemImageKept()),
114 _statisticLogsBufferedInRAM(
Parameters::defaultRtabmapStatisticLogsBufferedInRAM()),
115 _statisticLogged(
Parameters::defaultRtabmapStatisticLogged()),
116 _statisticLoggedHeaders(
Parameters::defaultRtabmapStatisticLoggedHeaders()),
117 _rgbdSlamMode(
Parameters::defaultRGBDEnabled()),
118 _rgbdLinearUpdate(
Parameters::defaultRGBDLinearUpdate()),
119 _rgbdAngularUpdate(
Parameters::defaultRGBDAngularUpdate()),
120 _rgbdLinearSpeedUpdate(
Parameters::defaultRGBDLinearSpeedUpdate()),
121 _rgbdAngularSpeedUpdate(
Parameters::defaultRGBDAngularSpeedUpdate()),
122 _newMapOdomChangeDistance(
Parameters::defaultRGBDNewMapOdomChangeDistance()),
123 _neighborLinkRefining(
Parameters::defaultRGBDNeighborLinkRefining()),
124 _proximityByTime(
Parameters::defaultRGBDProximityByTime()),
125 _proximityBySpace(
Parameters::defaultRGBDProximityBySpace()),
126 _scanMatchingIdsSavedInLinks(
Parameters::defaultRGBDScanMatchingIdsSavedInLinks()),
127 _loopClosureIdentityGuess(
Parameters::defaultRGBDLoopClosureIdentityGuess()),
128 _localRadius(
Parameters::defaultRGBDLocalRadius()),
129 _localImmunizationRatio(
Parameters::defaultRGBDLocalImmunizationRatio()),
130 _proximityMaxGraphDepth(
Parameters::defaultRGBDProximityMaxGraphDepth()),
131 _proximityMaxPaths(
Parameters::defaultRGBDProximityMaxPaths()),
132 _proximityMaxNeighbors(
Parameters::defaultRGBDProximityPathMaxNeighbors()),
133 _proximityFilteringRadius(
Parameters::defaultRGBDProximityPathFilteringRadius()),
134 _proximityRawPosesUsed(
Parameters::defaultRGBDProximityPathRawPosesUsed()),
136 _proximityOdomGuess(
Parameters::defaultRGBDProximityOdomGuess()),
137 _proximityMergedScanCovFactor(
Parameters::defaultRGBDProximityMergedScanCovFactor()),
139 _optimizeFromGraphEnd(
Parameters::defaultRGBDOptimizeFromGraphEnd()),
140 _optimizationMaxError(
Parameters::defaultRGBDOptimizeMaxError()),
141 _startNewMapOnLoopClosure(
Parameters::defaultRtabmapStartNewMapOnLoopClosure()),
142 _startNewMapOnGoodSignature(
Parameters::defaultRtabmapStartNewMapOnGoodSignature()),
143 _goalReachedRadius(
Parameters::defaultRGBDGoalReachedRadius()),
144 _goalsSavedInUserData(
Parameters::defaultRGBDGoalsSavedInUserData()),
145 _pathStuckIterations(
Parameters::defaultRGBDPlanStuckIterations()),
146 _pathLinearVelocity(
Parameters::defaultRGBDPlanLinearVelocity()),
147 _pathAngularVelocity(
Parameters::defaultRGBDPlanAngularVelocity()),
148 _forceOdom3doF(
Parameters::defaultRGBDForceOdom3DoF()),
149 _restartAtOrigin(
Parameters::defaultRGBDStartAtOrigin()),
150 _loopCovLimited(
Parameters::defaultRGBDLoopCovLimited()),
151 _loopGPS(
Parameters::defaultRtabmapLoopGPS()),
152 _maxOdomCacheSize(
Parameters::defaultRGBDMaxOdomCacheSize()),
153 _localizationSmoothing(
Parameters::defaultRGBDLocalizationSmoothing()),
154 _localizationPriorInf(1.0/(
Parameters::defaultRGBDLocalizationPriorError()*
Parameters::defaultRGBDLocalizationPriorError())),
155 _createGlobalScanMap(
Parameters::defaultRGBDProximityGlobalScanMap()),
156 _markerPriorsLinearVariance(
Parameters::defaultMarkerPriorsVarianceLinear()),
157 _markerPriorsAngularVariance(
Parameters::defaultMarkerPriorsVarianceAngular()),
158 _loopClosureHypothesis(0,0.0
f),
159 _highestHypothesis(0,0.0
f),
160 _lastProcessTime(0.0),
161 _someNodesHaveBeenTransferred(
false),
162 _distanceTravelled(0.0
f),
163 _distanceTravelledSinceLastLocalization(0.0
f),
164 _optimizeFromGraphEndChanged(
false),
165 _epipolarGeometry(0),
172 _mapCorrection(
Transform::getIdentity()),
173 _lastLocalizationNodeId(0),
174 _currentSessionHasGPS(
false),
176 _pathCurrentIndex(0),
178 _pathTransformToGoal(
Transform::getIdentity()),
180 _pathStuckDistance(0.0
f)
181 #ifdef RTABMAP_PYTHON
209 std::string attributes =
"a+";
232 fprintf(
_foutFloat,
" 1-Total iteration time (s)\n");
233 fprintf(
_foutFloat,
" 2-Memory update time (s)\n");
234 fprintf(
_foutFloat,
" 3-Retrieval time (s)\n");
235 fprintf(
_foutFloat,
" 4-Likelihood time (s)\n");
236 fprintf(
_foutFloat,
" 5-Posterior time (s)\n");
237 fprintf(
_foutFloat,
" 6-Hypothesis selection time (s)\n");
238 fprintf(
_foutFloat,
" 7-Hypothesis validation time (s)\n");
239 fprintf(
_foutFloat,
" 8-Transfer time (s)\n");
240 fprintf(
_foutFloat,
" 9-Statistics creation time (s)\n");
241 fprintf(
_foutFloat,
" 10-Loop closure hypothesis value\n");
247 fprintf(
_foutFloat,
" 16-Virtual place hypothesis\n");
248 fprintf(
_foutFloat,
" 17-Join trash time (s)\n");
249 fprintf(
_foutFloat,
" 18-Weight Update (rehearsal) similarity\n");
250 fprintf(
_foutFloat,
" 19-Empty trash time (s)\n");
251 fprintf(
_foutFloat,
" 20-Retrieval database access time (s)\n");
252 fprintf(
_foutFloat,
" 21-Add loop closure link time (s)\n");
253 fprintf(
_foutFloat,
" 22-Memory cleanup time (s)\n");
254 fprintf(
_foutFloat,
" 23-Scan matching (odometry correction) time (s)\n");
255 fprintf(
_foutFloat,
" 24-Local time loop closure detection time (s)\n");
256 fprintf(
_foutFloat,
" 25-Local space loop closure detection time (s)\n");
257 fprintf(
_foutFloat,
" 26-Map optimization (s)\n");
261 fprintf(
_foutInt,
"Column headers:\n");
262 fprintf(
_foutInt,
" 1-Loop closure ID\n");
263 fprintf(
_foutInt,
" 2-Highest loop closure hypothesis\n");
264 fprintf(
_foutInt,
" 3-Locations transferred\n");
266 fprintf(
_foutInt,
" 5-Words extracted from the last image\n");
267 fprintf(
_foutInt,
" 6-Vocabulary size\n");
268 fprintf(
_foutInt,
" 7-Working memory size\n");
269 fprintf(
_foutInt,
" 8-Is loop closure hypothesis rejected?\n");
272 fprintf(
_foutInt,
" 11-Locations retrieved\n");
273 fprintf(
_foutInt,
" 12-Retrieval location ID\n");
274 fprintf(
_foutInt,
" 13-Unique words extraced from last image\n");
275 fprintf(
_foutInt,
" 14-Retrieval ID\n");
276 fprintf(
_foutInt,
" 15-Non-null likelihood values\n");
277 fprintf(
_foutInt,
" 16-Weight Update ID\n");
278 fprintf(
_foutInt,
" 17-Is last location merged through Weight Update?\n");
279 fprintf(
_foutInt,
" 18-Local graph size\n");
280 fprintf(
_foutInt,
" 19-Sensor data id\n");
281 fprintf(
_foutInt,
" 20-Indexed words\n");
282 fprintf(
_foutInt,
" 21-Index memory usage (KB)\n");
292 UWARN(
"Working directory is not set, log disabled!");
322 UDEBUG(
"path=%s", databasePath.c_str());
331 UWARN(
"Using empty database. Mapping session will not be saved unless it is closed with an output database path.");
344 allParameters.erase(Parameters::kRtabmapWorkingDirectory());
349 uInsert(allParameters, parameters);
350 ParametersMap::const_iterator
iter;
351 if((
iter=allParameters.find(Parameters::kRtabmapWorkingDirectory())) != allParameters.end())
391 UWARN(
"last localization pose is ignored (%s=true), assuming we start at the origin of the map.", Parameters::kRGBDStartAtOrigin().
c_str());
396 UINFO(
"Loaded optimizedPoses=%d firstPose %d=%s lastLocalizationPose=%s",
404 std::map<int, Transform> tmp;
411 std::map<int, float> likelihood;
417 likelihood.insert(std::make_pair(
iter->first, 0));
428 UINFO(
"Loaded optimizedPoses=0, last localization pose is ignored!");
436 std::map<int, Transform> tmp;
449 void Rtabmap::init(
const std::string & configFile,
const std::string & databasePath,
bool loadDatabaseParameters)
454 if(!configFile.empty())
456 ULOGGER_DEBUG(
"Read parameters from = %s", configFile.c_str());
460 this->
init(param, databasePath, loadDatabaseParameters);
465 UINFO(
"databaseSaved=%d", databaseSaved?1:0);
514 std::map<int, int> reducedIds;
516 for(std::map<int, int>::iterator
iter=reducedIds.begin();
iter!=reducedIds.end(); ++
iter)
555 ParametersMap::const_iterator
iter;
556 if((
iter=parameters.find(Parameters::kRtabmapWorkingDirectory())) != parameters.end())
631 double localizationPriorError = Parameters::defaultRGBDLocalizationPriorError();
632 Parameters::parse(parameters, Parameters::kRGBDLocalizationPriorError(), localizationPriorError);
633 UASSERT(localizationPriorError>0.0);
641 std::string markerPriorsStr;
645 std::list<std::string> strList =
uSplit(markerPriorsStr,
'|');
646 for(std::list<std::string>::iterator
iter=strList.begin();
iter!=strList.end(); ++
iter)
648 std::string markerStr = *
iter;
649 while(!markerStr.empty() && !
uIsDigit(markerStr[0]))
651 markerStr.erase(markerStr.begin());
653 if(!markerStr.empty())
658 if(!
prior.isNull() &&
id>0)
661 UDEBUG(
"Added landmark prior %d: %s",
id,
prior.prettyPrint().c_str());
665 UERROR(
"Failed to parse element \"%s\" in parameter %s", markerStr.c_str(), Parameters::kMarkerPriors().c_str());
668 else if(!
iter->empty())
670 UERROR(
"Failed to parse parameter %s, value=\"%s\"", Parameters::kMarkerPriors().
c_str(),
iter->c_str());
686 if((
iter=parameters.find(Parameters::kOptimizerStrategy())) != parameters.end())
692 UDEBUG(
"new detector strategy %d",
int(optimizerType));
707 optimizerType = (
Optimizer::Type)Parameters::defaultOptimizerStrategy();
720 if(
Parameters::parse(parameters, Parameters::kMemIncrementalMemory(), isMemIncremental) &&
727 std::map<int, int> reducedIds;
729 for(std::map<int, int>::iterator
iter=reducedIds.begin();
iter!=reducedIds.end(); ++
iter)
752 UWARN(
"Map is now incremental, clearing global scan map...");
821 std::map<int, int> weights;
836 return std::set<int>();
876 return Parameters::defaultMemGenerateIds();
912 UWARN(
"Initial pose can only be set in localization mode (%s=false), ignoring it...", Parameters::kMemIncrementalMemory().
c_str());
938 std::map<int, int> reducedIds;
940 UINFO(
"New map triggered, new map = %d", mapId);
950 if(reducedIds.size() &&
_path.size())
952 for(
unsigned int i=0;
i<
_path.size(); ++
i)
954 std::map<int, int>::const_iterator
iter = reducedIds.find(
_path[
i].
first);
955 if(
iter!= reducedIds.end())
981 if(!nearestNodes.empty())
987 UERROR(
"No nodes found inside %s=%fm of the current pose (%s). Cannot set label \"%s\"",
988 Parameters::kRGBDLocalRadius().
c_str(),
996 UERROR(
"Last signature is null! Cannot set label \"%s\"", label.c_str());
1016 UERROR(
"Last signature is null! Cannot set user data!");
1034 ids.insert(std::pair<int,int>(
id, 0));
1035 std::set<int> idsSet;
1036 for(std::map<int, int>::iterator
iter = ids.begin();
iter!=ids.end(); ++
iter)
1038 idsSet.insert(idsSet.end(),
iter->first);
1044 UERROR(
"No neighbors found for signature %d.",
id);
1058 std::map<int, Transform> poses;
1059 std::multimap<int, Link> constraints;
1072 std::map<int, double> stamps;
1075 for(std::map<int, Transform>::iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
1081 std::vector<float>
v;
1084 _memory->
getNodeInfo(
iter->first, o,
m,
w, l, stamp,
g,
v, gps, sensors,
true);
1085 stamps.insert(std::make_pair(
iter->first, stamp));
1132 UERROR(
"RTAB-Map is not initialized. No memory to reset...");
1179 const cv::Mat & image,
1181 const std::map<std::string, float> & externalStats)
1188 float odomLinearVariance,
1189 float odomAngularVariance,
1190 const std::vector<float> & odomVelocity,
1191 const std::map<std::string, float> & externalStats)
1198 cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1);
1199 covariance.at<
double>(0,0) = odomLinearVariance;
1200 covariance.at<
double>(1,1) = odomLinearVariance;
1201 covariance.at<
double>(2,2) = odomLinearVariance;
1202 covariance.at<
double>(3,3) = odomAngularVariance;
1203 covariance.at<
double>(4,4) = odomAngularVariance;
1204 covariance.at<
double>(5,5) = odomAngularVariance;
1205 return process(
data, odomPose, covariance, odomVelocity, externalStats);
1210 const cv::Mat & odomCovariance,
1211 const std::vector<float> & odomVelocity,
1212 const std::map<std::string, float> & externalStats)
1221 double timeMemoryUpdate = 0;
1222 double timeNeighborLinkRefining = 0;
1223 double timeProximityByTimeDetection = 0;
1224 double timeProximityBySpaceSearch = 0;
1225 double timeProximityBySpaceVisualDetection = 0;
1226 double timeProximityBySpaceDetection = 0;
1227 double timeCleaningNeighbors = 0;
1228 double timeReactivations = 0;
1229 double timeAddLoopClosureLink = 0;
1230 double timeMapOptimization = 0;
1231 double timeRetrievalDbAccess = 0;
1232 double timeLikelihoodCalculation = 0;
1233 double timePosteriorCalculation = 0;
1234 double timeHypothesesCreation = 0;
1235 double timeHypothesesValidation = 0;
1236 double timeRealTimeLimitReachedProcess = 0;
1237 double timeMemoryCleanup = 0;
1238 double timeEmptyingTrash = 0;
1239 double timeFinalizingStatistics = 0;
1240 double timeJoiningTrash = 0;
1241 double timeStatsCreation = 0;
1243 float hypothesisRatio = 0.0f;
1244 bool rejectedGlobalLoopClosure =
false;
1246 std::map<int, float> rawLikelihood;
1247 std::map<int, float> adjustedLikelihood;
1248 std::map<int, float> likelihood;
1249 std::map<int, int> weights;
1250 std::map<int, float> posterior;
1251 std::list<std::pair<int, float> > reactivateHypotheses;
1253 std::map<int, int> childCount;
1254 std::set<int> signaturesRetrieved;
1255 int proximityDetectionsInTimeFound = 0;
1264 std::set<int> immunizedLocations;
1267 for(std::map<std::string, float>::const_iterator
iter=externalStats.begin();
iter!=externalStats.end(); ++
iter)
1287 bool fakeOdom =
false;
1295 odomPose = odomPose.
to3DoF();
1301 UWARN(
"Input odometry is not invertible! pose = %s\n"
1306 "Trying to normalize rotation to see if it makes it invertible...",
1308 odomPose.
r11(), odomPose.
r12(), odomPose.
r13(), odomPose.
o14(),
1309 odomPose.
r21(), odomPose.
r22(), odomPose.
r23(), odomPose.
o24(),
1310 odomPose.
r31(), odomPose.
r32(), odomPose.
r33(), odomPose.
o34());
1317 odomPose.
r11(), odomPose.
r12(), odomPose.
r13(), odomPose.
o14(),
1318 odomPose.
r21(), odomPose.
r22(), odomPose.
r23(), odomPose.
o24(),
1319 odomPose.
r31(), odomPose.
r32(), odomPose.
r33(), odomPose.
o34()).c_str());
1320 UWARN(
"Normalizing rotation succeeded! fixed pose = %s\n"
1325 "If the resulting rotation is very different from original one, try to fix the odometry or TF.",
1327 odomPose.
r11(), odomPose.
r12(), odomPose.
r13(), odomPose.
o14(),
1328 odomPose.
r21(), odomPose.
r22(), odomPose.
r23(), odomPose.
o24(),
1329 odomPose.
r31(), odomPose.
r32(), odomPose.
r33(), odomPose.
o34());
1333 UDEBUG(
"incremental=%d odomPose=%s optimizedPoses=%d mapCorrection=%s lastLocalizationPose=%s lastLocalizationNodeId=%d",
1366 UWARN(
"Update map correction based on last localization saved in database! correction = %s, nearest id = %d of last pose = %s, odom = %s",
1390 iter->second = mapCorrectionInv *
iter->second;
1395 UWARN(
"Transformed map accordingly to last localization pose saved in database (%s=true)! nearest id = %d of last pose = %s",
1396 Parameters::kRGBDOptimizeFromGraphEnd().
c_str(),
1406 UERROR(
"RGB-D SLAM mode is enabled, memory is incremental but no odometry is provided. "
1407 "Image %d is ignored!",
data.id());
1439 UWARN(
"Odometry is reset (identity pose detected). Increment map id to %d!", mapId);
1450 UWARN(
"Odometry is reset (large odometry change detected > %f). A new map (%d) is created! Last pose = %s, new pose = %s",
1484 UFATAL(
"Not supposed to be here...last signature is null?!?");
1488 timeMemoryUpdate =
timer.ticks();
1489 ULOGGER_INFO(
"timeMemoryUpdate=%fs", timeMemoryUpdate);
1494 bool smallDisplacement =
false;
1495 bool tooFastMovement =
false;
1496 std::list<int> signaturesRemoved;
1497 bool neighborLinkRefined =
false;
1498 bool addedNewLandmark =
false;
1499 float distanceToClosestNodeInTheGraph = 0;
1500 float angleToClosestNodeInTheGraph = 0;
1503 double linVar = odomCovariance.empty()?1.0f:
uMax3(odomCovariance.at<
double>(0,0), odomCovariance.at<
double>(1,1)>=9999?0:odomCovariance.at<
double>(1,1), odomCovariance.at<
double>(2,2)>=9999?0:odomCovariance.at<
double>(2,2));
1504 double angVar = odomCovariance.empty()?1.0f:
uMax3(odomCovariance.at<
double>(3,3)>=9999?0:odomCovariance.at<
double>(3,3), odomCovariance.at<
double>(4,4)>=9999?0:odomCovariance.at<
double>(4,4), odomCovariance.at<
double>(5,5));
1525 const std::multimap<int, Link> & links = signature->
getLinks();
1531 if(signature->
getWeight() < 0 ||
s->getWeight() >= 0)
1533 t = links.begin()->second.transform();
1556 smallDisplacement =
true;
1561 if(odomVelocity.size() == 6)
1573 bool intermediateNodeRefining =
false;
1581 int oldId = signature->
getLinks().begin()->first;
1589 if(smallDisplacement)
1591 if(signature->
getLinks().begin()->second.transVariance() == 1)
1594 UDEBUG(
"Set small variance. The robot is not moving.");
1608 UINFO(
"Odometry refining: update neighbor link (%d->%d, variance:lin=%f, ang=%f) from %s to %s",
1611 info.covariance.at<
double>(0,0),
1612 info.covariance.at<
double>(5,5),
1614 t.prettyPrint().c_str());
1615 UASSERT(
info.covariance.at<
double>(0,0) > 0.0 &&
info.covariance.at<
double>(5,5) > 0.0);
1624 std::map<int, Transform>::iterator jter =
_optimizedPoses.find(oldId);
1630 iter->second = mapCorrectionInv * up *
iter->second;
1636 UINFO(
"Odometry refining rejected: %s",
info.rejectedMsg.c_str());
1637 if(!
info.covariance.empty() &&
info.covariance.at<
double>(0,0) > 0.0 &&
info.covariance.at<
double>(0,0) != 1.0 &&
info.covariance.at<
double>(5,5) > 0.0 &&
info.covariance.at<
double>(5,5) != 1.0)
1641 std::cout <<
info.covariance << std::endl;
1646 neighborLinkRefined = !
t.isNull();
1655 timeNeighborLinkRefining =
timer.ticks();
1656 ULOGGER_INFO(
"timeOdometryRefining=%fs", timeNeighborLinkRefining);
1667 UERROR(
"Map correction should be identity when optimizing from the last node. T=%s NewPose=%s OldPose=%s",
1676 intermediateNodeRefining =
true;
1687 int closestNode = 0;
1688 float sqrdDistance = 0.0f;
1698 if(closestNode>0 && sqrdDistance>0.0
f)
1700 distanceToClosestNodeInTheGraph =
sqrt(sqrdDistance);
1701 UDEBUG(
"Last localization pose = %s, closest node=%d (%f m)", newPose.
prettyPrint().c_str(), closestNode, distanceToClosestNodeInTheGraph);
1716 UDEBUG(
"Added landmark %d : %s",
iter->first, (newPose*
iter->second.transform()).prettyPrint().c_str());
1717 addedNewLandmark =
true;
1731 "Only forward links should be added.");
1733 Link tmp = signature->
getLinks().begin()->second.inverse();
1735 if(!smallDisplacement)
1746 if(
s->getWeight() == -1)
1758 !smallDisplacement &&
1759 odomCovariance.cols == 6 &&
1760 odomCovariance.rows == 6 &&
1761 odomCovariance.type() == CV_64FC1 &&
1762 odomCovariance.at<
double>(0,0) < 1)
1775 mrpt::math::CMatrixDouble66 gaussian;
1776 gaussian.loadFromRawPointer((
const double*)odomCovariance.data);
1777 mrpt::poses::CPose3DPDFGaussian gaussianTransformed(mrpt::poses::CPose3D(), gaussian);
1778 gaussianTransformed.changeCoordinatesReference(pose);
1795 if(!smallDisplacement)
1811 odomCovariance.inv());
1827 for(
unsigned int i=0;
i<
_path.size(); ++
i)
1846 if(jter->second.from() ==
iter->first || jter->second.to() ==
iter->first)
1868 for(std::set<int>::const_reverse_iterator
iter = stm.rbegin();
iter!=stm.rend(); ++
iter)
1870 if(*
iter != signature->
id() &&
1875 std::string rejectedMsg;
1876 UDEBUG(
"Check local transform between %d and %d", signature->
id(), *
iter);
1890 UDEBUG(
"Add local loop closure in TIME (%d->%d) %s",
1895 UASSERT(
info.covariance.at<
double>(0,0) > 0.0 &&
info.covariance.at<
double>(5,5) > 0.0);
1898 ++proximityDetectionsInTimeFound;
1899 UINFO(
"Local loop closure found between %d and %d with t=%s",
1904 UWARN(
"Cannot add local loop closure between %d and %d ?!?",
1910 UINFO(
"Local loop closure (time) between %d and %d rejected: %s",
1911 *
iter, signature->
id(), rejectedMsg.c_str());
1924 timeProximityByTimeDetection =
timer.ticks();
1925 UINFO(
"timeProximityByTimeDetection=%fs", timeProximityByTimeDetection);
1930 bool localizationOnPreviousUpdate =
false;
1933 localizationOnPreviousUpdate =
1935 signature->
getLinks().begin()->first!=signature->
id() &&
1943 int localizationLinks = 0;
1944 int previousIdWithLocalizationLink = 0;
1948 if(previousIdWithLocalizationLink ==
iter->first)
1960 ++localizationLinks;
1961 previousIdWithLocalizationLink =
iter->first;
1965 localizationOnPreviousUpdate = localizationLinks > 1;
1969 if(!signature->
isBadSignature() && signature->
getWeight()>=0 && (!smallDisplacement || !localizationOnPreviousUpdate) && !tooFastMovement)
1983 std::list<int> signaturesToCompare;
1996 for(std::map<int, float>::reverse_iterator
iter=nearestIds.rbegin();
iter!=nearestIds.rend() &&
iter->first>0; ++
iter)
2000 if(
s->sensorData().gps().stamp() > 0.0)
2002 originGPS =
s->sensorData().gps();
2014 if(originGPS.
stamp() > 0.0)
2029 if(
s->getWeight() != -1)
2032 if(originGPS.
stamp()>0.0)
2037 GPS gps =
s->sensorData().gps();
2039 if(gps.
stamp()==0.0)
2043 if(gps.
stamp() > 0.0)
2046 std::make_pair(
s->id(),
2058 const Transform & offsetENU = cacheIter->second.second;
2059 relativePose.
x += offsetENU.
x() - originOffsetENU.
x();
2060 relativePose.y += offsetENU.
y() - originOffsetENU.
y();
2061 relativePose.z += offsetENU.
z() - originOffsetENU.
z();
2063 if(relativePose.z>
error)
2065 relativePose.z -=
error;
2067 else if(relativePose.z < -
error)
2069 relativePose.z +=
error;
2081 signaturesToCompare.push_back(
iter->first);
2088 signaturesToCompare.push_back(
iter->first);
2095 likelihood = rawLikelihood;
2098 timeLikelihoodCalculation =
timer.ticks();
2099 ULOGGER_INFO(
"timeLikelihoodCalculation=%fs",timeLikelihoodCalculation);
2109 timePosteriorCalculation =
timer.ticks();
2110 ULOGGER_INFO(
"timePosteriorCalculation=%fs",timePosteriorCalculation);
2122 if(posterior.size())
2124 for(std::map<int, float>::const_reverse_iterator
iter = posterior.rbegin();
iter != posterior.rend(); ++
iter)
2134 timeHypothesesCreation =
timer.ticks();
2140 bool hasLoopClosureConstraints =
false;
2143 hasLoopClosureConstraints =
2162 rejectedGlobalLoopClosure =
true;
2163 if(posterior.size() <= 2 && loopThr>0.0f)
2166 UDEBUG(
"rejected hypothesis: single hypothesis");
2170 UWARN(
"rejected hypothesis: by epipolar geometry");
2174 UWARN(
"rejected hypothesis: not satisfying hypothesis ratio (%f < %f * %f)",
2177 else if(
_loopRatio > 0.0
f && lastHighestHypothesis.second == 0)
2179 UWARN(
"rejected hypothesis: last closure hypothesis is null (loop ratio is on)");
2184 rejectedGlobalLoopClosure =
false;
2187 timeHypothesesValidation =
timer.ticks();
2188 ULOGGER_INFO(
"timeHypothesesValidation=%fs",timeHypothesesValidation);
2195 rejectedGlobalLoopClosure =
true;
2204 else if(!signature->
isBadSignature() && (smallDisplacement || tooFastMovement))
2207 UDEBUG(
"smallDisplacement=%d tooFastMovement=%d", smallDisplacement?1:0, tooFastMovement?1:0);
2211 UDEBUG(
"Ignoring likelihood and loop closure hypotheses as current signature doesn't have enough visual features.");
2219 timeJoiningTrash =
timer.ticks();
2220 ULOGGER_INFO(
"Time emptying memory trash = %fs, joining (actual overhead) = %fs", timeEmptyingTrash, timeJoiningTrash);
2226 std::list<int> reactivatedIds;
2227 double timeGetNeighborsTimeDb = 0.0;
2228 double timeGetNeighborsSpaceDb = 0.0;
2229 int immunizedGlobally = 0;
2230 int immunizedLocally = 0;
2231 int maxLocalLocationsImmunized = 0;
2244 ULOGGER_INFO(
"Retrieving locations... around id=%d", retrievalId);
2246 UASSERT(neighborhoodSize >= 0);
2250 unsigned int nbLoadedFromDb = 0;
2251 std::set<int> reactivatedIdsSet;
2252 std::map<int, int> neighbors;
2253 int nbDirectNeighborsInDb = 0;
2266 &timeGetNeighborsTimeDb);
2267 ULOGGER_DEBUG(
"neighbors of %d in time = %d", retrievalId, (
int)neighbors.size());
2269 bool firstPassDone =
false;
2271 while(
m < neighborhoodSize)
2273 std::set<int> idsSorted;
2274 for(std::map<int, int>::iterator
iter=neighbors.begin();
iter!=neighbors.end();)
2278 neighbors.erase(
iter++);
2280 else if(
iter->second ==
m)
2282 if(reactivatedIdsSet.find(
iter->first) == reactivatedIdsSet.end())
2284 idsSorted.insert(
iter->first);
2285 reactivatedIdsSet.insert(
iter->first);
2289 ++nbDirectNeighborsInDb;
2293 if(immunizedLocations.insert(
iter->first).second)
2295 ++immunizedGlobally;
2300 neighbors.erase(
iter++);
2307 firstPassDone =
true;
2308 reactivatedIds.insert(reactivatedIds.end(), idsSorted.rbegin(), idsSorted.rend());
2322 &timeGetNeighborsSpaceDb);
2323 ULOGGER_DEBUG(
"neighbors of %d in space = %d", retrievalId, (
int)neighbors.size());
2324 firstPassDone =
false;
2326 while(
m < neighborhoodSize)
2328 std::set<int> idsSorted;
2329 for(std::map<int, int>::iterator
iter=neighbors.begin();
iter!=neighbors.end();)
2333 neighbors.erase(
iter++);
2335 else if(
iter->second ==
m)
2337 if(reactivatedIdsSet.find(
iter->first) == reactivatedIdsSet.end())
2339 idsSorted.insert(
iter->first);
2340 reactivatedIdsSet.insert(
iter->first);
2344 ++nbDirectNeighborsInDb;
2348 neighbors.erase(
iter++);
2355 firstPassDone =
true;
2356 reactivatedIds.insert(reactivatedIds.end(), idsSorted.rbegin(), idsSorted.rend());
2360 "reactivatedIds.size=%d, "
2361 "nbLoadedFromDb=%d, "
2362 "nbDirectNeighborsInDb=%d, "
2363 "time=%fs (%fs %fs)",
2365 reactivatedIds.size(),
2366 (
int)nbLoadedFromDb,
2367 nbDirectNeighborsInDb,
2369 timeGetNeighborsTimeDb,
2370 timeGetNeighborsSpaceDb);
2378 std::list<int> retrievalLocalIds;
2386 float distanceSoFar = 0.0f;
2400 if(immunizedLocations.insert(
_path[
i].first).second)
2408 UINFO(
"retrieval of node %d on path (dist=%fm)",
_path[
i].
first, distanceSoFar);
2415 UDEBUG(
"Stop on node %d (dist=%fm > %fm)",
2425 if(immunizedLocally < maxLocalLocationsImmunized &&
2428 std::map<int ,Transform> poses;
2434 poses.insert(*
iter);
2443 std::multimap<int, int> links;
2448 links.insert(std::make_pair(
iter->second.from(),
iter->second.to()));
2449 links.insert(std::make_pair(
iter->second.to(),
iter->second.from()));
2454 if(
path.size() == 0)
2456 UWARN(
"Could not compute a path between %d and %d", nearestId, signature->
id());
2466 if(immunizedLocally >= maxLocalLocationsImmunized)
2471 UWARN(
"Could not immunize the whole local path (%d) between "
2472 "%d and %d (max location immunized=%d). You may want "
2473 "to increase RGBD/LocalImmunizationRatio (current=%f (%d of WM=%d)) "
2474 "to be able to immunize longer paths.",
2478 maxLocalLocationsImmunized,
2480 maxLocalLocationsImmunized,
2487 if(immunizedLocations.insert(
iter->first).second)
2503 std::multimap<float, int> nearNodesByDist;
2504 for(std::map<int, float>::iterator
iter=nearNodes.lower_bound(1);
iter!=nearNodes.end(); ++
iter)
2506 nearNodesByDist.insert(std::make_pair(
iter->second,
iter->first));
2508 UINFO(
"near nodes=%d, max local immunized=%d, ratio=%f WM=%d",
2509 (
int)nearNodesByDist.size(),
2510 maxLocalLocationsImmunized,
2513 for(std::multimap<float, int>::iterator
iter=nearNodesByDist.begin();
2514 iter!=nearNodesByDist.end() && (retrievalLocalIds.size() <
_maxLocalRetrieved || immunizedLocally < maxLocalLocationsImmunized);
2522 const std::multimap<int, Link> & links =
s->getLinks();
2523 for(std::multimap<int, Link>::const_reverse_iterator jter=links.rbegin();
2529 UINFO(
"retrieval of node %d on local map", jter->first);
2530 retrievalLocalIds.push_back(jter->first);
2533 if(!
_memory->
isInSTM(
s->id()) && immunizedLocally < maxLocalLocationsImmunized)
2535 if(immunizedLocations.insert(
s->id()).second)
2546 std::set<int> retrievalLocalIdsSet(retrievalLocalIds.begin(), retrievalLocalIds.end());
2547 for(std::list<int>::iterator
iter=retrievalLocalIds.begin();
2552 for(std::map<int, int>::reverse_iterator jter=ids.rbegin();
2557 retrievalLocalIdsSet.find(jter->first) == retrievalLocalIdsSet.end())
2559 UINFO(
"retrieval of node %d on local map", jter->first);
2560 retrievalLocalIds.push_back(jter->first);
2561 retrievalLocalIdsSet.insert(jter->first);
2568 for(std::multimap<float, int>::reverse_iterator
iter=nearNodesByDist.rbegin();
iter!=nearNodesByDist.rend(); ++
iter)
2574 reactivatedIds.insert(reactivatedIds.begin(), retrievalLocalIds.begin(), retrievalLocalIds.end());
2581 if(reactivatedIds.size())
2588 timeRetrievalDbAccess);
2590 ULOGGER_INFO(
"retrieval of %d (db time = %fs)", (
int)signaturesRetrieved.size(), timeRetrievalDbAccess);
2592 timeRetrievalDbAccess += timeGetNeighborsTimeDb + timeGetNeighborsSpaceDb;
2593 UINFO(
"total timeRetrievalDbAccess=%fs", timeRetrievalDbAccess);
2596 immunizedLocations.insert(signaturesRetrieved.begin(), signaturesRetrieved.end());
2600 UWARN(
"Some signatures have been retrieved from memory management, clearing global scan map...");
2605 timeReactivations =
timer.ticks();
2606 ULOGGER_INFO(
"timeReactivations=%fs", timeReactivations);
2611 std::list<std::pair<int, int> > loopClosureLinksAdded;
2612 int loopClosureVisualInliers = 0;
2613 float loopClosureVisualInliersRatio = 0.0f;
2614 int loopClosureVisualMatches = 0;
2615 float loopClosureLinearVariance = 0.0f;
2616 float loopClosureAngularVariance = 0.0f;
2617 float loopClosureVisualInliersMeanDist = 0;
2618 float loopClosureVisualInliersDistribution = 0;
2620 int proximityDetectionsAddedVisually = 0;
2621 int proximityDetectionsAddedByICPMulti = 0;
2622 int proximityDetectionsAddedByICPGlobal = 0;
2623 int lastProximitySpaceClosureId = 0;
2624 int proximitySpacePaths = 0;
2625 int localVisualPathsChecked = 0;
2626 int localScanPathsChecked = 0;
2627 int loopIdSuppressedByProximity = 0;
2639 UINFO(
"Proximity detection by space disabled as if we force to have a global loop "
2640 "closure with previous map before doing proximity detections (%s=true).",
2641 Parameters::kRtabmapStartNewMapOnLoopClosure().
c_str());
2645 UWARN(
"Cannot do local loop closure detection in space if graph optimization is disabled!");
2654 if((!smallDisplacement || !localizationOnPreviousUpdate) && !tooFastMovement)
2664 UDEBUG(
"Proximity detection (local loop closure in SPACE using matching images, local radius=%fm)",
_localRadius);
2667 std::map<int, Transform> nearestPoses;
2668 std::multimap<int, int> links;
2676 links.insert(std::make_pair(
iter->second.from(),
iter->second.to()));
2677 links.insert(std::make_pair(
iter->second.to(),
iter->second.from()));
2681 for(std::map<int, float>::iterator
iter=nearestIds.lower_bound(1);
iter!=nearestIds.end(); ++
iter)
2700 UDEBUG(
"nearestPoses=%d", (
int)nearestPoses.size());
2704 UDEBUG(
"got %d paths", (
int)nearestPathsNotSorted.size());
2706 std::map<NearestPathKey, std::map<int, Transform> > nearestPaths;
2708 for(std::map<
int, std::map<int, Transform> >::const_iterator
iter=nearestPathsNotSorted.begin();
iter!=nearestPathsNotSorted.end(); ++
iter)
2710 const std::map<int, Transform> &
path =
iter->second;
2711 float highestLikelihood = 0.0f;
2712 int highestLikelihoodId =
iter->first;
2713 float smallestDistanceSqr = -1;
2714 for(std::map<int, Transform>::const_iterator jter=
path.begin(); jter!=
path.end(); ++jter)
2716 float v =
uValue(likelihood, jter->first, 0.0f);
2717 float distance = (currentPoseInv * jter->second).getNormSquared();
2718 if(
v > highestLikelihood || (
v == highestLikelihood && (smallestDistanceSqr < 0 ||
distance < smallestDistanceSqr)))
2720 highestLikelihood =
v;
2721 highestLikelihoodId = jter->first;
2725 nearestPaths.insert(std::make_pair(
NearestPathKey(highestLikelihood, highestLikelihoodId, smallestDistanceSqr),
path));
2729 timeProximityBySpaceSearch =
timer.ticks();
2730 ULOGGER_INFO(
"timeProximityBySpaceSearch=%fs", timeProximityBySpaceSearch);
2737 for(std::map<
NearestPathKey, std::map<int, Transform> >::const_reverse_iterator
iter=nearestPaths.rbegin();
2738 iter!=nearestPaths.rend() &&
2742 std::map<int, Transform>
path =
iter->second;
2750 if(
iter->first.likelihood > 0.0f &&
2753 nearestId =
iter->first.id;
2763 if(!signature->
hasLink(nearestId) &&
2764 (proximityFilteringRadius <= 0.0f ||
2767 ++localVisualPathsChecked;
2779 if(proximityFilteringRadius <= 0 ||
transform.getNormSquared() <= proximityFilteringRadius*proximityFilteringRadius)
2781 UINFO(
"[Visual] Add local loop closure in SPACE (%d->%d) %s",
2785 UASSERT(
info.covariance.at<
double>(0,0) > 0.0 &&
info.covariance.at<
double>(5,5) > 0.0);
2788 loopClosureVisualInliersMeanDist =
info.inliersMeanDistance;
2789 loopClosureVisualInliersDistribution =
info.inliersDistribution;
2791 ++proximityDetectionsAddedVisually;
2792 lastProximitySpaceClosureId = nearestId;
2794 loopClosureVisualInliers =
info.inliers;
2795 loopClosureVisualInliersRatio =
info.inliersRatio;
2796 loopClosureVisualMatches =
info.matches;
2799 loopClosureLinearVariance = 1.0/information.at<
double>(0,0);
2800 loopClosureAngularVariance = 1.0/information.at<
double>(5,5);
2808 UDEBUG(
"Proximity detection on %d is close to loop closure %d, ignoring loop closure transform estimation...",
2814 loopIdSuppressedByProximity = nearestId;
2816 else if(loopIdSuppressedByProximity == 0)
2818 loopIdSuppressedByProximity = nearestId;
2823 loopClosureLinksAdded.push_back(std::make_pair(signature->
id(), nearestId));
2827 UWARN(
"Ignoring local loop closure with %d because resulting "
2828 "transform is too large!? (%fm > %fm)",
2829 nearestId,
transform.getNorm(), proximityFilteringRadius);
2833 else if(!signature->
hasLink(nearestId) && proximityFilteringRadius>0.0f)
2835 UDEBUG(
"Skipping path %d as most likely ID %d is too far %f > %f (%s)",
2839 proximityFilteringRadius,
2840 Parameters::kRGBDProximityPathFilteringRadius().c_str());
2845 timeProximityBySpaceVisualDetection =
timer.ticks();
2846 ULOGGER_INFO(
"timeProximityBySpaceVisualDetection=%fs", timeProximityBySpaceVisualDetection);
2851 UDEBUG(
"Proximity detection (local loop closure in SPACE with scan matching)");
2858 proximitySpacePaths = (
int)nearestPaths.size();
2859 for(std::map<
NearestPathKey, std::map<int, Transform> >::const_reverse_iterator
iter=nearestPaths.rbegin();
2860 iter!=nearestPaths.rend() &&
2864 std::map<int, Transform>
path =
iter->second;
2874 if(!signature->
hasLink(nearestId))
2878 std::map<int, Transform> filteredPath;
2880 std::map<int, Transform>::iterator nearestIdIter =
path.find(nearestId);
2886 filteredPath.insert(*
iter);
2891 filteredPath.insert(*
iter);
2893 path = filteredPath;
2897 std::map<int, Transform> optimizedLocalPath;
2906 UERROR(
"Proximity path not containing nearest ID ?! Skipping this path.");
2911 for(std::map<int, Transform>::iterator jter=
path.lower_bound(1); jter!=
path.end(); ++jter)
2913 optimizedLocalPath.insert(std::make_pair(jter->first,
t * jter->second));
2918 optimizedLocalPath =
path;
2921 std::map<int, Transform> filteredPath;
2922 if(
_globalScanMap.
empty() && optimizedLocalPath.size() > 2 && proximityFilteringRadius > 0.0f)
2927 filteredPath.insert(*optimizedLocalPath.find(nearestId));
2931 filteredPath = optimizedLocalPath;
2934 if(filteredPath.size() > 0)
2937 filteredPath.insert(std::make_pair(signature->
id(),
_optimizedPoses.at(signature->
id())));
2941 ++localScanPathsChecked;
2944 bool icpMulti =
true;
2955 assembledData.
setId(nearestId);
2962 Transform guess = filteredPath.at(nearestId).
inverse() * filteredPath.at(signature->
id());
2972 UINFO(
"[Scan matching] Add local loop closure in SPACE (%d->%d) %s",
2977 cv::Mat scanMatchingIds;
2980 std::stringstream
stream;
2982 for(std::map<int, Transform>::iterator
iter=optimizedLocalPath.begin();
iter!=optimizedLocalPath.end(); ++
iter)
2984 if(
iter != optimizedLocalPath.begin())
2990 std::string scansStr =
stream.str();
2991 scanMatchingIds = cv::Mat(1,
int(scansStr.size()+1), CV_8SC1, (
void *)scansStr.c_str());
2996 UASSERT(
info.covariance.at<
double>(0,0) > 0.0 &&
info.covariance.at<
double>(5,5) > 0.0);
2998 loopClosureLinksAdded.push_back(std::make_pair(signature->
id(), nearestId));
3002 ++proximityDetectionsAddedByICPMulti;
3006 ++proximityDetectionsAddedByICPGlobal;
3010 if(proximityDetectionsAddedVisually == 0)
3012 lastProximitySpaceClosureId = nearestId;
3017 UINFO(
"Local scan matching rejected: %s",
info.rejectedMsg.c_str());
3035 timeProximityBySpaceDetection =
timer.ticks();
3036 ULOGGER_INFO(
"timeProximityBySpaceDetection=%fs", timeProximityBySpaceDetection);
3044 if(loopIdSuppressedByProximity==0)
3049 info.covariance = cv::Mat::eye(6,6,CV_64FC1);
3058 loopClosureVisualInliersMeanDist =
info.inliersMeanDistance;
3059 loopClosureVisualInliersDistribution =
info.inliersDistribution;
3061 loopClosureVisualInliers =
info.inliers;
3062 loopClosureVisualInliersRatio =
info.inliersRatio;
3063 loopClosureVisualMatches =
info.matches;
3064 rejectedGlobalLoopClosure =
transform.isNull();
3065 if(rejectedGlobalLoopClosure)
3067 UWARN(
"Rejected loop closure %d -> %d: %s",
3072 rejectedGlobalLoopClosure =
true;
3073 UWARN(
"Rejected localization %d -> %d because distance to map (%fm) is over %s=%fm.",
3081 if(!rejectedGlobalLoopClosure)
3084 UASSERT(
info.covariance.at<
double>(0,0) > 0.0 &&
info.covariance.at<
double>(5,5) > 0.0);
3086 loopClosureLinearVariance =
uMax3(
info.covariance.at<
double>(0,0),
info.covariance.at<
double>(1,1)>=9999?0:
info.covariance.at<
double>(1,1),
info.covariance.at<
double>(2,2)>=9999?0:
info.covariance.at<
double>(2,2));
3087 loopClosureAngularVariance =
uMax3(
info.covariance.at<
double>(3,3)>=9999?0:
info.covariance.at<
double>(3,3),
info.covariance.at<
double>(4,4)>=9999?0:
info.covariance.at<
double>(4,4),
info.covariance.at<
double>(5,5));
3090 if(!rejectedGlobalLoopClosure)
3096 if(rejectedGlobalLoopClosure)
3107 timeAddLoopClosureLink =
timer.ticks();
3108 ULOGGER_INFO(
"timeAddLoopClosureLink=%fs", timeAddLoopClosureLink);
3113 std::map<int, std::set<int> > landmarksDetected;
3117 UDEBUG(
"hasGlobalLoopClosuresInOdomCache=%d", hasGlobalLoopClosuresInOdomCache?1:0);
3124 !hasGlobalLoopClosuresInOdomCache &&
3129 UWARN(
"Ignoring landmark %d for localization as it is too far (%fm > %s=%f) "
3130 "and odom cache doesn't contain global loop closure(s).",
3132 iter->second.transform().getNorm(),
3133 Parameters::kRGBDLocalRadius().c_str(),
3140 rejectedGlobalLoopClosure =
false;
3141 loopClosureLinksAdded.push_back(std::make_pair(signature->
id(),
iter->first));
3166 UERROR(
"Virtual link larger than local radius (%fm > %fm). Aborting the plan!",
3176 float maxLinearError = 0.0f;
3177 float maxLinearErrorRatio = 0.0f;
3178 float maxAngularError = 0.0f;
3179 float maxAngularErrorRatio = 0.0f;
3180 double optimizationError = 0.0;
3181 int optimizationIterations = 0;
3183 bool rejectedLandmark =
false;
3184 bool delayedLocalization =
false;
3188 UDEBUG(
"Last prox: %d", lastProximitySpaceClosureId);
3193 UDEBUG(
"Prox Time: %d", proximityDetectionsInTimeFound);
3194 UDEBUG(
"Landmarks: %d", (
int)landmarksDetected.size());
3195 UDEBUG(
"Retrieved: %d", (
int)signaturesRetrieved.size());
3201 lastProximitySpaceClosureId>0 ||
3205 proximityDetectionsInTimeFound>0 ||
3206 !landmarksDetected.empty() ||
3207 signaturesRetrieved.size())
3212 !landmarksDetected.empty()))
3221 for(std::map<
int, std::set<int> >::
iterator iter=landmarksDetected.begin();
iter!=landmarksDetected.end(); ++
iter)
3226 localizationLinks.insert(std::make_pair(
iter->first, signature->
getLandmarks().at(
iter->first)));
3231 bool allLocalizationLinksInGraph = !localizationLinks.empty();
3232 for(std::multimap<int, Link>::iterator
iter=localizationLinks.begin();
iter!=localizationLinks.end(); ++
iter)
3236 allLocalizationLinksInGraph =
false;
3246 signaturesRetrieved.empty() &&
3247 !localizationLinks.empty() &&
3248 allLocalizationLinksInGraph)
3265 constraints.insert(selfLinks.begin(), selfLinks.end());
3266 for(std::multimap<int, Link>::iterator
iter=localizationLinks.begin();
iter!=localizationLinks.end(); ++
iter)
3268 constraints.insert(std::make_pair(
iter->second.from(),
iter->second));
3271 for(std::multimap<int, Link>::iterator
iter=constraints.begin();
iter!=constraints.end(); ++
iter)
3274 if(iterPose !=
_optimizedPoses.end() && poses.find(iterPose->first) == poses.end())
3276 poses.insert(*iterPose);
3278 constraints.insert(std::make_pair(iterPose->first,
Link(iterPose->first, iterPose->first,
Link::kPosePrior, iterPose->second, priorInfMat)));
3281 UDEBUG(
"Constraint %d->%d: %s (type=%s, var = %f %f)",
iter->second.from(),
iter->second.to(),
iter->second.transform().prettyPrint().c_str(),
iter->second.typeName().c_str(),
iter->second.transVariance(),
iter->second.rotVariance());
3284 std::map<int, Transform> posesOut;
3285 std::multimap<int, Link> edgeConstraintsOut;
3287 UDEBUG(
"priorsIgnored was %s", priorsIgnored?
"true":
"false");
3293 for(std::map<int, Transform>::iterator
iter=posesOut.begin();
iter!=posesOut.end(); ++
iter)
3295 UDEBUG(
"Pose %d %s",
iter->first,
iter->second.prettyPrint().c_str());
3298 cv::Mat locOptCovariance;
3299 std::map<int, Transform> optPoses;
3300 if(!posesOut.empty() &&
3303 optPoses =
_graphOptimizer->
optimize(posesOut.begin()->first, posesOut, edgeConstraintsOut, locOptCovariance);
3307 UERROR(
"Invalid localization constraints");
3310 for(std::map<int, Transform>::iterator
iter=optPoses.begin();
iter!=optPoses.end(); ++
iter)
3312 UDEBUG(
"Opt %d %s",
iter->first,
iter->second.prettyPrint().c_str());
3315 if(optPoses.empty())
3317 UWARN(
"Optimization failed, rejecting localization!");
3318 rejectLocalization =
true;
3322 UINFO(
"Compute max graph errors...");
3323 const Link * maxLinearLink = 0;
3324 const Link * maxAngularLink = 0;
3328 maxLinearErrorRatio,
3329 maxAngularErrorRatio,
3335 if(maxLinearLink == 0 && maxAngularLink==0)
3337 UWARN(
"Could not compute graph errors! Rejecting localization!");
3338 rejectLocalization =
true;
3343 UINFO(
"Max optimization linear error = %f m (link %d->%d, var=%f, ratio error/std=%f, thr=%f)",
3345 maxLinearLink->
from(),
3346 maxLinearLink->
to(),
3352 UWARN(
"Rejecting localization (%d <-> %d) in this "
3353 "iteration because a wrong loop closure has been "
3354 "detected after graph optimization, resulting in "
3355 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). The "
3356 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3357 localizationLinks.rbegin()->second.from(),
3358 localizationLinks.rbegin()->second.to(),
3359 maxLinearErrorRatio,
3360 maxLinearLink->
from(),
3361 maxLinearLink->
to(),
3362 maxLinearLink->
type(),
3365 Parameters::kRGBDOptimizeMaxError().c_str(),
3367 rejectLocalization =
true;
3371 UERROR(
"Huge optimization error detected!"
3372 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3373 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3374 maxLinearErrorRatio,
3375 maxLinearLink->
from(),
3376 maxLinearLink->
to(),
3377 maxLinearLink->
type(),
3380 Parameters::kRGBDOptimizeMaxError().c_str());
3385 UINFO(
"Max optimization angular error = %f deg (link %d->%d, var=%f, ratio error/std=%f, thr=%f)",
3386 maxAngularError*180.0
f/CV_PI,
3387 maxAngularLink->
from(),
3388 maxAngularLink->
to(),
3394 UWARN(
"Rejecting localization (%d <-> %d) in this "
3395 "iteration because a wrong loop closure has been "
3396 "detected after graph optimization, resulting in "
3397 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f deg, stddev=%f). The "
3398 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3399 localizationLinks.rbegin()->second.from(),
3400 localizationLinks.rbegin()->second.to(),
3401 maxAngularErrorRatio,
3402 maxAngularLink->
from(),
3403 maxAngularLink->
to(),
3404 maxAngularLink->
type(),
3405 maxAngularError*180.0f/CV_PI,
3407 Parameters::kRGBDOptimizeMaxError().c_str(),
3409 rejectLocalization =
true;
3413 UERROR(
"Huge optimization error detected!"
3414 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3415 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3416 maxAngularErrorRatio,
3417 maxAngularLink->
from(),
3418 maxAngularLink->
to(),
3419 maxAngularLink->
type(),
3420 maxAngularError*180.0f/CV_PI,
3422 Parameters::kRGBDOptimizeMaxError().c_str());
3427 bool hasGlobalLoopClosuresOrLandmarks =
false;
3433 for(std::multimap<int, Link>::iterator
iter=constraints.begin();
iter!=constraints.end() && !hasGlobalLoopClosuresOrLandmarks; ++
iter)
3435 hasGlobalLoopClosuresOrLandmarks =
3439 if(hasGlobalLoopClosuresOrLandmarks && !localizationLinks.empty())
3441 rejectLocalization =
false;
3442 UWARN(
"Global and loop closures seem not tallying together, try again to optimize without local loop closures...");
3444 UDEBUG(
"priorsIgnored was %s", priorsIgnored?
"true":
"false");
3449 if(!posesOut.empty() &&
3452 optPoses =
_graphOptimizer->
optimize(posesOut.begin()->first, posesOut, edgeConstraintsOut, locOptCovariance);
3456 UERROR(
"Invalid localization constraints");
3459 for(std::map<int, Transform>::iterator
iter=optPoses.begin();
iter!=optPoses.end(); ++
iter)
3461 UDEBUG(
"Opt2 %d %s",
iter->first,
iter->second.prettyPrint().c_str());
3464 if(optPoses.empty())
3466 UWARN(
"Optimization failed, rejecting localization!");
3467 rejectLocalization =
true;
3471 UINFO(
"Compute max graph errors...");
3472 const Link * maxLinearLink = 0;
3473 const Link * maxAngularLink = 0;
3477 maxLinearErrorRatio,
3478 maxAngularErrorRatio,
3484 if(maxLinearLink == 0 && maxAngularLink==0)
3486 UWARN(
"Could not compute graph errors! Rejecting localization!");
3487 rejectLocalization =
true;
3492 UINFO(
"Max optimization linear error = %f m (link %d->%d, var=%f, ratio error/std=%f, thr=%f)",
3494 maxLinearLink->
from(),
3495 maxLinearLink->
to(),
3501 UWARN(
"Rejecting localization (%d <-> %d) in this "
3502 "iteration because a wrong loop closure has been "
3503 "detected after graph optimization, resulting in "
3504 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). The "
3505 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3506 localizationLinks.rbegin()->second.from(),
3507 localizationLinks.rbegin()->second.to(),
3508 maxLinearErrorRatio,
3509 maxLinearLink->
from(),
3510 maxLinearLink->
to(),
3511 maxLinearLink->
type(),
3514 Parameters::kRGBDOptimizeMaxError().c_str(),
3516 rejectLocalization =
true;
3520 UERROR(
"Huge optimization error detected!"
3521 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3522 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3523 maxLinearErrorRatio,
3524 maxLinearLink->
from(),
3525 maxLinearLink->
to(),
3526 maxLinearLink->
type(),
3529 Parameters::kRGBDOptimizeMaxError().c_str());
3534 UINFO(
"Max optimization angular error = %f deg (link %d->%d, var=%f, ratio error/std=%f, thr=%f)",
3535 maxAngularError*180.0
f/CV_PI,
3536 maxAngularLink->
from(),
3537 maxAngularLink->
to(),
3543 UWARN(
"Rejecting localization (%d <-> %d) in this "
3544 "iteration because a wrong loop closure has been "
3545 "detected after graph optimization, resulting in "
3546 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f deg, stddev=%f). The "
3547 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3548 localizationLinks.rbegin()->second.from(),
3549 localizationLinks.rbegin()->second.to(),
3550 maxAngularErrorRatio,
3551 maxAngularLink->
from(),
3552 maxAngularLink->
to(),
3553 maxAngularLink->
type(),
3554 maxAngularError*180.0f/CV_PI,
3556 Parameters::kRGBDOptimizeMaxError().c_str(),
3558 rejectLocalization =
true;
3562 UERROR(
"Huge optimization error detected!"
3563 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3564 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3565 maxAngularErrorRatio,
3566 maxAngularLink->
from(),
3567 maxAngularLink->
to(),
3568 maxAngularLink->
type(),
3569 maxAngularError*180.0f/CV_PI,
3571 Parameters::kRGBDOptimizeMaxError().c_str());
3578 if(!rejectLocalization)
3580 if(hasGlobalLoopClosuresOrLandmarks)
3588 UWARN(
"Successfully optimized without local loop closures! Clear them from local odometry cache. %ld/%ld have been removed.",
3593 UWARN(
"Successfully optimized without local loop closures!");
3598 bool hadAlreadyLocalizationLinks =
false;
3609 hadAlreadyLocalizationLinks =
true;
3617 for(std::multimap<int, Link>::iterator
iter=localizationLinks.begin();
iter!=localizationLinks.end(); ++
iter)
3622 UDEBUG(
"Adding new odom cache constraint %d->%d (%s)",
3623 iter->second.from(),
iter->second.to(),
iter->second.transform().prettyPrint().c_str());
3630 UDEBUG(
"Adjusted localization link %d->%d after optimization",
iter->second.from(),
iter->second.to());
3631 UDEBUG(
"from %s",
iter->second.transform().prettyPrint().c_str());
3633 iter->second.setTransform(newT);
3648 UINFO(
"Update localization");
3656 Transform u = signature->
getPose() * localizationLinks.rbegin()->second.transform();
3661 int loopId = localizationLinks.rbegin()->first;
3667 landmarkId = loopId;
3668 UASSERT(landmarksDetected.find(landmarkId) != landmarksDetected.end() &&
3669 !landmarksDetected.at(landmarkId).empty());
3670 loopId = *landmarksDetected.at(landmarkId).begin();
3677 if(iterGravityLoop!=loopS->
getLinks().end() &&
3678 iterGravitySign!=signature->
getLinks().end())
3683 iterGravityLoop->second.transform().getEulerAngles(
roll,
pitch,
yaw);
3692 iterGravityLoop->second.transform().getEulerAngles(
roll,
pitch,
yaw);
3696 Transform error =
transform.rotation().inverse() * iterGravitySign->second.transform().rotation().inverse() * targetRotation;
3700 else if(iterGravityLoop!=loopS->
getLinks().end() ||
3701 iterGravitySign!=signature->
getLinks().end())
3703 UWARN(
"Gravity link not found for %d or %d, localization won't be corrected with gravity.", loopId, signature->
id());
3714 iter->second = mapCorrectionInv * up *
iter->second;
3720 Transform newPose =
_optimizedPoses.at(localizationLinks.rbegin()->first) * localizationLinks.rbegin()->second.transform().inverse();
3725 newPose = newPose.
to3DoF();
3732 if(iterGravitySign!=signature->
getLinks().end())
3737 UDEBUG(
"Gravity link = %s", iterGravitySign->second.transform().prettyPrint().c_str());
3741 Transform error =
transform.rotation().inverse() * iterGravitySign->second.transform().rotation().inverse() * targetRotation;
3744 iterGravitySign->second.transform().getEulerAngles(
roll,
pitch, tmp1);
3749 else if(iterGravitySign!=signature->
getLinks().end())
3751 UWARN(
"Gravity link not found for %d, localization won't be corrected with gravity.", signature->
id());
3756 _localizationCovariance = locOptCovariance.empty()?localizationLinks.rbegin()->second.infMatrix().inv():locOptCovariance;
3760 UWARN(
"Localization was good, but waiting for another one to be more accurate (%s>0)", Parameters::kRGBDMaxOdomCacheSize().
c_str());
3761 delayedLocalization =
true;
3762 rejectLocalization =
true;
3767 if(rejectLocalization)
3770 lastProximitySpaceClosureId = 0;
3771 rejectedGlobalLoopClosure =
true;
3772 rejectedLandmark =
true;
3777 UINFO(
"Update map correction");
3783 UWARN(
"Optimization: clearing guess poses as %s has changed state, now %s",
3789 std::multimap<int, Link> constraints;
3791 optimizeCurrentMap(signature->
id(),
false, poses, covariance, &constraints, &optimizationError, &optimizationIterations);
3795 bool updateConstraints =
true;
3798 UWARN(
"Graph optimization failed! Rejecting last loop closures added.");
3799 for(std::list<std::pair<int, int> >::
iterator iter=loopClosureLinksAdded.begin();
iter!=loopClosureLinksAdded.end(); ++
iter)
3802 UWARN(
"Loop closure %d->%d rejected!",
iter->first,
iter->second);
3804 updateConstraints =
false;
3806 lastProximitySpaceClosureId = 0;
3807 rejectedGlobalLoopClosure =
true;
3808 rejectedLandmark =
true;
3811 loopClosureLinksAdded.size() &&
3812 optimizationIterations > 0 &&
3815 UINFO(
"Compute max graph errors...");
3816 const Link * maxLinearLink = 0;
3817 const Link * maxAngularLink = 0;
3821 maxLinearErrorRatio,
3822 maxAngularErrorRatio,
3827 if(maxLinearLink == 0 && maxAngularLink==0)
3829 UWARN(
"Could not compute graph errors! Wrong loop closures could be accepted!");
3832 bool reject =
false;
3835 UINFO(
"Max optimization linear error = %f m (link %d->%d, var=%f, ratio error/std=%f)", maxLinearError, maxLinearLink->
from(), maxLinearLink->
to(), maxLinearLink->
transVariance(), maxLinearError/
sqrt(maxLinearLink->
transVariance()));
3838 UWARN(
"Rejecting all added loop closures (%d, first is %d <-> %d) in this "
3839 "iteration because a wrong loop closure has been "
3840 "detected after graph optimization, resulting in "
3841 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). The "
3842 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3843 (
int)loopClosureLinksAdded.size(),
3844 loopClosureLinksAdded.front().first,
3845 loopClosureLinksAdded.front().second,
3846 maxLinearErrorRatio,
3847 maxLinearLink->
from(),
3848 maxLinearLink->
to(),
3849 maxLinearLink->
type(),
3852 Parameters::kRGBDOptimizeMaxError().c_str(),
3858 UERROR(
"Huge optimization error detected!"
3859 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3860 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3861 maxLinearErrorRatio,
3862 maxLinearLink->
from(),
3863 maxLinearLink->
to(),
3864 maxLinearLink->
type(),
3867 Parameters::kRGBDOptimizeMaxError().c_str());
3872 UINFO(
"Max optimization angular error = %f deg (link %d->%d, var=%f, ratio error/std=%f)", maxAngularError*180.0
f/CV_PI, maxAngularLink->
from(), maxAngularLink->
to(), maxAngularLink->
rotVariance(), maxAngularError/
sqrt(maxAngularLink->
rotVariance()));
3875 UWARN(
"Rejecting all added loop closures (%d, first is %d <-> %d) in this "
3876 "iteration because a wrong loop closure has been "
3877 "detected after graph optimization, resulting in "
3878 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f deg, stddev=%f). The "
3879 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3880 (
int)loopClosureLinksAdded.size(),
3881 loopClosureLinksAdded.front().first,
3882 loopClosureLinksAdded.front().second,
3883 maxAngularErrorRatio,
3884 maxAngularLink->
from(),
3885 maxAngularLink->
to(),
3886 maxAngularLink->
type(),
3887 maxAngularError*180.0f/CV_PI,
3889 Parameters::kRGBDOptimizeMaxError().c_str(),
3895 UERROR(
"Huge optimization error detected!"
3896 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3897 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3898 maxAngularErrorRatio,
3899 maxAngularLink->
from(),
3900 maxAngularLink->
to(),
3901 maxAngularLink->
type(),
3902 maxAngularError*180.0f/CV_PI,
3904 Parameters::kRGBDOptimizeMaxError().c_str());
3910 for(std::list<std::pair<int, int> >::
iterator iter=loopClosureLinksAdded.begin();
iter!=loopClosureLinksAdded.end(); ++
iter)
3913 UWARN(
"Loop closure %d->%d rejected!",
iter->first,
iter->second);
3915 updateConstraints =
false;
3917 lastProximitySpaceClosureId = 0;
3918 rejectedGlobalLoopClosure =
true;
3919 rejectedLandmark =
true;
3923 if(updateConstraints)
3925 UINFO(
"Updated local map (old size=%d, new size=%d)", (
int)
_optimizedPoses.size(), (
int)poses.size());
3954 bool hasPrior = signature->
hasLink(signature->
id());
3973 if(newLocId==0 && !landmarksDetected.empty())
3978 if(
iter->second.size() && *
iter->second.begin()!=signature->
id())
3985 timeMapOptimization =
timer.ticks();
3986 ULOGGER_INFO(
"timeMapOptimization=%fs", timeMapOptimization);
3992 int dictionarySize = 0;
3993 int refWordsCount = 0;
3994 int refUniqueWordsCount = 0;
3995 int lcHypothesisReactivated = 0;
4001 lcHypothesisReactivated = sLoop->
isSaved()?1.0f:0.0f;
4004 refWordsCount = (
int)signature->
getWords().size();
4058 statistics_.
addStatistic(Statistics::kLoopLandmark_detected(), landmarksDetected.empty()?0:-landmarksDetected.begin()->first);
4059 statistics_.
addStatistic(Statistics::kLoopLandmark_detected_node_ref(), landmarksDetected.empty() || landmarksDetected.begin()->second.empty()?0:*landmarksDetected.begin()->second.begin());
4061 statistics_.
addStatistic(Statistics::kLoopVisual_inliers_distribution(), loopClosureVisualInliersDistribution);
4064 statistics_.
addStatistic(Statistics::kProximitySpace_detections_added_visually(), proximityDetectionsAddedVisually);
4065 statistics_.
addStatistic(Statistics::kProximitySpace_detections_added_icp_multi(), proximityDetectionsAddedByICPMulti);
4066 statistics_.
addStatistic(Statistics::kProximitySpace_detections_added_icp_global(), proximityDetectionsAddedByICPGlobal);
4080 if(
_loopClosureHypothesis.first || lastProximitySpaceClosureId || (!rejectedLandmark && !landmarksDetected.empty()))
4086 std::multimap<int, Link>::const_iterator loopIter = sLoop->
getLinks().find(signature->
id());
4088 UINFO(
"Set loop closure transform = %s", loopIter->second.transform().prettyPrint().c_str());
4097 Transform error = loopIter->second.transform().inverse() * transformGT;
4161 statistics_.
addStatistic(Statistics::kTimingProximity_by_space_visual(), timeProximityBySpaceVisualDetection*1000);
4189 if(distanceToClosestNodeInTheGraph>0.0)
4199 long estimatedMemoryUsage =
sizeof(
Rtabmap);
4200 estimatedMemoryUsage +=
_optimizedPoses.size() * (
sizeof(
int) +
sizeof(
Transform) + 12 *
sizeof(
float) +
sizeof(std::map<int, Transform>::iterator)) +
sizeof(std::map<int, Transform>);
4201 estimatedMemoryUsage +=
_constraints.size() * (
sizeof(
int) +
sizeof(
Transform) + 12 *
sizeof(
float) +
sizeof(cv::Mat) + 36 *
sizeof(double) +
sizeof(std::map<int, Link>::iterator)) +
sizeof(std::map<int, Link>);
4204 estimatedMemoryUsage +=
_parameters.size()*(
sizeof(std::string)*2+
sizeof(ParametersMap::iterator)) +
sizeof(
ParametersMap);
4234 timeStatsCreation =
timer.ticks();
4235 ULOGGER_INFO(
"Time creating stats = %f...", timeStatsCreation);
4238 Signature lastSignatureData = *signature;
4263 if(signatureRemoved)
4265 signaturesRemoved.push_back(signatureRemoved);
4272 if(signatureRemoved != lastSignatureData.
id())
4277 (landmarksDetected.empty() || rejectedLandmark) &&
4280 UWARN(
"Ignoring location %d because a global loop closure is required before starting a new map!",
4282 signaturesRemoved.push_back(signature->
id());
4289 UWARN(
"Ignoring location %d because a good signature (with enough features or with a landmark detected) is required before starting a new map!",
4291 signaturesRemoved.push_back(signature->
id());
4294 else if((smallDisplacement || tooFastMovement) &&
4296 lastProximitySpaceClosureId == 0 &&
4297 (rejectedLandmark || landmarksDetected.empty()) &&
4301 UINFO(
"Ignoring location %d because the displacement is too small! (d=%f a=%f)",
4304 signaturesRemoved.push_back(signature->
id());
4313 (smallDisplacement || tooFastMovement) &&
4315 lastProximitySpaceClosureId == 0 &&
4316 !delayedLocalization &&
4317 (rejectedLandmark || landmarksDetected.empty()))
4322 if(
iter->second.from() == signatureRemoved ||
iter->second.to() == signatureRemoved)
4336 timeMemoryCleanup =
timer.ticks();
4337 ULOGGER_INFO(
"timeMemoryCleanup = %fs... %d signatures removed", timeMemoryCleanup, (
int)signaturesRemoved.size());
4349 double totalTime = timerTotal.
ticks();
4350 ULOGGER_INFO(
"Total time processing = %fs...", totalTime);
4356 std::list<int> transferred =
_memory->
forget(immunizedLocations);
4357 signaturesRemoved.insert(signaturesRemoved.end(), transferred.begin(), transferred.end());
4384 UDEBUG(
"Refresh local map from %d",
id);
4391 UDEBUG(
"Refresh local map from %d",
id);
4405 UDEBUG(
"Refresh local map from %d",
id);
4416 if(signaturesRemoved.size() == 1 && signaturesRemoved.front() == lastSignatureData.
id())
4418 int lastId = signaturesRemoved.front();
4419 UDEBUG(
"Detected that only last signature has been removed (lastId=%d)", lastId);
4423 if(
iter->second.to() !=
iter->second.from())
4442 UDEBUG(
"Removed %d from local map",
iter->first);
4448 UWARN(
"optimized poses have been modified, clearing global scan map...");
4474 UDEBUG(
"Optimized poses cleared!");
4489 timeRealTimeLimitReachedProcess =
timer.ticks();
4490 ULOGGER_INFO(
"Time limit reached processing = %f...", timeRealTimeLimitReachedProcess);
4495 int localGraphSize = 0;
4517 std::map<int, Transform> poses;
4518 std::multimap<int, Link> constraints;
4536 std::multimap<int, int> missingIds;
4542 missingIds.insert(std::make_pair(-1, tmpId));
4553 for(std::map<int, int>::iterator
iter=ids.begin();
iter!=ids.end(); ++
iter)
4555 if(
iter->first != loopId &&
4558 missingIds.insert(std::make_pair(
iter->second,
iter->first));
4567 if(ids.find(*
iter) == ids.end())
4581 std::stringstream
stream;
4591 UWARN(
"Republishing data of requested node(s) %s(%s=%d)",
4593 Parameters::kRtabmapMaxRepublished().c_str(),
4599 localGraphSize = (
int)poses.size();
4600 if(!lastSignatureLocalizedPose.
isNull())
4602 poses.insert(std::make_pair(lastSignatureData.
id(), lastSignatureLocalizedPose));
4616 UDEBUG(
"Computing RMSE...");
4617 float translational_rmse = 0.0f;
4618 float translational_mean = 0.0f;
4619 float translational_median = 0.0f;
4620 float translational_std = 0.0f;
4621 float translational_min = 0.0f;
4622 float translational_max = 0.0f;
4623 float rotational_rmse = 0.0f;
4624 float rotational_mean = 0.0f;
4625 float rotational_median = 0.0f;
4626 float rotational_std = 0.0f;
4627 float rotational_min = 0.0f;
4628 float rotational_max = 0.0f;
4635 translational_median,
4658 UDEBUG(
"Computing RMSE...done!");
4661 std::vector<int> ids;
4665 ids.push_back(*
iter);
4669 ids.push_back(
iter->first);
4672 UDEBUG(
"wmState=%d", (
int)ids.size());
4682 UDEBUG(
"Empty trash...");
4690 std::string logF =
uFormat(
"%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n",
4694 timeLikelihoodCalculation,
4695 timePosteriorCalculation,
4696 timeHypothesesCreation,
4697 timeHypothesesValidation,
4698 timeRealTimeLimitReachedProcess,
4710 timeRetrievalDbAccess,
4711 timeAddLoopClosureLink,
4713 timeNeighborLinkRefining,
4714 timeProximityByTimeDetection,
4715 timeProximityBySpaceDetection,
4716 timeMapOptimization);
4717 std::string logI =
uFormat(
"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
4720 (
int)signaturesRemoved.size(),
4725 rejectedGlobalLoopClosure?1:0,
4728 int(signaturesRetrieved.size()),
4729 lcHypothesisReactivated,
4730 refUniqueWordsCount,
4734 rehearsalMaxId>0?1:0,
4752 fprintf(
_foutInt,
"%s", logI.c_str());
4755 UINFO(
"Time logging = %f...",
timer.ticks());
4758 timeFinalizingStatistics =
timer.ticks();
4759 UDEBUG(
"End process, timeFinalizingStatistics=%fs", timeFinalizingStatistics);
4775 ULOGGER_WARN(
"maxTimeAllowed < 0, then setting it to 0 (inf).");
4787 if(maxMemoryAllowed < 0)
4789 ULOGGER_WARN(
"maxMemoryAllowed < 0, then setting it to 0 (inf).");
4804 UWARN(
"Working directory has been changed from \"%s\" with \"%s\", new log files will be created.",
4811 else if(
path.empty())
4827 bool linksRemoved =
false;
4828 for(std::multimap<int, Link>::iterator
iter = links.begin();
iter!=links.end(); ++
iter)
4847 linksRemoved =
true;
4858 UINFO(
"Update graph");
4860 std::multimap<int, Link> constraints;
4866 UWARN(
"Graph optimization failed after removing loop closure links from last location!");
4870 UINFO(
"Updated local map (old size=%d, new size=%d)", (
int)
_optimizedPoses.size(), (
int)poses.size());
4889 UINFO(
"Update graph");
4895 if(
iter->second.from() == lastId ||
iter->second.to() == lastId)
4911 std::multimap<int, Link> constraints;
4917 UWARN(
"Graph optimization failed after deleting the last location!");
4943 UERROR(
"Working directory not set.");
4956 int maxNearestNeighbors,
4961 std::map<int, Transform> poses;
4969 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
4975 std::map<int, float> foundIds;
4985 float radiusSqrd = radius * radius;
4988 if(
iter->first != fromId)
4990 if(stm.find(
iter->first) == stm.end() &&
4992 (radiusSqrd==0 || foundIds.at(
iter->first) <= radiusSqrd))
4994 (*cloud)[oi] = pcl::PointXYZ(
iter->second.x(),
iter->second.y(),
iter->second.z());
4995 ids[oi++] =
iter->first;
5017 pcl::CropBox<pcl::PointXYZ> cropbox;
5018 cropbox.setInputCloud(cloud);
5019 cropbox.setMin(Eigen::Vector4f(-1, -radius, -999999, 0));
5020 cropbox.setMax(Eigen::Vector4f(radius, radius, 999999, 0));
5021 cropbox.setRotation(Eigen::Vector3f(
roll,
pitch,
yaw));
5022 cropbox.setTranslation(Eigen::Vector3f(
x,
y,
z));
5024 pcl::IndicesPtr
indices(
new std::vector<int>());
5035 pcl::search::KdTree<pcl::PointXYZ>::Ptr kdTree(
new pcl::search::KdTree<pcl::PointXYZ>);
5036 kdTree->setInputCloud(cloud,
indices);
5037 std::vector<int>
ind;
5038 std::vector<float>
dist;
5039 pcl::PointXYZ pt(fromT.
x(), fromT.
y(), fromT.
z());
5040 kdTree->radiusSearch(pt, radius,
ind,
dist, maxNearestNeighbors);
5042 for(
unsigned int i=0;
i<
ind.size(); ++
i)
5049 poses.insert(std::make_pair(ids[
ind[
i]], tmp));
5070 std::map<int, std::map<int, Transform> >
Rtabmap::getPaths(
const std::map<int, Transform> & posesIn,
const Transform & target,
int maxGraphDepth)
const
5072 std::map<int, std::map<int, Transform> > paths;
5073 std::set<int> nodesSet;
5074 std::map<int, Transform> poses;
5075 for(std::map<int, Transform>::const_iterator
iter=posesIn.lower_bound(1);
iter!=posesIn.end(); ++
iter)
5077 nodesSet.insert(
iter->first);
5078 poses.insert(*
iter);
5082 double e0=0,e1=0,e2=0,e3=0,e4=0;
5088 std::map<int, Transform>
path;
5096 UWARN(
"Nearest id of %s in %d poses is 0 !? Returning empty path.",
target.prettyPrint().c_str(), (
int)poses.size());
5099 std::map<int, int> ids =
_memory->
getNeighborsId(nearestId, maxGraphDepth, 0,
true,
true,
true,
true, nodesSet);
5103 for(std::map<int, int>::iterator
iter=ids.begin();
iter!=ids.end(); ++
iter)
5105 std::map<int, Transform>::iterator jter = poses.find(
iter->first);
5106 if(jter != poses.end())
5108 bool valid =
path.empty();
5113 for(std::multimap<int, Link>::iterator kter=links.begin(); kter!=links.end() && !valid; ++kter)
5115 valid =
path.find(kter->first) !=
path.end();
5134 UWARN(
"%s=Off but path(%d) > maxGraphDepth(%d)*2+1, nearestId=%d ids=%d. Is reduce graph activated before?",
5135 Parameters::kMemReduceGraph().
c_str(), (
int)
path.size(), maxGraphDepth, nearestId, (
int)ids.size());
5137 paths.insert(std::make_pair(nearestId,
path));
5141 UWARN(
"path.size()=0!? nearestId=%d ids=%d, aborting...", nearestId, (
int)ids.size());
5147 UDEBUG(
"e0=%fs e1=%fs e2=%fs e3=%fs e4=%fs", e0, e1, e2, e3, e4);
5154 bool lookInDatabase,
5155 std::map<int, Transform> & optimizedPoses,
5156 cv::Mat & covariance,
5157 std::multimap<int, Link> * constraints,
5159 int * iterationsDone)
const
5162 UINFO(
"Optimize map: around location %d (lookInDatabase=%s)",
id, lookInDatabase?
"true":
"false");
5169 id = ids.begin()->first;
5171 UINFO(
"get %d ids time %f s", (
int)ids.size(),
timer.ticks());
5178 optimizedPoses = poses;
5183 UINFO(
"Correction (from node %d) %s",
id,
t.prettyPrint().c_str());
5188 UWARN(
"Failed to optimize the graph! returning empty optimized poses...");
5189 optimizedPoses.clear();
5192 constraints->clear();
5200 const std::set<int> & ids,
5201 const std::map<int, Transform> & guessPoses,
5202 bool lookInDatabase,
5203 cv::Mat & covariance,
5204 std::multimap<int, Link> * constraints,
5206 int * iterationsDone)
const
5209 std::map<int, Transform> optimizedPoses;
5210 std::map<int, Transform> poses;
5211 std::multimap<int, Link> edgeConstraints;
5212 UDEBUG(
"ids=%d", (
int)ids.size());
5214 UINFO(
"get constraints (ids=%d, %d poses, %d edges) time %f s", (
int)ids.size(), (
int)poses.size(), (
int)edgeConstraints.size(),
timer.ticks());
5217 for(std::map<int, Transform>::iterator
iter=poses.begin();
iter!=poses.end() &&
iter->first < 0; ++
iter)
5221 cv::Mat infMatrix = cv::Mat::eye(6, 6, CV_64FC1);
5232 for(std::map<int, Transform>::iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
5235 std::map<int, Transform>::const_iterator foundGuess = guessPoses.find(
iter->first);
5236 if(foundGuess!=guessPoses.end() &&
iter->first != fromId)
5238 iter->second = foundGuess->second;
5248 optimizedPoses = poses;
5251 *constraints = edgeConstraints;
5256 bool hasLandmarks = !edgeConstraints.empty() && edgeConstraints.begin()->first < 0;
5257 if(poses.size() != guessPoses.size() || hasLandmarks)
5259 UDEBUG(
"recompute poses using only links (robust to multi-session)");
5260 std::map<int, Transform> posesOut;
5261 std::multimap<int, Link> edgeConstraintsOut;
5266 *constraints = edgeConstraintsOut;
5271 UDEBUG(
"use input guess poses");
5275 *constraints = edgeConstraints;
5279 if(!poses.empty() && optimizedPoses.empty())
5281 UWARN(
"Optimization has failed (poses=%d, guess=%d, links=%d)...",
5282 (
int)poses.size(), (
int)guessPoses.size(), (
int)edgeConstraints.size());
5286 UINFO(
"Optimization time %f s",
timer.ticks());
5288 return optimizedPoses;
5296 if(likelihood.size()==0)
5303 bool likelihoodNullValuesIgnored =
true;
5304 for(std::map<int, float>::iterator
iter = ++likelihood.begin();
iter!=likelihood.end(); ++
iter)
5306 if((
iter->second >= 0 && !likelihoodNullValuesIgnored) ||
5307 (
iter->second > 0 && likelihoodNullValuesIgnored))
5322 for(std::map<int, float>::iterator
iter=++likelihood.begin();
iter!= likelihood.end(); ++
iter)
5325 iter->second = 1.0f;
5341 maxId =
iter->first;
5347 likelihood.begin()->second =
mean/stdDev + 1.0f;
5351 likelihood.begin()->second = stdDev/(
max-
mean) + 1.0
f;
5355 likelihood.begin()->second = 2.0f;
5359 UDEBUG(
"mean=%f, stdDev=%f, max=%f, maxId=%d, time=%fs",
mean, stdDev,
max, maxId,
time);
5368 UERROR(
"Working directory not set.");
5371 std::list<int> signaturesToCompare;
5380 if(
s->getWeight() != -1)
5382 signaturesToCompare.push_back(
iter->first);
5388 signaturesToCompare.push_back(
iter->first);
5394 std::string fileName = this->
getWorkingDir() +
"/DumpPrediction.txt";
5396 fopen_s(&fout, fileName.c_str(),
"w");
5398 fout = fopen(fileName.c_str(),
"w");
5403 for(
int i=0;
i<prediction.rows; ++
i)
5405 for(
int j=0;
j<prediction.cols; ++
j)
5407 fprintf(fout,
"%f ",((
float*)prediction.data)[
j +
i*prediction.cols]);
5409 fprintf(fout,
"\n");
5416 UWARN(
"Memory and/or the Bayes filter are not created");
5434 _memory->
getNodeInfo(
id, odomPoseLocal, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors,
true);
5437 if(images || scan || userData || occupancyGrid)
5441 if(!images && withWords)
5443 std::vector<CameraModel> models;
5444 std::vector<StereoCameraModel> stereoModels;
5446 data.setCameraModels(models);
5447 data.setStereoCameraModels(stereoModels);
5460 for(std::multimap<int, Link>::iterator
iter=links.begin();
iter!=links.end(); ++
iter)
5464 s.addLandmark(
iter->second);
5468 s.addLink(
iter->second);
5472 if(withWords || withGlobalDescriptors)
5474 std::multimap<int, int> words;
5475 std::vector<cv::KeyPoint> wordsKpts;
5476 std::vector<cv::Point3f> words3;
5477 cv::Mat wordsDescriptors;
5478 std::vector<rtabmap::GlobalDescriptor> globalDescriptors;
5482 s.setWords(words, wordsKpts, words3, wordsDescriptors);
5484 if(withGlobalDescriptors)
5486 s.sensorData().setGlobalDescriptors(globalDescriptors);
5493 s.sensorData().setGPS(gps);
5494 s.sensorData().setEnvSensors(sensors);
5500 std::map<int, Signature> & signatures,
5501 std::map<int, Transform> & poses,
5502 std::multimap<int, Link> & constraints,
5507 return getGraph(poses, constraints, optimized, global, &signatures,
true,
true,
true,
true);
5511 std::map<int, Transform> & poses,
5512 std::multimap<int, Link> & constraints,
5515 std::map<int, Signature> * signatures,
5521 bool withGlobalDescriptors)
const
5566 for(std::set<int>::iterator
iter = ids.begin();
iter!=ids.end(); ++
iter)
5568 signatures->insert(std::make_pair(*
iter,
getSignatureCopy(*
iter, withImages, withScan, withUserData, withGrid, withWords, withGlobalDescriptors)));
5574 UERROR(
"Last working signature is null!?");
5578 UWARN(
"Memory not initialized...");
5584 std::map<int, float> nearestNodesTmp;
5585 std::map<int, float> * nearestNodesPtr = distsSqr == 0? &nearestNodesTmp : distsSqr;
5587 std::map<int, Transform> nearestPoses;
5588 for(std::map<int, float>::iterator
iter=nearestNodesPtr->begin();
iter!=nearestNodesPtr->end(); ++
iter)
5592 return nearestPoses;
5597 UDEBUG(
"nodeId=%d, radius=%f", nodeId, radius);
5598 std::map<int, float> nearestNodesTmp;
5599 std::map<int, float> * nearestNodesPtr = distsSqr == 0? &nearestNodesTmp : distsSqr;
5617 std::map<int, Transform> nearestPoses;
5618 for(std::map<int, float>::iterator
iter=nearestNodesPtr->begin();
iter!=nearestNodesPtr->end(); ++
iter)
5623 return nearestPoses;
5627 float clusterRadiusMax,
5633 float clusterRadiusMin)
5639 UERROR(
"Cannot detect more loop closures if graph optimization iterations = 0");
5644 UERROR(
"Detecting more loop closures can be done only in RGBD-SLAM mode.");
5647 if(!intraSession && !interSession)
5649 UERROR(
"Intra and/or inter session argument should be true.");
5653 std::list<Link> loopClosuresAdded;
5654 std::multimap<int, int> checkedLoopClosures;
5656 std::map<int, Transform> posesToCheckLoopClosures;
5657 std::map<int, Transform> poses;
5658 std::multimap<int, Link> links;
5659 std::map<int, Signature> signatures;
5660 this->
getGraph(poses, links,
true,
true, &signatures);
5662 std::map<int, int> mapIds;
5663 UDEBUG(
"remove all invalid or intermediate nodes, fill mapIds");
5664 for(std::map<int, Transform>::iterator
iter=poses.upper_bound(0);
iter!=poses.end();++
iter)
5666 if(signatures.at(
iter->first).getWeight() >= 0)
5668 posesToCheckLoopClosures.insert(*
iter);
5669 mapIds.insert(std::make_pair(
iter->first, signatures.at(
iter->first).mapId()));
5673 for(
int n=0;
n<iterations; ++
n)
5675 UINFO(
"Looking for more loop closures, clustering poses... (iteration=%d/%d, radius=%f m angle=%f rad)",
5676 n+1, iterations, clusterRadiusMax, clusterAngle);
5679 posesToCheckLoopClosures,
5683 UINFO(
"Looking for more loop closures, clustering poses... found %d clusters.", (
int)clusters.size());
5686 std::set<int> addedLinks;
5687 for(std::multimap<int, int>::iterator
iter=clusters.begin();
iter!= clusters.end(); ++
iter, ++
i)
5689 if(processState && processState->
isCanceled())
5695 int from =
iter->first;
5696 int to =
iter->second;
5699 from =
iter->second;
5703 int mapIdFrom =
uValue(mapIds, from, 0);
5704 int mapIdTo =
uValue(mapIds, to, 0);
5706 if((interSession && mapIdFrom != mapIdTo) ||
5707 (intraSession && mapIdFrom == mapIdTo))
5710 bool alreadyChecked =
false;
5711 for(std::multimap<int, int>::iterator jter = checkedLoopClosures.lower_bound(from);
5712 !alreadyChecked && jter!=checkedLoopClosures.end() && jter->first == from;
5715 if(to == jter->second)
5717 alreadyChecked =
true;
5724 if(addedLinks.find(from) == addedLinks.end() &&
5725 addedLinks.find(to) == addedLinks.end() &&
5730 if(
delta.getNorm() < clusterRadiusMax &&
5731 delta.getNorm() >= clusterRadiusMin)
5733 checkedLoopClosures.insert(std::make_pair(from, to));
5735 UASSERT(signatures.find(from) != signatures.end());
5736 UASSERT(signatures.find(to) != signatures.end());
5741 guess = poses.at(from).
inverse() * poses.at(to);
5750 bool updateConstraints =
true;
5755 int mapId = signatures.at(from).mapId();
5757 for(std::map<int, Signature>::iterator ster=signatures.begin(); ster!=signatures.end(); ++ster)
5759 if(ster->second.mapId() == mapId)
5761 fromId = ster->first;
5765 std::multimap<int, Link> linksIn = links;
5767 const Link * maxLinearLink = 0;
5768 const Link * maxAngularLink = 0;
5769 float maxLinearError = 0.0f;
5770 float maxAngularError = 0.0f;
5771 float maxLinearErrorRatio = 0.0f;
5772 float maxAngularErrorRatio = 0.0f;
5773 std::map<int, Transform> optimizedPoses;
5774 std::multimap<int, Link> links;
5775 UASSERT(poses.find(fromId) != poses.end());
5776 UASSERT_MSG(poses.find(from) != poses.end(),
uFormat(
"id=%d poses=%d links=%d", from, (
int)poses.size(), (
int)links.size()).c_str());
5777 UASSERT_MSG(poses.find(to) != poses.end(),
uFormat(
"id=%d poses=%d links=%d", to, (
int)poses.size(), (
int)links.size()).c_str());
5779 UASSERT(optimizedPoses.find(fromId) != optimizedPoses.end());
5780 UASSERT_MSG(optimizedPoses.find(from) != optimizedPoses.end(),
uFormat(
"id=%d poses=%d links=%d", from, (
int)optimizedPoses.size(), (
int)links.size()).c_str());
5781 UASSERT_MSG(optimizedPoses.find(to) != optimizedPoses.end(),
uFormat(
"id=%d poses=%d links=%d", to, (
int)optimizedPoses.size(), (
int)links.size()).c_str());
5785 if(optimizedPoses.size())
5790 maxLinearErrorRatio,
5791 maxAngularErrorRatio,
5798 UINFO(
"Max optimization linear error = %f m (link %d->%d)", maxLinearError, maxLinearLink->
from(), maxLinearLink->
to());
5801 msg =
uFormat(
"Rejecting edge %d->%d because "
5802 "graph error is too large after optimization (%f m for edge %d->%d with ratio %f > std=%f m). "
5807 maxLinearLink->
from(),
5808 maxLinearLink->
to(),
5809 maxLinearErrorRatio,
5811 Parameters::kRGBDOptimizeMaxError().c_str(),
5816 UERROR(
"Huge optimization error detected!"
5817 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
5818 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
5819 maxLinearErrorRatio,
5820 maxLinearLink->
from(),
5821 maxLinearLink->
to(),
5822 maxLinearLink->
type(),
5825 Parameters::kRGBDOptimizeMaxError().c_str());
5828 else if(maxAngularLink)
5830 UINFO(
"Max optimization angular error = %f deg (link %d->%d)", maxAngularError*180.0
f/
M_PI, maxAngularLink->
from(), maxAngularLink->
to());
5833 msg =
uFormat(
"Rejecting edge %d->%d because "
5834 "graph error is too large after optimization (%f deg for edge %d->%d with ratio %f > std=%f deg). "
5838 maxAngularError*180.0
f/
M_PI,
5839 maxAngularLink->
from(),
5840 maxAngularLink->
to(),
5841 maxAngularErrorRatio,
5843 Parameters::kRGBDOptimizeMaxError().c_str(),
5848 UERROR(
"Huge optimization error detected!"
5849 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
5850 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
5851 maxAngularErrorRatio,
5852 maxAngularLink->
from(),
5853 maxAngularLink->
to(),
5854 maxAngularLink->
type(),
5855 maxAngularError*180.0f/CV_PI,
5857 Parameters::kRGBDOptimizeMaxError().c_str());
5863 msg =
uFormat(
"Rejecting edge %d->%d because graph optimization has failed!",
5870 updateConstraints =
false;
5874 poses = optimizedPoses;
5877 if(updateConstraints)
5879 addedLinks.insert(from);
5880 addedLinks.insert(to);
5884 std::string
msg =
uFormat(
"Iteration %d/%d: Added loop closure %d->%d! (%d/%d)",
n+1, iterations, from, to,
i+1, (
int)clusters.size());
5905 std::string
msg =
uFormat(
"Iteration %d/%d: Detected %d total loop closures!",
n+1, iterations, (
int)addedLinks.size()/2);
5914 UINFO(
"Iteration %d/%d: Detected %d total loop closures!",
n+1, iterations, (
int)addedLinks.size()/2);
5917 if(addedLinks.size() == 0)
5922 UINFO(
"Optimizing graph with new links (%d nodes, %d constraints)...",
5923 (
int)poses.size(), (
int)links.size());
5926 if(poses.size() == 0)
5928 UERROR(
"Optimization failed! Rejecting all loop closures...");
5929 loopClosuresAdded.clear();
5932 UINFO(
"Optimizing graph with new links... done!");
5934 UINFO(
"Total added %d loop closures.", (
int)loopClosuresAdded.size());
5936 if(loopClosuresAdded.size())
5938 for(std::list<Link>::iterator
iter=loopClosuresAdded.begin();
iter!=loopClosuresAdded.end(); ++
iter)
5945 std::map<int, Transform>::iterator jter = poses.find(
iter->first);
5946 if(jter != poses.end())
5948 iter->second = jter->second;
5951 std::map<int, Transform> tmp;
5957 return (
int)loopClosuresAdded.size();
5962 bool rematchFeatures,
5964 float pixelVariance)
5968 int iterations = Parameters::defaultOptimizerIterations();
5969 float pixelVariance = Parameters::defaultg2oPixelVariance();
5977 if(pixelVariance > 0.0
f)
5982 std::map<int, Signature> signatures;
5992 std::map<int, Transform> poses = optimizer->
optimizeBA(
6002 UERROR(
"Optimization failed!");
6020 const std::map<int, Transform> & poses,
6021 const cv::Mat & map,
6046 UERROR(
"Refining links can be done only in RGBD-SLAM mode.");
6050 std::list<Link> linksRefined;
6052 std::map<int, Transform> poses;
6053 std::multimap<int, Link> links;
6054 std::map<int, Signature> signatures;
6055 this->
getGraph(poses, links,
false,
true, &signatures);
6058 for(std::multimap<int, Link>::iterator
iter=links.lower_bound(1);
iter!= links.end(); ++
iter)
6060 int from =
iter->second.from();
6061 int to =
iter->second.to();
6063 UASSERT(signatures.find(from) != signatures.end());
6064 UASSERT(signatures.find(to) != signatures.end());
6072 linksRefined.push_back(
Link(from, to,
iter->second.type(),
t,
info.covariance.inv()));
6073 UINFO(
"Refined link %d->%d! (%d/%d)", from, to, ++
i, (
int)links.size());
6076 UINFO(
"Total refined %d links.", (
int)linksRefined.size());
6078 if(linksRefined.size())
6080 for(std::list<Link>::iterator
iter=linksRefined.begin();
iter!=linksRefined.end(); ++
iter)
6085 return (
int)linksRefined.size();
6093 UERROR(
"Adding new link can be done only in RGBD-SLAM mode.");
6098 UERROR(
"Memory is not initialized.");
6103 UERROR(
"Link's transform is null! (%d->%d type=%s)", link.
from(), link.
to(), link.
typeName().c_str());
6110 UERROR(
"Link's \"from id\" %d is not in working memory", link.
from());
6115 UERROR(
"Link's \"to id\" %d is not in working memory", link.
to());
6122 UERROR(
"Neither nodes %d or %d are in the local graph (size=%d). One of the 2 nodes should be in the local graph.", (
int)
_optimizedPoses.size(), link.
from(), link.
to());
6129 UERROR(
"Cannot add new link %d->%d to memory", link.
from(), link.
to());
6135 std::multimap<int, Link> links;
6139 if(poses.find(link.
from()) == poses.end())
6141 UERROR(
"Link's \"from id\" %d is not in the graph (size=%d)", link.
from(), (
int)poses.size());
6145 if(poses.find(link.
to()) == poses.end())
6147 UERROR(
"Link's \"to id\" %d is not in the graph (size=%d)", link.
to(), (
int)poses.size());
6155 msg =
uFormat(
"Rejecting edge %d->%d because graph optimization has failed!", link.
from(), link.
to());
6159 float maxLinearError = 0.0f;
6160 float maxLinearErrorRatio = 0.0f;
6161 float maxAngularError = 0.0f;
6162 float maxAngularErrorRatio = 0.0f;
6163 const Link * maxLinearLink = 0;
6164 const Link * maxAngularLink = 0;
6169 maxLinearErrorRatio,
6170 maxAngularErrorRatio,
6177 UINFO(
"Max optimization linear error = %f m (link %d->%d)", maxLinearError, maxLinearLink->
from(), maxLinearLink->
to());
6180 msg =
uFormat(
"Rejecting edge %d->%d because "
6181 "graph error is too large after optimization (%f m for edge %d->%d with ratio %f > std=%f m). "
6186 maxLinearLink->
from(),
6187 maxLinearLink->
to(),
6188 maxLinearErrorRatio,
6190 Parameters::kRGBDOptimizeMaxError().c_str(),
6195 UERROR(
"Huge optimization error detected!"
6196 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
6197 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
6198 maxLinearErrorRatio,
6199 maxLinearLink->
from(),
6200 maxLinearLink->
to(),
6201 maxLinearLink->
type(),
6204 Parameters::kRGBDOptimizeMaxError().c_str());
6207 else if(maxAngularLink)
6209 UINFO(
"Max optimization angular error = %f deg (link %d->%d)", maxAngularError*180.0
f/
M_PI, maxAngularLink->
from(), maxAngularLink->
to());
6212 msg =
uFormat(
"Rejecting edge %d->%d because "
6213 "graph error is too large after optimization (%f deg for edge %d->%d with ratio %f > std=%f deg). "
6217 maxAngularError*180.0f/
M_PI,
6218 maxAngularLink->
from(),
6219 maxAngularLink->
to(),
6220 maxAngularErrorRatio,
6222 Parameters::kRGBDOptimizeMaxError().c_str(),
6227 UERROR(
"Huge optimization error detected!"
6228 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
6229 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
6230 maxAngularErrorRatio,
6231 maxAngularLink->
from(),
6232 maxAngularLink->
to(),
6233 maxAngularLink->
type(),
6234 maxAngularError*180.0f/CV_PI,
6236 Parameters::kRGBDOptimizeMaxError().c_str());
6250 std::map<int, Transform>::iterator jter = poses.find(
iter->first);
6251 if(jter != poses.end())
6253 iter->second = jter->second;
6261 std::map<int, Transform> tmp;
6271 int oldestId = link.
from()>link.
to()?link.
to():link.
from();
6272 int newestId = link.
from()<link.
to()?link.
to():link.
from();
6276 UERROR(
"Link's id %d is not in working memory", oldestId);
6281 UERROR(
"Link's id %d is not in the optimized graph (_optimizedPoses=%d)", oldestId, (
int)
_optimizedPoses.size());
6286 UERROR(
"Adding link with %s=true in localization mode is not supported.", Parameters::kRGBDOptimizeFromGraphEnd().
c_str());
6293 UERROR(
"Link's id %d is not in the odometry cache (oldest=%d, newest=%d, %s=%d)",
6297 Parameters::kRGBDMaxOdomCacheSize().c_str(),
6302 UERROR(
"Link's id %d is not in the odometry cache (%s=%d).",
6304 Parameters::kRGBDMaxOdomCacheSize().
c_str(),
6316 constraints.insert(std::make_pair(link.
from(), link));
6317 for(std::multimap<int, Link>::iterator
iter=constraints.begin();
iter!=constraints.end(); ++
iter)
6320 if(iterPose !=
_optimizedPoses.end() && poses.find(iterPose->first) == poses.end())
6322 poses.insert(*iterPose);
6324 constraints.insert(std::make_pair(iterPose->first,
Link(iterPose->first, iterPose->first,
Link::kPosePrior, iterPose->second, cv::Mat::eye(6,6, CV_64FC1)*999999)));
6328 std::map<int, Transform> posesOut;
6329 std::multimap<int, Link> edgeConstraintsOut;
6333 std::map<int, Transform> optPoses =
_graphOptimizer->
optimize(poses.begin()->first, posesOut, edgeConstraintsOut);
6336 bool rejectLocalization =
false;
6337 if(optPoses.empty())
6339 UWARN(
"Optimization failed, rejecting localization!");
6340 rejectLocalization =
true;
6344 UINFO(
"Compute max graph errors...");
6345 float maxLinearError = 0.0f;
6346 float maxLinearErrorRatio = 0.0f;
6347 float maxAngularError = 0.0f;
6348 float maxAngularErrorRatio = 0.0f;
6349 const Link * maxLinearLink = 0;
6350 const Link * maxAngularLink = 0;
6354 maxLinearErrorRatio,
6355 maxAngularErrorRatio,
6361 if(maxLinearLink == 0 && maxAngularLink==0)
6363 UWARN(
"Could not compute graph errors! Wrong loop closures could be accepted!");
6368 UINFO(
"Max optimization linear error = %f m (link %d->%d, var=%f, ratio error/std=%f)", maxLinearError, maxLinearLink->
from(), maxLinearLink->
to(), maxLinearLink->
transVariance(), maxLinearError/
sqrt(maxLinearLink->
transVariance()));
6371 UWARN(
"Rejecting localization (%d <-> %d) in this "
6372 "iteration because a wrong loop closure has been "
6373 "detected after graph optimization, resulting in "
6374 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). The "
6375 "maximum error ratio parameter \"%s\" is %f of std deviation.",
6378 maxLinearErrorRatio,
6379 maxLinearLink->
from(),
6380 maxLinearLink->
to(),
6381 maxLinearLink->
type(),
6384 Parameters::kRGBDOptimizeMaxError().c_str(),
6386 rejectLocalization =
true;
6390 UERROR(
"Huge optimization error detected!"
6391 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
6392 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
6393 maxLinearErrorRatio,
6394 maxLinearLink->
from(),
6395 maxLinearLink->
to(),
6396 maxLinearLink->
type(),
6399 Parameters::kRGBDOptimizeMaxError().c_str());
6404 UINFO(
"Max optimization angular error = %f deg (link %d->%d, var=%f, ratio error/std=%f)", maxAngularError*180.0
f/CV_PI, maxAngularLink->
from(), maxAngularLink->
to(), maxAngularLink->
rotVariance(), maxAngularError/
sqrt(maxAngularLink->
rotVariance()));
6407 UWARN(
"Rejecting localization (%d <-> %d) in this "
6408 "iteration because a wrong loop closure has been "
6409 "detected after graph optimization, resulting in "
6410 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f deg, stddev=%f). The "
6411 "maximum error ratio parameter \"%s\" is %f of std deviation.",
6414 maxAngularErrorRatio,
6415 maxAngularLink->
from(),
6416 maxAngularLink->
to(),
6417 maxAngularLink->
type(),
6418 maxAngularError*180.0f/CV_PI,
6420 Parameters::kRGBDOptimizeMaxError().c_str(),
6422 rejectLocalization =
true;
6426 UERROR(
"Huge optimization error detected!"
6427 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
6428 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
6429 maxAngularErrorRatio,
6430 maxAngularLink->
from(),
6431 maxAngularLink->
to(),
6432 maxAngularLink->
type(),
6433 maxAngularError*180.0f/CV_PI,
6435 Parameters::kRGBDOptimizeMaxError().c_str());
6440 if(!rejectLocalization)
6443 Transform newT = newOptPoseInv * optPoses.at(link.
to());
6444 Link linkTmp = link;
6446 if(oldestId == link.
from())
6473 cv::Mat information = covariance.inv();
6477 if(odomMaxInf.size() == 6)
6479 for(
int i=0;
i<6; ++
i)
6481 if(information.at<
double>(
i,
i) > odomMaxInf[
i])
6483 information.at<
double>(
i,
i) = odomMaxInf[
i];
6503 UWARN(
"%s=0, so cannot republish the %d requested nodes.", Parameters::kRtabmapMaxRepublished().
c_str(), (
int)ids.size());
6507 UWARN(
"%s=false, so cannot republish the %d requested nodes.", Parameters::kRtabmapPublishLastSignature().
c_str(), (
int)ids.size());
6513 UINFO(
"status=%d", status);
6535 UINFO(
"Planning a path to node %d (global=%d)", targetNode, global?1:0);
6539 UINFO(
"Planning a path to landmark %d (global=%d)", -targetNode, global?1:0);
6544 UWARN(
"A path can only be computed in RGBD-SLAM mode");
6555 int currentNode = 0;
6560 UWARN(
"Working memory is empty... cannot compute a path");
6569 UWARN(
"Last localization pose is null or optimized graph is empty... cannot compute a path");
6582 if(currentNode && targetNode)
6607 if(!
_path.empty() && !
path.empty() &&
path.rbegin()->first < 0)
6609 transformToLandmark =
_path.back().second.inverse() *
t *
path.rbegin()->second;
6612 else if(currentNode == 0)
6614 UWARN(
"We should be localized before planning.");
6619 if(
_path.size() == 0)
6622 UWARN(
"Cannot compute a path!");
6627 UINFO(
"Path generated! Size=%d", (
int)
_path.size());
6630 std::stringstream
stream;
6631 for(
unsigned int i=0;
i<
_path.size(); ++
i)
6644 std::string goalStr =
uFormat(
"GOAL:%d", targetNode);
6657 std::map<int, std::string>::iterator
iter =
labels.find(targetNode);
6660 goalStr = std::string(
"GOAL:")+
labels.at(targetNode);
6663 setUserData(0, cv::Mat(1,
int(goalStr.size()+1), CV_8SC1, (
void *)goalStr.c_str()).clone());
6679 if(tolerance < 0.0
f)
6684 std::list<std::pair<int, Transform> > pathPoses;
6688 UWARN(
"This method can only be used in RGBD-SLAM mode");
6695 std::multimap<int, int> links;
6700 for(std::map<int, Link>::const_iterator jter=
s->getLinks().begin(); jter!=
s->getLinks().end(); ++jter)
6703 if(jter->second.from() != jter->second.to() &&
uContains(
nodes, jter->second.to()))
6705 links.insert(std::make_pair(jter->second.from(), jter->second.to()));
6710 UINFO(
"Time getting links = %fs",
timer.ticks());
6712 int currentNode = 0;
6717 UWARN(
"Working memory is empty... cannot compute a path");
6726 UWARN(
"Last localization pose is null... cannot compute a path");
6744 nearestId = currentNode;
6750 UINFO(
"Nearest node found=%d ,%fs", nearestId,
timer.ticks());
6753 if(tolerance != 0.0
f && targetPose.
getDistance(
nodes.at(nearestId)) > tolerance)
6755 UWARN(
"Cannot plan farther than %f m from the graph! (distance=%f m from node %d)",
6760 UINFO(
"Computing path from location %d to %d", currentNode, nearestId);
6765 if(
_path.size() == 0)
6767 UWARN(
"Cannot compute a path!");
6771 UINFO(
"Path generated! Size=%d", (
int)
_path.size());
6774 std::stringstream
stream;
6775 for(
unsigned int i=0;
i<
_path.size(); ++
i)
6797 UWARN(
"Nearest node not found in graph (size=%d) for pose %s", (
int)
nodes.size(), targetPose.
prettyPrint().c_str());
6805 std::vector<std::pair<int, Transform> > poses;
6816 poses[oi++] = *
iter;
6830 std::vector<int> ids;
6841 ids[oi++] =
iter->first;
6867 UWARN(
"This method can on be used in RGBD-SLAM mode!");
6889 std::multimap<int, Link> links = currentIndexS->
getLinks();
6890 bool latestVirtualLinkFound =
false;
6891 for(std::multimap<int, Link>::reverse_iterator
iter=links.rbegin();
iter!=links.rend(); ++
iter)
6895 if(latestVirtualLinkFound)
6901 latestVirtualLinkFound =
true;
6907 float distanceSoFar = 0.0f;
6948 UERROR(
"Last node is null in memory or not in optimized poses. Aborting the plan...");
6958 UERROR(
"Last localization pose is null. Aborting the plan...");
6965 int goalId =
_path.back().first;
6972 UINFO(
"Goal %d reached!", goalId);
6981 float distanceFromCurrentNode = 0.0f;
6982 bool sameGoalIndex =
false;
7013 UINFO(
"Updated current goal from %d to %d (%d/%d)",
7019 sameGoalIndex =
true;
7023 unsigned int nearestNodeIndex = 0;
7025 bool sameCurrentIndex =
false;
7036 nearestNodeIndex =
i;
7042 UERROR(
"The nearest pose on the path not found! Aborting the plan...");
7056 sameCurrentIndex =
true;
7059 bool isStuck =
false;
7062 float distanceToCurrentGoal = 0.0f;
7077 if(distanceToCurrentGoal > 0.0
f)
7098 UWARN(
"Current goal %d not reached since %d iterations (\"RGBD/PlanStuckIterations\"=%d), mark that node as unreachable.",
7111 UERROR(
"No upcoming nodes on the path are reachable! Aborting the plan...");
7128 UDEBUG(
"Creating global scan map (if scans are available)");
7131 std::vector<int> scanIndices;
7132 std::map<int, Transform> scanViewpoints;
7136 if(!
data.laserScanCompressed().empty())
7139 data.uncompressDataConst(0, 0, &scan, 0, 0, 0, 0);
7153 UWARN(
"Incompatible scan formats (%s vs %s), cannot create global scan map.",
7163 UDEBUG(
"Ignored %d (scan is empty), pose still added.",
iter->first);
7169 UDEBUG(
"Ignored %d (no scan), pose still added.",
iter->first);
7175 float voxelSize = 0.0f;
7177 float normalRadius = 0.0f;
7182 if(voxelSize > 0.0
f)
7197 UINFO(
"Global scan map has been assembled (size=%d points, %d poses) "
7198 "for proximity detection (only in localization mode %s=false and with %s=true)",
7201 Parameters::kMemIncrementalMemory().c_str(),
7202 Parameters::kRGBDProximityGlobalScanMap().c_str());
7209 UWARN(
"Saving %s/rtabmap_global_scan_map.pcd (only saved when logger level is debug)",
_wDir.c_str());
7211 pcl::io::savePCDFile(
_wDir+
"/rtabmap_global_scan_map.pcd", *cloud2);
7215 UWARN(
"%s is enabled and logger is debug, but %s is not set, cannot save global scan map for debugging.",
7216 Parameters::kRGBDProximityGlobalScanMap().
c_str(), Parameters::kRtabmapWorkingDirectory().
c_str());