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 rejectedLoopClosure =
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 rejectedLoopClosure =
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 rejectedLoopClosure =
false;
2187 timeHypothesesValidation =
timer.ticks();
2188 ULOGGER_INFO(
"timeHypothesesValidation=%fs",timeHypothesesValidation);
2195 rejectedLoopClosure =
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 rejectedLoopClosure =
transform.isNull();
3065 if(rejectedLoopClosure)
3067 UWARN(
"Rejected loop closure %d -> %d: %s",
3072 rejectedLoopClosure =
true;
3073 UWARN(
"Rejected localization %d -> %d because distance to map (%fm) is over %s=%fm.",
3081 if(!rejectedLoopClosure)
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(!rejectedLoopClosure)
3096 if(rejectedLoopClosure)
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 rejectedLoopClosure =
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 delayedLocalization =
false;
3187 UDEBUG(
"Last prox: %d", lastProximitySpaceClosureId);
3192 UDEBUG(
"Prox Time: %d", proximityDetectionsInTimeFound);
3193 UDEBUG(
"Landmarks: %d", (
int)landmarksDetected.size());
3194 UDEBUG(
"Retrieved: %d", (
int)signaturesRetrieved.size());
3200 lastProximitySpaceClosureId>0 ||
3204 proximityDetectionsInTimeFound>0 ||
3205 !landmarksDetected.empty() ||
3206 signaturesRetrieved.size())
3211 !landmarksDetected.empty()))
3220 for(std::map<
int, std::set<int> >::
iterator iter=landmarksDetected.begin();
iter!=landmarksDetected.end(); ++
iter)
3225 localizationLinks.insert(std::make_pair(
iter->first, signature->
getLandmarks().at(
iter->first)));
3230 bool allLocalizationLinksInGraph = !localizationLinks.empty();
3231 for(std::multimap<int, Link>::iterator
iter=localizationLinks.begin();
iter!=localizationLinks.end(); ++
iter)
3235 allLocalizationLinksInGraph =
false;
3245 signaturesRetrieved.empty() &&
3246 !localizationLinks.empty() &&
3247 allLocalizationLinksInGraph)
3264 constraints.insert(selfLinks.begin(), selfLinks.end());
3265 for(std::multimap<int, Link>::iterator
iter=localizationLinks.begin();
iter!=localizationLinks.end(); ++
iter)
3267 constraints.insert(std::make_pair(
iter->second.from(),
iter->second));
3270 for(std::multimap<int, Link>::iterator
iter=constraints.begin();
iter!=constraints.end(); ++
iter)
3273 if(iterPose !=
_optimizedPoses.end() && poses.find(iterPose->first) == poses.end())
3275 poses.insert(*iterPose);
3277 constraints.insert(std::make_pair(iterPose->first,
Link(iterPose->first, iterPose->first,
Link::kPosePrior, iterPose->second, priorInfMat)));
3280 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());
3283 std::map<int, Transform> posesOut;
3284 std::multimap<int, Link> edgeConstraintsOut;
3286 UDEBUG(
"priorsIgnored was %s", priorsIgnored?
"true":
"false");
3292 for(std::map<int, Transform>::iterator
iter=posesOut.begin();
iter!=posesOut.end(); ++
iter)
3294 UDEBUG(
"Pose %d %s",
iter->first,
iter->second.prettyPrint().c_str());
3297 cv::Mat locOptCovariance;
3298 std::map<int, Transform> optPoses;
3299 if(!posesOut.empty() &&
3302 optPoses =
_graphOptimizer->
optimize(posesOut.begin()->first, posesOut, edgeConstraintsOut, locOptCovariance);
3306 UERROR(
"Invalid localization constraints");
3309 for(std::map<int, Transform>::iterator
iter=optPoses.begin();
iter!=optPoses.end(); ++
iter)
3311 UDEBUG(
"Opt %d %s",
iter->first,
iter->second.prettyPrint().c_str());
3314 if(optPoses.empty())
3316 UWARN(
"Optimization failed, rejecting localization!");
3317 rejectLocalization =
true;
3321 UINFO(
"Compute max graph errors...");
3322 const Link * maxLinearLink = 0;
3323 const Link * maxAngularLink = 0;
3327 maxLinearErrorRatio,
3328 maxAngularErrorRatio,
3334 if(maxLinearLink == 0 && maxAngularLink==0)
3336 UWARN(
"Could not compute graph errors! Rejecting localization!");
3337 rejectLocalization =
true;
3342 UINFO(
"Max optimization linear error = %f m (link %d->%d, var=%f, ratio error/std=%f, thr=%f)",
3344 maxLinearLink->
from(),
3345 maxLinearLink->
to(),
3351 UWARN(
"Rejecting localization (%d <-> %d) in this "
3352 "iteration because a wrong loop closure has been "
3353 "detected after graph optimization, resulting in "
3354 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). The "
3355 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3356 localizationLinks.rbegin()->second.from(),
3357 localizationLinks.rbegin()->second.to(),
3358 maxLinearErrorRatio,
3359 maxLinearLink->
from(),
3360 maxLinearLink->
to(),
3361 maxLinearLink->
type(),
3364 Parameters::kRGBDOptimizeMaxError().c_str(),
3366 rejectLocalization =
true;
3370 UERROR(
"Huge optimization error detected!"
3371 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3372 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3373 maxLinearErrorRatio,
3374 maxLinearLink->
from(),
3375 maxLinearLink->
to(),
3376 maxLinearLink->
type(),
3379 Parameters::kRGBDOptimizeMaxError().c_str());
3384 UINFO(
"Max optimization angular error = %f deg (link %d->%d, var=%f, ratio error/std=%f, thr=%f)",
3385 maxAngularError*180.0
f/CV_PI,
3386 maxAngularLink->
from(),
3387 maxAngularLink->
to(),
3393 UWARN(
"Rejecting localization (%d <-> %d) in this "
3394 "iteration because a wrong loop closure has been "
3395 "detected after graph optimization, resulting in "
3396 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f deg, stddev=%f). The "
3397 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3398 localizationLinks.rbegin()->second.from(),
3399 localizationLinks.rbegin()->second.to(),
3400 maxAngularErrorRatio,
3401 maxAngularLink->
from(),
3402 maxAngularLink->
to(),
3403 maxAngularLink->
type(),
3404 maxAngularError*180.0f/CV_PI,
3406 Parameters::kRGBDOptimizeMaxError().c_str(),
3408 rejectLocalization =
true;
3412 UERROR(
"Huge optimization error detected!"
3413 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3414 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3415 maxAngularErrorRatio,
3416 maxAngularLink->
from(),
3417 maxAngularLink->
to(),
3418 maxAngularLink->
type(),
3419 maxAngularError*180.0f/CV_PI,
3421 Parameters::kRGBDOptimizeMaxError().c_str());
3426 bool hasGlobalLoopClosuresOrLandmarks =
false;
3432 for(std::multimap<int, Link>::iterator
iter=constraints.begin();
iter!=constraints.end() && !hasGlobalLoopClosuresOrLandmarks; ++
iter)
3434 hasGlobalLoopClosuresOrLandmarks =
3438 if(hasGlobalLoopClosuresOrLandmarks && !localizationLinks.empty())
3440 rejectLocalization =
false;
3441 UWARN(
"Global and loop closures seem not tallying together, try again to optimize without local loop closures...");
3443 UDEBUG(
"priorsIgnored was %s", priorsIgnored?
"true":
"false");
3448 if(!posesOut.empty() &&
3451 optPoses =
_graphOptimizer->
optimize(posesOut.begin()->first, posesOut, edgeConstraintsOut, locOptCovariance);
3455 UERROR(
"Invalid localization constraints");
3458 for(std::map<int, Transform>::iterator
iter=optPoses.begin();
iter!=optPoses.end(); ++
iter)
3460 UDEBUG(
"Opt2 %d %s",
iter->first,
iter->second.prettyPrint().c_str());
3463 if(optPoses.empty())
3465 UWARN(
"Optimization failed, rejecting localization!");
3466 rejectLocalization =
true;
3470 UINFO(
"Compute max graph errors...");
3471 const Link * maxLinearLink = 0;
3472 const Link * maxAngularLink = 0;
3476 maxLinearErrorRatio,
3477 maxAngularErrorRatio,
3483 if(maxLinearLink == 0 && maxAngularLink==0)
3485 UWARN(
"Could not compute graph errors! Rejecting localization!");
3486 rejectLocalization =
true;
3491 UINFO(
"Max optimization linear error = %f m (link %d->%d, var=%f, ratio error/std=%f, thr=%f)",
3493 maxLinearLink->
from(),
3494 maxLinearLink->
to(),
3500 UWARN(
"Rejecting localization (%d <-> %d) in this "
3501 "iteration because a wrong loop closure has been "
3502 "detected after graph optimization, resulting in "
3503 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). The "
3504 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3505 localizationLinks.rbegin()->second.from(),
3506 localizationLinks.rbegin()->second.to(),
3507 maxLinearErrorRatio,
3508 maxLinearLink->
from(),
3509 maxLinearLink->
to(),
3510 maxLinearLink->
type(),
3513 Parameters::kRGBDOptimizeMaxError().c_str(),
3515 rejectLocalization =
true;
3519 UERROR(
"Huge optimization error detected!"
3520 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3521 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3522 maxLinearErrorRatio,
3523 maxLinearLink->
from(),
3524 maxLinearLink->
to(),
3525 maxLinearLink->
type(),
3528 Parameters::kRGBDOptimizeMaxError().c_str());
3533 UINFO(
"Max optimization angular error = %f deg (link %d->%d, var=%f, ratio error/std=%f, thr=%f)",
3534 maxAngularError*180.0
f/CV_PI,
3535 maxAngularLink->
from(),
3536 maxAngularLink->
to(),
3542 UWARN(
"Rejecting localization (%d <-> %d) in this "
3543 "iteration because a wrong loop closure has been "
3544 "detected after graph optimization, resulting in "
3545 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f deg, stddev=%f). The "
3546 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3547 localizationLinks.rbegin()->second.from(),
3548 localizationLinks.rbegin()->second.to(),
3549 maxAngularErrorRatio,
3550 maxAngularLink->
from(),
3551 maxAngularLink->
to(),
3552 maxAngularLink->
type(),
3553 maxAngularError*180.0f/CV_PI,
3555 Parameters::kRGBDOptimizeMaxError().c_str(),
3557 rejectLocalization =
true;
3561 UERROR(
"Huge optimization error detected!"
3562 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3563 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3564 maxAngularErrorRatio,
3565 maxAngularLink->
from(),
3566 maxAngularLink->
to(),
3567 maxAngularLink->
type(),
3568 maxAngularError*180.0f/CV_PI,
3570 Parameters::kRGBDOptimizeMaxError().c_str());
3577 if(!rejectLocalization)
3579 if(hasGlobalLoopClosuresOrLandmarks)
3587 UWARN(
"Successfully optimized without local loop closures! Clear them from local odometry cache. %ld/%ld have been removed.",
3592 UWARN(
"Successfully optimized without local loop closures!");
3597 bool hadAlreadyLocalizationLinks =
false;
3608 hadAlreadyLocalizationLinks =
true;
3616 for(std::multimap<int, Link>::iterator
iter=localizationLinks.begin();
iter!=localizationLinks.end(); ++
iter)
3621 UDEBUG(
"Adding new odom cache constraint %d->%d (%s)",
3622 iter->second.from(),
iter->second.to(),
iter->second.transform().prettyPrint().c_str());
3629 UDEBUG(
"Adjusted localization link %d->%d after optimization",
iter->second.from(),
iter->second.to());
3630 UDEBUG(
"from %s",
iter->second.transform().prettyPrint().c_str());
3632 iter->second.setTransform(newT);
3647 UINFO(
"Update localization");
3655 Transform u = signature->
getPose() * localizationLinks.rbegin()->second.transform();
3660 int loopId = localizationLinks.rbegin()->first;
3666 landmarkId = loopId;
3667 UASSERT(landmarksDetected.find(landmarkId) != landmarksDetected.end() &&
3668 !landmarksDetected.at(landmarkId).empty());
3669 loopId = *landmarksDetected.at(landmarkId).begin();
3676 if(iterGravityLoop!=loopS->
getLinks().end() &&
3677 iterGravitySign!=signature->
getLinks().end())
3682 iterGravityLoop->second.transform().getEulerAngles(
roll,
pitch,
yaw);
3691 iterGravityLoop->second.transform().getEulerAngles(
roll,
pitch,
yaw);
3695 Transform error =
transform.rotation().inverse() * iterGravitySign->second.transform().rotation().inverse() * targetRotation;
3699 else if(iterGravityLoop!=loopS->
getLinks().end() ||
3700 iterGravitySign!=signature->
getLinks().end())
3702 UWARN(
"Gravity link not found for %d or %d, localization won't be corrected with gravity.", loopId, signature->
id());
3713 iter->second = mapCorrectionInv * up *
iter->second;
3719 Transform newPose =
_optimizedPoses.at(localizationLinks.rbegin()->first) * localizationLinks.rbegin()->second.transform().inverse();
3724 newPose = newPose.
to3DoF();
3731 if(iterGravitySign!=signature->
getLinks().end())
3736 UDEBUG(
"Gravity link = %s", iterGravitySign->second.transform().prettyPrint().c_str());
3740 Transform error =
transform.rotation().inverse() * iterGravitySign->second.transform().rotation().inverse() * targetRotation;
3743 iterGravitySign->second.transform().getEulerAngles(
roll,
pitch, tmp1);
3748 else if(iterGravitySign!=signature->
getLinks().end())
3750 UWARN(
"Gravity link not found for %d, localization won't be corrected with gravity.", signature->
id());
3755 _localizationCovariance = locOptCovariance.empty()?localizationLinks.rbegin()->second.infMatrix().inv():locOptCovariance;
3759 UWARN(
"Localization was good, but waiting for another one to be more accurate (%s>0)", Parameters::kRGBDMaxOdomCacheSize().
c_str());
3760 delayedLocalization =
true;
3761 rejectLocalization =
true;
3766 if(rejectLocalization)
3769 lastProximitySpaceClosureId = 0;
3770 rejectedLoopClosure =
true;
3775 UINFO(
"Update map correction");
3781 UWARN(
"Optimization: clearing guess poses as %s has changed state, now %s",
3787 std::multimap<int, Link> constraints;
3789 optimizeCurrentMap(signature->
id(),
false, poses, covariance, &constraints, &optimizationError, &optimizationIterations);
3793 bool updateConstraints =
true;
3796 UWARN(
"Graph optimization failed! Rejecting last loop closures added.");
3797 for(std::list<std::pair<int, int> >::
iterator iter=loopClosureLinksAdded.begin();
iter!=loopClosureLinksAdded.end(); ++
iter)
3800 UWARN(
"Loop closure %d->%d rejected!",
iter->first,
iter->second);
3802 updateConstraints =
false;
3804 lastProximitySpaceClosureId = 0;
3805 rejectedLoopClosure =
true;
3808 loopClosureLinksAdded.size() &&
3809 optimizationIterations > 0 &&
3812 UINFO(
"Compute max graph errors...");
3813 const Link * maxLinearLink = 0;
3814 const Link * maxAngularLink = 0;
3818 maxLinearErrorRatio,
3819 maxAngularErrorRatio,
3824 if(maxLinearLink == 0 && maxAngularLink==0)
3826 UWARN(
"Could not compute graph errors! Wrong loop closures could be accepted!");
3829 bool reject =
false;
3832 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()));
3835 UWARN(
"Rejecting all added loop closures (%d, first is %d <-> %d) in this "
3836 "iteration because a wrong loop closure has been "
3837 "detected after graph optimization, resulting in "
3838 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). The "
3839 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3840 (
int)loopClosureLinksAdded.size(),
3841 loopClosureLinksAdded.front().first,
3842 loopClosureLinksAdded.front().second,
3843 maxLinearErrorRatio,
3844 maxLinearLink->
from(),
3845 maxLinearLink->
to(),
3846 maxLinearLink->
type(),
3849 Parameters::kRGBDOptimizeMaxError().c_str(),
3855 UERROR(
"Huge optimization error detected!"
3856 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3857 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3858 maxLinearErrorRatio,
3859 maxLinearLink->
from(),
3860 maxLinearLink->
to(),
3861 maxLinearLink->
type(),
3864 Parameters::kRGBDOptimizeMaxError().c_str());
3869 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()));
3872 UWARN(
"Rejecting all added loop closures (%d, first is %d <-> %d) in this "
3873 "iteration because a wrong loop closure has been "
3874 "detected after graph optimization, resulting in "
3875 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f deg, stddev=%f). The "
3876 "maximum error ratio parameter \"%s\" is %f of std deviation.",
3877 (
int)loopClosureLinksAdded.size(),
3878 loopClosureLinksAdded.front().first,
3879 loopClosureLinksAdded.front().second,
3880 maxAngularErrorRatio,
3881 maxAngularLink->
from(),
3882 maxAngularLink->
to(),
3883 maxAngularLink->
type(),
3884 maxAngularError*180.0f/CV_PI,
3886 Parameters::kRGBDOptimizeMaxError().c_str(),
3892 UERROR(
"Huge optimization error detected!"
3893 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
3894 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
3895 maxAngularErrorRatio,
3896 maxAngularLink->
from(),
3897 maxAngularLink->
to(),
3898 maxAngularLink->
type(),
3899 maxAngularError*180.0f/CV_PI,
3901 Parameters::kRGBDOptimizeMaxError().c_str());
3907 for(std::list<std::pair<int, int> >::
iterator iter=loopClosureLinksAdded.begin();
iter!=loopClosureLinksAdded.end(); ++
iter)
3910 UWARN(
"Loop closure %d->%d rejected!",
iter->first,
iter->second);
3912 updateConstraints =
false;
3914 lastProximitySpaceClosureId = 0;
3915 rejectedLoopClosure =
true;
3919 if(updateConstraints)
3921 UINFO(
"Updated local map (old size=%d, new size=%d)", (
int)
_optimizedPoses.size(), (
int)poses.size());
3950 bool hasPrior = signature->
hasLink(signature->
id());
3969 if(newLocId==0 && !landmarksDetected.empty())
3974 if(
iter->second.size() && *
iter->second.begin()!=signature->
id())
3981 timeMapOptimization =
timer.ticks();
3982 ULOGGER_INFO(
"timeMapOptimization=%fs", timeMapOptimization);
3988 int dictionarySize = 0;
3989 int refWordsCount = 0;
3990 int refUniqueWordsCount = 0;
3991 int lcHypothesisReactivated = 0;
3997 lcHypothesisReactivated = sLoop->
isSaved()?1.0f:0.0f;
4000 refWordsCount = (
int)signature->
getWords().size();
4054 statistics_.
addStatistic(Statistics::kLoopLandmark_detected(), landmarksDetected.empty()?0:-landmarksDetected.begin()->first);
4055 statistics_.
addStatistic(Statistics::kLoopLandmark_detected_node_ref(), landmarksDetected.empty() || landmarksDetected.begin()->second.empty()?0:*landmarksDetected.begin()->second.begin());
4057 statistics_.
addStatistic(Statistics::kLoopVisual_inliers_distribution(), loopClosureVisualInliersDistribution);
4060 statistics_.
addStatistic(Statistics::kProximitySpace_detections_added_visually(), proximityDetectionsAddedVisually);
4061 statistics_.
addStatistic(Statistics::kProximitySpace_detections_added_icp_multi(), proximityDetectionsAddedByICPMulti);
4062 statistics_.
addStatistic(Statistics::kProximitySpace_detections_added_icp_global(), proximityDetectionsAddedByICPGlobal);
4076 if(
_loopClosureHypothesis.first || lastProximitySpaceClosureId || (!rejectedLoopClosure && !landmarksDetected.empty()))
4082 std::multimap<int, Link>::const_iterator loopIter = sLoop->
getLinks().find(signature->
id());
4084 UINFO(
"Set loop closure transform = %s", loopIter->second.transform().prettyPrint().c_str());
4093 Transform error = loopIter->second.transform().inverse() * transformGT;
4157 statistics_.
addStatistic(Statistics::kTimingProximity_by_space_visual(), timeProximityBySpaceVisualDetection*1000);
4185 if(distanceToClosestNodeInTheGraph>0.0)
4195 long estimatedMemoryUsage =
sizeof(
Rtabmap);
4196 estimatedMemoryUsage +=
_optimizedPoses.size() * (
sizeof(
int) +
sizeof(
Transform) + 12 *
sizeof(
float) +
sizeof(std::map<int, Transform>::iterator)) +
sizeof(std::map<int, Transform>);
4197 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>);
4200 estimatedMemoryUsage +=
_parameters.size()*(
sizeof(std::string)*2+
sizeof(ParametersMap::iterator)) +
sizeof(
ParametersMap);
4230 timeStatsCreation =
timer.ticks();
4231 ULOGGER_INFO(
"Time creating stats = %f...", timeStatsCreation);
4234 Signature lastSignatureData = *signature;
4259 if(signatureRemoved)
4261 signaturesRemoved.push_back(signatureRemoved);
4268 if(signatureRemoved != lastSignatureData.
id())
4273 (landmarksDetected.empty() || rejectedLoopClosure) &&
4276 UWARN(
"Ignoring location %d because a global loop closure is required before starting a new map!",
4278 signaturesRemoved.push_back(signature->
id());
4285 UWARN(
"Ignoring location %d because a good signature (with enough features or with a landmark detected) is required before starting a new map!",
4287 signaturesRemoved.push_back(signature->
id());
4290 else if((smallDisplacement || tooFastMovement) &&
4292 lastProximitySpaceClosureId == 0 &&
4293 (rejectedLoopClosure || landmarksDetected.empty()) &&
4297 UINFO(
"Ignoring location %d because the displacement is too small! (d=%f a=%f)",
4300 signaturesRemoved.push_back(signature->
id());
4309 (smallDisplacement || tooFastMovement) &&
4311 lastProximitySpaceClosureId == 0 &&
4312 !delayedLocalization &&
4313 (rejectedLoopClosure || landmarksDetected.empty()))
4318 if(
iter->second.from() == signatureRemoved ||
iter->second.to() == signatureRemoved)
4332 timeMemoryCleanup =
timer.ticks();
4333 ULOGGER_INFO(
"timeMemoryCleanup = %fs... %d signatures removed", timeMemoryCleanup, (
int)signaturesRemoved.size());
4345 double totalTime = timerTotal.
ticks();
4346 ULOGGER_INFO(
"Total time processing = %fs...", totalTime);
4352 std::list<int> transferred =
_memory->
forget(immunizedLocations);
4353 signaturesRemoved.insert(signaturesRemoved.end(), transferred.begin(), transferred.end());
4380 UDEBUG(
"Refresh local map from %d",
id);
4387 UDEBUG(
"Refresh local map from %d",
id);
4401 UDEBUG(
"Refresh local map from %d",
id);
4412 if(signaturesRemoved.size() == 1 && signaturesRemoved.front() == lastSignatureData.
id())
4414 int lastId = signaturesRemoved.front();
4415 UDEBUG(
"Detected that only last signature has been removed (lastId=%d)", lastId);
4419 if(
iter->second.to() !=
iter->second.from())
4438 UDEBUG(
"Removed %d from local map",
iter->first);
4444 UWARN(
"optimized poses have been modified, clearing global scan map...");
4470 UDEBUG(
"Optimized poses cleared!");
4485 timeRealTimeLimitReachedProcess =
timer.ticks();
4486 ULOGGER_INFO(
"Time limit reached processing = %f...", timeRealTimeLimitReachedProcess);
4491 int localGraphSize = 0;
4513 std::map<int, Transform> poses;
4514 std::multimap<int, Link> constraints;
4532 std::multimap<int, int> missingIds;
4538 missingIds.insert(std::make_pair(-1, tmpId));
4549 for(std::map<int, int>::iterator
iter=ids.begin();
iter!=ids.end(); ++
iter)
4551 if(
iter->first != loopId &&
4554 missingIds.insert(std::make_pair(
iter->second,
iter->first));
4563 if(ids.find(*
iter) == ids.end())
4577 std::stringstream
stream;
4587 UWARN(
"Republishing data of requested node(s) %s(%s=%d)",
4589 Parameters::kRtabmapMaxRepublished().c_str(),
4595 localGraphSize = (
int)poses.size();
4596 if(!lastSignatureLocalizedPose.
isNull())
4598 poses.insert(std::make_pair(lastSignatureData.
id(), lastSignatureLocalizedPose));
4612 UDEBUG(
"Computing RMSE...");
4613 float translational_rmse = 0.0f;
4614 float translational_mean = 0.0f;
4615 float translational_median = 0.0f;
4616 float translational_std = 0.0f;
4617 float translational_min = 0.0f;
4618 float translational_max = 0.0f;
4619 float rotational_rmse = 0.0f;
4620 float rotational_mean = 0.0f;
4621 float rotational_median = 0.0f;
4622 float rotational_std = 0.0f;
4623 float rotational_min = 0.0f;
4624 float rotational_max = 0.0f;
4631 translational_median,
4654 UDEBUG(
"Computing RMSE...done!");
4657 std::vector<int> ids;
4661 ids.push_back(*
iter);
4665 ids.push_back(
iter->first);
4668 UDEBUG(
"wmState=%d", (
int)ids.size());
4678 UDEBUG(
"Empty trash...");
4686 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",
4690 timeLikelihoodCalculation,
4691 timePosteriorCalculation,
4692 timeHypothesesCreation,
4693 timeHypothesesValidation,
4694 timeRealTimeLimitReachedProcess,
4706 timeRetrievalDbAccess,
4707 timeAddLoopClosureLink,
4709 timeNeighborLinkRefining,
4710 timeProximityByTimeDetection,
4711 timeProximityBySpaceDetection,
4712 timeMapOptimization);
4713 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",
4716 (
int)signaturesRemoved.size(),
4721 rejectedLoopClosure?1:0,
4724 int(signaturesRetrieved.size()),
4725 lcHypothesisReactivated,
4726 refUniqueWordsCount,
4730 rehearsalMaxId>0?1:0,
4748 fprintf(
_foutInt,
"%s", logI.c_str());
4751 UINFO(
"Time logging = %f...",
timer.ticks());
4754 timeFinalizingStatistics =
timer.ticks();
4755 UDEBUG(
"End process, timeFinalizingStatistics=%fs", timeFinalizingStatistics);
4771 ULOGGER_WARN(
"maxTimeAllowed < 0, then setting it to 0 (inf).");
4783 if(maxMemoryAllowed < 0)
4785 ULOGGER_WARN(
"maxMemoryAllowed < 0, then setting it to 0 (inf).");
4800 UWARN(
"Working directory has been changed from \"%s\" with \"%s\", new log files will be created.",
4807 else if(
path.empty())
4823 bool linksRemoved =
false;
4824 for(std::multimap<int, Link>::iterator
iter = links.begin();
iter!=links.end(); ++
iter)
4843 linksRemoved =
true;
4854 UINFO(
"Update graph");
4856 std::multimap<int, Link> constraints;
4862 UWARN(
"Graph optimization failed after removing loop closure links from last location!");
4866 UINFO(
"Updated local map (old size=%d, new size=%d)", (
int)
_optimizedPoses.size(), (
int)poses.size());
4885 UINFO(
"Update graph");
4891 if(
iter->second.from() == lastId ||
iter->second.to() == lastId)
4907 std::multimap<int, Link> constraints;
4913 UWARN(
"Graph optimization failed after deleting the last location!");
4939 UERROR(
"Working directory not set.");
4952 int maxNearestNeighbors,
4957 std::map<int, Transform> poses;
4965 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
4971 std::map<int, float> foundIds;
4981 float radiusSqrd = radius * radius;
4984 if(
iter->first != fromId)
4986 if(stm.find(
iter->first) == stm.end() &&
4988 (radiusSqrd==0 || foundIds.at(
iter->first) <= radiusSqrd))
4990 (*cloud)[oi] = pcl::PointXYZ(
iter->second.x(),
iter->second.y(),
iter->second.z());
4991 ids[oi++] =
iter->first;
5013 pcl::CropBox<pcl::PointXYZ> cropbox;
5014 cropbox.setInputCloud(cloud);
5015 cropbox.setMin(Eigen::Vector4f(-1, -radius, -999999, 0));
5016 cropbox.setMax(Eigen::Vector4f(radius, radius, 999999, 0));
5017 cropbox.setRotation(Eigen::Vector3f(
roll,
pitch,
yaw));
5018 cropbox.setTranslation(Eigen::Vector3f(
x,
y,
z));
5020 pcl::IndicesPtr
indices(
new std::vector<int>());
5031 pcl::search::KdTree<pcl::PointXYZ>::Ptr kdTree(
new pcl::search::KdTree<pcl::PointXYZ>);
5032 kdTree->setInputCloud(cloud,
indices);
5033 std::vector<int>
ind;
5034 std::vector<float>
dist;
5035 pcl::PointXYZ pt(fromT.
x(), fromT.
y(), fromT.
z());
5036 kdTree->radiusSearch(pt, radius,
ind,
dist, maxNearestNeighbors);
5038 for(
unsigned int i=0;
i<
ind.size(); ++
i)
5045 poses.insert(std::make_pair(ids[
ind[
i]], tmp));
5066 std::map<int, std::map<int, Transform> >
Rtabmap::getPaths(
const std::map<int, Transform> & posesIn,
const Transform & target,
int maxGraphDepth)
const
5068 std::map<int, std::map<int, Transform> > paths;
5069 std::set<int> nodesSet;
5070 std::map<int, Transform> poses;
5071 for(std::map<int, Transform>::const_iterator
iter=posesIn.lower_bound(1);
iter!=posesIn.end(); ++
iter)
5073 nodesSet.insert(
iter->first);
5074 poses.insert(*
iter);
5078 double e0=0,e1=0,e2=0,e3=0,e4=0;
5084 std::map<int, Transform>
path;
5092 UWARN(
"Nearest id of %s in %d poses is 0 !? Returning empty path.",
target.prettyPrint().c_str(), (
int)poses.size());
5095 std::map<int, int> ids =
_memory->
getNeighborsId(nearestId, maxGraphDepth, 0,
true,
true,
true,
true, nodesSet);
5099 for(std::map<int, int>::iterator
iter=ids.begin();
iter!=ids.end(); ++
iter)
5101 std::map<int, Transform>::iterator jter = poses.find(
iter->first);
5102 if(jter != poses.end())
5104 bool valid =
path.empty();
5109 for(std::multimap<int, Link>::iterator kter=links.begin(); kter!=links.end() && !valid; ++kter)
5111 valid =
path.find(kter->first) !=
path.end();
5130 UWARN(
"%s=Off but path(%d) > maxGraphDepth(%d)*2+1, nearestId=%d ids=%d. Is reduce graph activated before?",
5131 Parameters::kMemReduceGraph().
c_str(), (
int)
path.size(), maxGraphDepth, nearestId, (
int)ids.size());
5133 paths.insert(std::make_pair(nearestId,
path));
5137 UWARN(
"path.size()=0!? nearestId=%d ids=%d, aborting...", nearestId, (
int)ids.size());
5143 UDEBUG(
"e0=%fs e1=%fs e2=%fs e3=%fs e4=%fs", e0, e1, e2, e3, e4);
5150 bool lookInDatabase,
5151 std::map<int, Transform> & optimizedPoses,
5152 cv::Mat & covariance,
5153 std::multimap<int, Link> * constraints,
5155 int * iterationsDone)
const
5158 UINFO(
"Optimize map: around location %d (lookInDatabase=%s)",
id, lookInDatabase?
"true":
"false");
5165 id = ids.begin()->first;
5167 UINFO(
"get %d ids time %f s", (
int)ids.size(),
timer.ticks());
5174 optimizedPoses = poses;
5179 UINFO(
"Correction (from node %d) %s",
id,
t.prettyPrint().c_str());
5184 UWARN(
"Failed to optimize the graph! returning empty optimized poses...");
5185 optimizedPoses.clear();
5188 constraints->clear();
5196 const std::set<int> & ids,
5197 const std::map<int, Transform> & guessPoses,
5198 bool lookInDatabase,
5199 cv::Mat & covariance,
5200 std::multimap<int, Link> * constraints,
5202 int * iterationsDone)
const
5205 std::map<int, Transform> optimizedPoses;
5206 std::map<int, Transform> poses;
5207 std::multimap<int, Link> edgeConstraints;
5208 UDEBUG(
"ids=%d", (
int)ids.size());
5210 UINFO(
"get constraints (ids=%d, %d poses, %d edges) time %f s", (
int)ids.size(), (
int)poses.size(), (
int)edgeConstraints.size(),
timer.ticks());
5213 for(std::map<int, Transform>::iterator
iter=poses.begin();
iter!=poses.end() &&
iter->first < 0; ++
iter)
5217 cv::Mat infMatrix = cv::Mat::eye(6, 6, CV_64FC1);
5228 for(std::map<int, Transform>::iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
5231 std::map<int, Transform>::const_iterator foundGuess = guessPoses.find(
iter->first);
5232 if(foundGuess!=guessPoses.end() &&
iter->first != fromId)
5234 iter->second = foundGuess->second;
5244 optimizedPoses = poses;
5247 *constraints = edgeConstraints;
5252 bool hasLandmarks = !edgeConstraints.empty() && edgeConstraints.begin()->first < 0;
5253 if(poses.size() != guessPoses.size() || hasLandmarks)
5255 UDEBUG(
"recompute poses using only links (robust to multi-session)");
5256 std::map<int, Transform> posesOut;
5257 std::multimap<int, Link> edgeConstraintsOut;
5262 *constraints = edgeConstraintsOut;
5267 UDEBUG(
"use input guess poses");
5271 *constraints = edgeConstraints;
5275 if(!poses.empty() && optimizedPoses.empty())
5277 UWARN(
"Optimization has failed (poses=%d, guess=%d, links=%d)...",
5278 (
int)poses.size(), (
int)guessPoses.size(), (
int)edgeConstraints.size());
5282 UINFO(
"Optimization time %f s",
timer.ticks());
5284 return optimizedPoses;
5292 if(likelihood.size()==0)
5299 bool likelihoodNullValuesIgnored =
true;
5300 for(std::map<int, float>::iterator
iter = ++likelihood.begin();
iter!=likelihood.end(); ++
iter)
5302 if((
iter->second >= 0 && !likelihoodNullValuesIgnored) ||
5303 (
iter->second > 0 && likelihoodNullValuesIgnored))
5318 for(std::map<int, float>::iterator
iter=++likelihood.begin();
iter!= likelihood.end(); ++
iter)
5321 iter->second = 1.0f;
5337 maxId =
iter->first;
5343 likelihood.begin()->second =
mean/stdDev + 1.0f;
5347 likelihood.begin()->second = stdDev/(
max-
mean) + 1.0
f;
5351 likelihood.begin()->second = 2.0f;
5355 UDEBUG(
"mean=%f, stdDev=%f, max=%f, maxId=%d, time=%fs",
mean, stdDev,
max, maxId,
time);
5364 UERROR(
"Working directory not set.");
5367 std::list<int> signaturesToCompare;
5376 if(
s->getWeight() != -1)
5378 signaturesToCompare.push_back(
iter->first);
5384 signaturesToCompare.push_back(
iter->first);
5390 std::string fileName = this->
getWorkingDir() +
"/DumpPrediction.txt";
5392 fopen_s(&fout, fileName.c_str(),
"w");
5394 fout = fopen(fileName.c_str(),
"w");
5399 for(
int i=0;
i<prediction.rows; ++
i)
5401 for(
int j=0;
j<prediction.cols; ++
j)
5403 fprintf(fout,
"%f ",((
float*)prediction.data)[
j +
i*prediction.cols]);
5405 fprintf(fout,
"\n");
5412 UWARN(
"Memory and/or the Bayes filter are not created");
5430 _memory->
getNodeInfo(
id, odomPoseLocal, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors,
true);
5433 if(images || scan || userData || occupancyGrid)
5437 if(!images && withWords)
5439 std::vector<CameraModel> models;
5440 std::vector<StereoCameraModel> stereoModels;
5442 data.setCameraModels(models);
5443 data.setStereoCameraModels(stereoModels);
5456 for(std::multimap<int, Link>::iterator
iter=links.begin();
iter!=links.end(); ++
iter)
5460 s.addLandmark(
iter->second);
5464 s.addLink(
iter->second);
5468 if(withWords || withGlobalDescriptors)
5470 std::multimap<int, int> words;
5471 std::vector<cv::KeyPoint> wordsKpts;
5472 std::vector<cv::Point3f> words3;
5473 cv::Mat wordsDescriptors;
5474 std::vector<rtabmap::GlobalDescriptor> globalDescriptors;
5478 s.setWords(words, wordsKpts, words3, wordsDescriptors);
5480 if(withGlobalDescriptors)
5482 s.sensorData().setGlobalDescriptors(globalDescriptors);
5489 s.sensorData().setGPS(gps);
5490 s.sensorData().setEnvSensors(sensors);
5496 std::map<int, Signature> & signatures,
5497 std::map<int, Transform> & poses,
5498 std::multimap<int, Link> & constraints,
5503 return getGraph(poses, constraints, optimized, global, &signatures,
true,
true,
true,
true);
5507 std::map<int, Transform> & poses,
5508 std::multimap<int, Link> & constraints,
5511 std::map<int, Signature> * signatures,
5517 bool withGlobalDescriptors)
const
5562 for(std::set<int>::iterator
iter = ids.begin();
iter!=ids.end(); ++
iter)
5564 signatures->insert(std::make_pair(*
iter,
getSignatureCopy(*
iter, withImages, withScan, withUserData, withGrid, withWords, withGlobalDescriptors)));
5570 UERROR(
"Last working signature is null!?");
5574 UWARN(
"Memory not initialized...");
5580 std::map<int, float> nearestNodesTmp;
5581 std::map<int, float> * nearestNodesPtr = distsSqr == 0? &nearestNodesTmp : distsSqr;
5583 std::map<int, Transform> nearestPoses;
5584 for(std::map<int, float>::iterator
iter=nearestNodesPtr->begin();
iter!=nearestNodesPtr->end(); ++
iter)
5588 return nearestPoses;
5593 UDEBUG(
"nodeId=%d, radius=%f", nodeId, radius);
5594 std::map<int, float> nearestNodesTmp;
5595 std::map<int, float> * nearestNodesPtr = distsSqr == 0? &nearestNodesTmp : distsSqr;
5613 std::map<int, Transform> nearestPoses;
5614 for(std::map<int, float>::iterator
iter=nearestNodesPtr->begin();
iter!=nearestNodesPtr->end(); ++
iter)
5619 return nearestPoses;
5623 float clusterRadiusMax,
5629 float clusterRadiusMin)
5635 UERROR(
"Cannot detect more loop closures if graph optimization iterations = 0");
5640 UERROR(
"Detecting more loop closures can be done only in RGBD-SLAM mode.");
5643 if(!intraSession && !interSession)
5645 UERROR(
"Intra and/or inter session argument should be true.");
5649 std::list<Link> loopClosuresAdded;
5650 std::multimap<int, int> checkedLoopClosures;
5652 std::map<int, Transform> posesToCheckLoopClosures;
5653 std::map<int, Transform> poses;
5654 std::multimap<int, Link> links;
5655 std::map<int, Signature> signatures;
5656 this->
getGraph(poses, links,
true,
true, &signatures);
5658 std::map<int, int> mapIds;
5659 UDEBUG(
"remove all invalid or intermediate nodes, fill mapIds");
5660 for(std::map<int, Transform>::iterator
iter=poses.upper_bound(0);
iter!=poses.end();++
iter)
5662 if(signatures.at(
iter->first).getWeight() >= 0)
5664 posesToCheckLoopClosures.insert(*
iter);
5665 mapIds.insert(std::make_pair(
iter->first, signatures.at(
iter->first).mapId()));
5669 for(
int n=0;
n<iterations; ++
n)
5671 UINFO(
"Looking for more loop closures, clustering poses... (iteration=%d/%d, radius=%f m angle=%f rad)",
5672 n+1, iterations, clusterRadiusMax, clusterAngle);
5675 posesToCheckLoopClosures,
5679 UINFO(
"Looking for more loop closures, clustering poses... found %d clusters.", (
int)clusters.size());
5682 std::set<int> addedLinks;
5683 for(std::multimap<int, int>::iterator
iter=clusters.begin();
iter!= clusters.end(); ++
iter, ++
i)
5685 if(processState && processState->
isCanceled())
5691 int from =
iter->first;
5692 int to =
iter->second;
5695 from =
iter->second;
5699 int mapIdFrom =
uValue(mapIds, from, 0);
5700 int mapIdTo =
uValue(mapIds, to, 0);
5702 if((interSession && mapIdFrom != mapIdTo) ||
5703 (intraSession && mapIdFrom == mapIdTo))
5706 bool alreadyChecked =
false;
5707 for(std::multimap<int, int>::iterator jter = checkedLoopClosures.lower_bound(from);
5708 !alreadyChecked && jter!=checkedLoopClosures.end() && jter->first == from;
5711 if(to == jter->second)
5713 alreadyChecked =
true;
5720 if(addedLinks.find(from) == addedLinks.end() &&
5721 addedLinks.find(to) == addedLinks.end() &&
5726 if(
delta.getNorm() < clusterRadiusMax &&
5727 delta.getNorm() >= clusterRadiusMin)
5729 checkedLoopClosures.insert(std::make_pair(from, to));
5731 UASSERT(signatures.find(from) != signatures.end());
5732 UASSERT(signatures.find(to) != signatures.end());
5737 guess = poses.at(from).
inverse() * poses.at(to);
5746 bool updateConstraints =
true;
5751 int mapId = signatures.at(from).mapId();
5753 for(std::map<int, Signature>::iterator ster=signatures.begin(); ster!=signatures.end(); ++ster)
5755 if(ster->second.mapId() == mapId)
5757 fromId = ster->first;
5761 std::multimap<int, Link> linksIn = links;
5763 const Link * maxLinearLink = 0;
5764 const Link * maxAngularLink = 0;
5765 float maxLinearError = 0.0f;
5766 float maxAngularError = 0.0f;
5767 float maxLinearErrorRatio = 0.0f;
5768 float maxAngularErrorRatio = 0.0f;
5769 std::map<int, Transform> optimizedPoses;
5770 std::multimap<int, Link> links;
5771 UASSERT(poses.find(fromId) != poses.end());
5772 UASSERT_MSG(poses.find(from) != poses.end(),
uFormat(
"id=%d poses=%d links=%d", from, (
int)poses.size(), (
int)links.size()).c_str());
5773 UASSERT_MSG(poses.find(to) != poses.end(),
uFormat(
"id=%d poses=%d links=%d", to, (
int)poses.size(), (
int)links.size()).c_str());
5775 UASSERT(optimizedPoses.find(fromId) != optimizedPoses.end());
5776 UASSERT_MSG(optimizedPoses.find(from) != optimizedPoses.end(),
uFormat(
"id=%d poses=%d links=%d", from, (
int)optimizedPoses.size(), (
int)links.size()).c_str());
5777 UASSERT_MSG(optimizedPoses.find(to) != optimizedPoses.end(),
uFormat(
"id=%d poses=%d links=%d", to, (
int)optimizedPoses.size(), (
int)links.size()).c_str());
5781 if(optimizedPoses.size())
5786 maxLinearErrorRatio,
5787 maxAngularErrorRatio,
5794 UINFO(
"Max optimization linear error = %f m (link %d->%d)", maxLinearError, maxLinearLink->
from(), maxLinearLink->
to());
5797 msg =
uFormat(
"Rejecting edge %d->%d because "
5798 "graph error is too large after optimization (%f m for edge %d->%d with ratio %f > std=%f m). "
5803 maxLinearLink->
from(),
5804 maxLinearLink->
to(),
5805 maxLinearErrorRatio,
5807 Parameters::kRGBDOptimizeMaxError().c_str(),
5812 UERROR(
"Huge optimization error detected!"
5813 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
5814 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
5815 maxLinearErrorRatio,
5816 maxLinearLink->
from(),
5817 maxLinearLink->
to(),
5818 maxLinearLink->
type(),
5821 Parameters::kRGBDOptimizeMaxError().c_str());
5824 else if(maxAngularLink)
5826 UINFO(
"Max optimization angular error = %f deg (link %d->%d)", maxAngularError*180.0
f/
M_PI, maxAngularLink->
from(), maxAngularLink->
to());
5829 msg =
uFormat(
"Rejecting edge %d->%d because "
5830 "graph error is too large after optimization (%f deg for edge %d->%d with ratio %f > std=%f deg). "
5834 maxAngularError*180.0
f/
M_PI,
5835 maxAngularLink->
from(),
5836 maxAngularLink->
to(),
5837 maxAngularErrorRatio,
5839 Parameters::kRGBDOptimizeMaxError().c_str(),
5844 UERROR(
"Huge optimization error detected!"
5845 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
5846 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
5847 maxAngularErrorRatio,
5848 maxAngularLink->
from(),
5849 maxAngularLink->
to(),
5850 maxAngularLink->
type(),
5851 maxAngularError*180.0f/CV_PI,
5853 Parameters::kRGBDOptimizeMaxError().c_str());
5859 msg =
uFormat(
"Rejecting edge %d->%d because graph optimization has failed!",
5866 updateConstraints =
false;
5870 poses = optimizedPoses;
5873 if(updateConstraints)
5875 addedLinks.insert(from);
5876 addedLinks.insert(to);
5880 std::string
msg =
uFormat(
"Iteration %d/%d: Added loop closure %d->%d! (%d/%d)",
n+1, iterations, from, to,
i+1, (
int)clusters.size());
5901 std::string
msg =
uFormat(
"Iteration %d/%d: Detected %d total loop closures!",
n+1, iterations, (
int)addedLinks.size()/2);
5910 UINFO(
"Iteration %d/%d: Detected %d total loop closures!",
n+1, iterations, (
int)addedLinks.size()/2);
5913 if(addedLinks.size() == 0)
5918 UINFO(
"Optimizing graph with new links (%d nodes, %d constraints)...",
5919 (
int)poses.size(), (
int)links.size());
5922 if(poses.size() == 0)
5924 UERROR(
"Optimization failed! Rejecting all loop closures...");
5925 loopClosuresAdded.clear();
5928 UINFO(
"Optimizing graph with new links... done!");
5930 UINFO(
"Total added %d loop closures.", (
int)loopClosuresAdded.size());
5932 if(loopClosuresAdded.size())
5934 for(std::list<Link>::iterator
iter=loopClosuresAdded.begin();
iter!=loopClosuresAdded.end(); ++
iter)
5941 std::map<int, Transform>::iterator jter = poses.find(
iter->first);
5942 if(jter != poses.end())
5944 iter->second = jter->second;
5947 std::map<int, Transform> tmp;
5953 return (
int)loopClosuresAdded.size();
5958 bool rematchFeatures,
5960 float pixelVariance)
5964 int iterations = Parameters::defaultOptimizerIterations();
5965 float pixelVariance = Parameters::defaultg2oPixelVariance();
5973 if(pixelVariance > 0.0
f)
5978 std::map<int, Signature> signatures;
5988 std::map<int, Transform> poses = optimizer->
optimizeBA(
5998 UERROR(
"Optimization failed!");
6016 const std::map<int, Transform> & poses,
6017 const cv::Mat & map,
6042 UERROR(
"Refining links can be done only in RGBD-SLAM mode.");
6046 std::list<Link> linksRefined;
6048 std::map<int, Transform> poses;
6049 std::multimap<int, Link> links;
6050 std::map<int, Signature> signatures;
6051 this->
getGraph(poses, links,
false,
true, &signatures);
6054 for(std::multimap<int, Link>::iterator
iter=links.lower_bound(1);
iter!= links.end(); ++
iter)
6056 int from =
iter->second.from();
6057 int to =
iter->second.to();
6059 UASSERT(signatures.find(from) != signatures.end());
6060 UASSERT(signatures.find(to) != signatures.end());
6068 linksRefined.push_back(
Link(from, to,
iter->second.type(),
t,
info.covariance.inv()));
6069 UINFO(
"Refined link %d->%d! (%d/%d)", from, to, ++
i, (
int)links.size());
6072 UINFO(
"Total refined %d links.", (
int)linksRefined.size());
6074 if(linksRefined.size())
6076 for(std::list<Link>::iterator
iter=linksRefined.begin();
iter!=linksRefined.end(); ++
iter)
6081 return (
int)linksRefined.size();
6089 UERROR(
"Adding new link can be done only in RGBD-SLAM mode.");
6094 UERROR(
"Memory is not initialized.");
6099 UERROR(
"Link's transform is null! (%d->%d type=%s)", link.
from(), link.
to(), link.
typeName().c_str());
6106 UERROR(
"Link's \"from id\" %d is not in working memory", link.
from());
6111 UERROR(
"Link's \"to id\" %d is not in working memory", link.
to());
6118 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());
6125 UERROR(
"Cannot add new link %d->%d to memory", link.
from(), link.
to());
6131 std::multimap<int, Link> links;
6135 if(poses.find(link.
from()) == poses.end())
6137 UERROR(
"Link's \"from id\" %d is not in the graph (size=%d)", link.
from(), (
int)poses.size());
6141 if(poses.find(link.
to()) == poses.end())
6143 UERROR(
"Link's \"to id\" %d is not in the graph (size=%d)", link.
to(), (
int)poses.size());
6151 msg =
uFormat(
"Rejecting edge %d->%d because graph optimization has failed!", link.
from(), link.
to());
6155 float maxLinearError = 0.0f;
6156 float maxLinearErrorRatio = 0.0f;
6157 float maxAngularError = 0.0f;
6158 float maxAngularErrorRatio = 0.0f;
6159 const Link * maxLinearLink = 0;
6160 const Link * maxAngularLink = 0;
6165 maxLinearErrorRatio,
6166 maxAngularErrorRatio,
6173 UINFO(
"Max optimization linear error = %f m (link %d->%d)", maxLinearError, maxLinearLink->
from(), maxLinearLink->
to());
6176 msg =
uFormat(
"Rejecting edge %d->%d because "
6177 "graph error is too large after optimization (%f m for edge %d->%d with ratio %f > std=%f m). "
6182 maxLinearLink->
from(),
6183 maxLinearLink->
to(),
6184 maxLinearErrorRatio,
6186 Parameters::kRGBDOptimizeMaxError().c_str(),
6191 UERROR(
"Huge optimization error detected!"
6192 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
6193 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
6194 maxLinearErrorRatio,
6195 maxLinearLink->
from(),
6196 maxLinearLink->
to(),
6197 maxLinearLink->
type(),
6200 Parameters::kRGBDOptimizeMaxError().c_str());
6203 else if(maxAngularLink)
6205 UINFO(
"Max optimization angular error = %f deg (link %d->%d)", maxAngularError*180.0
f/
M_PI, maxAngularLink->
from(), maxAngularLink->
to());
6208 msg =
uFormat(
"Rejecting edge %d->%d because "
6209 "graph error is too large after optimization (%f deg for edge %d->%d with ratio %f > std=%f deg). "
6213 maxAngularError*180.0f/
M_PI,
6214 maxAngularLink->
from(),
6215 maxAngularLink->
to(),
6216 maxAngularErrorRatio,
6218 Parameters::kRGBDOptimizeMaxError().c_str(),
6223 UERROR(
"Huge optimization error detected!"
6224 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
6225 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
6226 maxAngularErrorRatio,
6227 maxAngularLink->
from(),
6228 maxAngularLink->
to(),
6229 maxAngularLink->
type(),
6230 maxAngularError*180.0f/CV_PI,
6232 Parameters::kRGBDOptimizeMaxError().c_str());
6246 std::map<int, Transform>::iterator jter = poses.find(
iter->first);
6247 if(jter != poses.end())
6249 iter->second = jter->second;
6257 std::map<int, Transform> tmp;
6267 int oldestId = link.
from()>link.
to()?link.
to():link.
from();
6268 int newestId = link.
from()<link.
to()?link.
to():link.
from();
6272 UERROR(
"Link's id %d is not in working memory", oldestId);
6277 UERROR(
"Link's id %d is not in the optimized graph (_optimizedPoses=%d)", oldestId, (
int)
_optimizedPoses.size());
6282 UERROR(
"Adding link with %s=true in localization mode is not supported.", Parameters::kRGBDOptimizeFromGraphEnd().
c_str());
6289 UERROR(
"Link's id %d is not in the odometry cache (oldest=%d, newest=%d, %s=%d)",
6293 Parameters::kRGBDMaxOdomCacheSize().c_str(),
6298 UERROR(
"Link's id %d is not in the odometry cache (%s=%d).",
6300 Parameters::kRGBDMaxOdomCacheSize().
c_str(),
6312 constraints.insert(std::make_pair(link.
from(), link));
6313 for(std::multimap<int, Link>::iterator
iter=constraints.begin();
iter!=constraints.end(); ++
iter)
6316 if(iterPose !=
_optimizedPoses.end() && poses.find(iterPose->first) == poses.end())
6318 poses.insert(*iterPose);
6320 constraints.insert(std::make_pair(iterPose->first,
Link(iterPose->first, iterPose->first,
Link::kPosePrior, iterPose->second, cv::Mat::eye(6,6, CV_64FC1)*999999)));
6324 std::map<int, Transform> posesOut;
6325 std::multimap<int, Link> edgeConstraintsOut;
6329 std::map<int, Transform> optPoses =
_graphOptimizer->
optimize(poses.begin()->first, posesOut, edgeConstraintsOut);
6332 bool rejectLocalization =
false;
6333 if(optPoses.empty())
6335 UWARN(
"Optimization failed, rejecting localization!");
6336 rejectLocalization =
true;
6340 UINFO(
"Compute max graph errors...");
6341 float maxLinearError = 0.0f;
6342 float maxLinearErrorRatio = 0.0f;
6343 float maxAngularError = 0.0f;
6344 float maxAngularErrorRatio = 0.0f;
6345 const Link * maxLinearLink = 0;
6346 const Link * maxAngularLink = 0;
6350 maxLinearErrorRatio,
6351 maxAngularErrorRatio,
6357 if(maxLinearLink == 0 && maxAngularLink==0)
6359 UWARN(
"Could not compute graph errors! Wrong loop closures could be accepted!");
6364 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()));
6367 UWARN(
"Rejecting localization (%d <-> %d) in this "
6368 "iteration because a wrong loop closure has been "
6369 "detected after graph optimization, resulting in "
6370 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). The "
6371 "maximum error ratio parameter \"%s\" is %f of std deviation.",
6374 maxLinearErrorRatio,
6375 maxLinearLink->
from(),
6376 maxLinearLink->
to(),
6377 maxLinearLink->
type(),
6380 Parameters::kRGBDOptimizeMaxError().c_str(),
6382 rejectLocalization =
true;
6386 UERROR(
"Huge optimization error detected!"
6387 "Linear error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
6388 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
6389 maxLinearErrorRatio,
6390 maxLinearLink->
from(),
6391 maxLinearLink->
to(),
6392 maxLinearLink->
type(),
6395 Parameters::kRGBDOptimizeMaxError().c_str());
6400 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()));
6403 UWARN(
"Rejecting localization (%d <-> %d) in this "
6404 "iteration because a wrong loop closure has been "
6405 "detected after graph optimization, resulting in "
6406 "a maximum graph error ratio of %f (edge %d->%d, type=%d, abs error=%f deg, stddev=%f). The "
6407 "maximum error ratio parameter \"%s\" is %f of std deviation.",
6410 maxAngularErrorRatio,
6411 maxAngularLink->
from(),
6412 maxAngularLink->
to(),
6413 maxAngularLink->
type(),
6414 maxAngularError*180.0f/CV_PI,
6416 Parameters::kRGBDOptimizeMaxError().c_str(),
6418 rejectLocalization =
true;
6422 UERROR(
"Huge optimization error detected!"
6423 "Angular error ratio of %f (edge %d->%d, type=%d, abs error=%f m, stddev=%f). You may consider "
6424 "enabling \"%s\" to reject those bad optimizations by setting it to a non null value!",
6425 maxAngularErrorRatio,
6426 maxAngularLink->
from(),
6427 maxAngularLink->
to(),
6428 maxAngularLink->
type(),
6429 maxAngularError*180.0f/CV_PI,
6431 Parameters::kRGBDOptimizeMaxError().c_str());
6436 if(!rejectLocalization)
6439 Transform newT = newOptPoseInv * optPoses.at(link.
to());
6440 Link linkTmp = link;
6442 if(oldestId == link.
from())
6469 cv::Mat information = covariance.inv();
6473 if(odomMaxInf.size() == 6)
6475 for(
int i=0;
i<6; ++
i)
6477 if(information.at<
double>(
i,
i) > odomMaxInf[
i])
6479 information.at<
double>(
i,
i) = odomMaxInf[
i];
6499 UWARN(
"%s=0, so cannot republish the %d requested nodes.", Parameters::kRtabmapMaxRepublished().
c_str(), (
int)ids.size());
6503 UWARN(
"%s=false, so cannot republish the %d requested nodes.", Parameters::kRtabmapPublishLastSignature().
c_str(), (
int)ids.size());
6509 UINFO(
"status=%d", status);
6531 UINFO(
"Planning a path to node %d (global=%d)", targetNode, global?1:0);
6535 UINFO(
"Planning a path to landmark %d (global=%d)", -targetNode, global?1:0);
6540 UWARN(
"A path can only be computed in RGBD-SLAM mode");
6551 int currentNode = 0;
6556 UWARN(
"Working memory is empty... cannot compute a path");
6565 UWARN(
"Last localization pose is null or optimized graph is empty... cannot compute a path");
6578 if(currentNode && targetNode)
6603 if(!
_path.empty() && !
path.empty() &&
path.rbegin()->first < 0)
6605 transformToLandmark =
_path.back().second.inverse() *
t *
path.rbegin()->second;
6608 else if(currentNode == 0)
6610 UWARN(
"We should be localized before planning.");
6615 if(
_path.size() == 0)
6618 UWARN(
"Cannot compute a path!");
6623 UINFO(
"Path generated! Size=%d", (
int)
_path.size());
6626 std::stringstream
stream;
6627 for(
unsigned int i=0;
i<
_path.size(); ++
i)
6640 std::string goalStr =
uFormat(
"GOAL:%d", targetNode);
6653 std::map<int, std::string>::iterator
iter =
labels.find(targetNode);
6656 goalStr = std::string(
"GOAL:")+
labels.at(targetNode);
6659 setUserData(0, cv::Mat(1,
int(goalStr.size()+1), CV_8SC1, (
void *)goalStr.c_str()).clone());
6675 if(tolerance < 0.0
f)
6680 std::list<std::pair<int, Transform> > pathPoses;
6684 UWARN(
"This method can only be used in RGBD-SLAM mode");
6691 std::multimap<int, int> links;
6696 for(std::map<int, Link>::const_iterator jter=
s->getLinks().begin(); jter!=
s->getLinks().end(); ++jter)
6699 if(jter->second.from() != jter->second.to() &&
uContains(
nodes, jter->second.to()))
6701 links.insert(std::make_pair(jter->second.from(), jter->second.to()));
6706 UINFO(
"Time getting links = %fs",
timer.ticks());
6708 int currentNode = 0;
6713 UWARN(
"Working memory is empty... cannot compute a path");
6722 UWARN(
"Last localization pose is null... cannot compute a path");
6740 nearestId = currentNode;
6746 UINFO(
"Nearest node found=%d ,%fs", nearestId,
timer.ticks());
6749 if(tolerance != 0.0
f && targetPose.
getDistance(
nodes.at(nearestId)) > tolerance)
6751 UWARN(
"Cannot plan farther than %f m from the graph! (distance=%f m from node %d)",
6756 UINFO(
"Computing path from location %d to %d", currentNode, nearestId);
6761 if(
_path.size() == 0)
6763 UWARN(
"Cannot compute a path!");
6767 UINFO(
"Path generated! Size=%d", (
int)
_path.size());
6770 std::stringstream
stream;
6771 for(
unsigned int i=0;
i<
_path.size(); ++
i)
6793 UWARN(
"Nearest node not found in graph (size=%d) for pose %s", (
int)
nodes.size(), targetPose.
prettyPrint().c_str());
6801 std::vector<std::pair<int, Transform> > poses;
6812 poses[oi++] = *
iter;
6826 std::vector<int> ids;
6837 ids[oi++] =
iter->first;
6863 UWARN(
"This method can on be used in RGBD-SLAM mode!");
6885 std::multimap<int, Link> links = currentIndexS->
getLinks();
6886 bool latestVirtualLinkFound =
false;
6887 for(std::multimap<int, Link>::reverse_iterator
iter=links.rbegin();
iter!=links.rend(); ++
iter)
6891 if(latestVirtualLinkFound)
6897 latestVirtualLinkFound =
true;
6903 float distanceSoFar = 0.0f;
6944 UERROR(
"Last node is null in memory or not in optimized poses. Aborting the plan...");
6954 UERROR(
"Last localization pose is null. Aborting the plan...");
6961 int goalId =
_path.back().first;
6968 UINFO(
"Goal %d reached!", goalId);
6977 float distanceFromCurrentNode = 0.0f;
6978 bool sameGoalIndex =
false;
7009 UINFO(
"Updated current goal from %d to %d (%d/%d)",
7015 sameGoalIndex =
true;
7019 unsigned int nearestNodeIndex = 0;
7021 bool sameCurrentIndex =
false;
7032 nearestNodeIndex =
i;
7038 UERROR(
"The nearest pose on the path not found! Aborting the plan...");
7052 sameCurrentIndex =
true;
7055 bool isStuck =
false;
7058 float distanceToCurrentGoal = 0.0f;
7073 if(distanceToCurrentGoal > 0.0
f)
7094 UWARN(
"Current goal %d not reached since %d iterations (\"RGBD/PlanStuckIterations\"=%d), mark that node as unreachable.",
7107 UERROR(
"No upcoming nodes on the path are reachable! Aborting the plan...");
7124 UDEBUG(
"Creating global scan map (if scans are available)");
7127 std::vector<int> scanIndices;
7128 std::map<int, Transform> scanViewpoints;
7132 if(!
data.laserScanCompressed().empty())
7135 data.uncompressDataConst(0, 0, &scan, 0, 0, 0, 0);
7149 UWARN(
"Incompatible scan formats (%s vs %s), cannot create global scan map.",
7159 UDEBUG(
"Ignored %d (scan is empty), pose still added.",
iter->first);
7165 UDEBUG(
"Ignored %d (no scan), pose still added.",
iter->first);
7171 float voxelSize = 0.0f;
7173 float normalRadius = 0.0f;
7178 if(voxelSize > 0.0
f)
7193 UINFO(
"Global scan map has been assembled (size=%d points, %d poses) "
7194 "for proximity detection (only in localization mode %s=false and with %s=true)",
7197 Parameters::kMemIncrementalMemory().c_str(),
7198 Parameters::kRGBDProximityGlobalScanMap().c_str());
7205 UWARN(
"Saving %s/rtabmap_global_scan_map.pcd (only saved when logger level is debug)",
_wDir.c_str());
7207 pcl::io::savePCDFile(
_wDir+
"/rtabmap_global_scan_map.pcd", *cloud2);
7211 UWARN(
"%s is enabled and logger is debug, but %s is not set, cannot save global scan map for debugging.",
7212 Parameters::kRGBDProximityGlobalScanMap().
c_str(), Parameters::kRtabmapWorkingDirectory().
c_str());