61 #include <pcl/io/pcd_io.h> 62 #include <pcl/common/common.h> 65 #include <opencv2/imgproc/types_c.h> 75 _similarityThreshold(
Parameters::defaultMemRehearsalSimilarity()),
76 _binDataKept(
Parameters::defaultMemBinDataKept()),
77 _rawDescriptorsKept(
Parameters::defaultMemRawDescriptorsKept()),
78 _saveDepth16Format(
Parameters::defaultMemSaveDepth16Format()),
79 _notLinkedNodesKeptInDb(
Parameters::defaultMemNotLinkedNodesKept()),
80 _saveIntermediateNodeData(
Parameters::defaultMemIntermediateNodeDataKept()),
81 _rgbCompressionFormat(
Parameters::defaultMemImageCompressionFormat()),
82 _incrementalMemory(
Parameters::defaultMemIncrementalMemory()),
83 _localizationDataSaved(
Parameters::defaultMemLocalizationDataSaved()),
84 _reduceGraph(
Parameters::defaultMemReduceGraph()),
85 _maxStMemSize(
Parameters::defaultMemSTMSize()),
86 _recentWmRatio(
Parameters::defaultMemRecentWmRatio()),
87 _transferSortingByWeightId(
Parameters::defaultMemTransferSortingByWeightId()),
88 _idUpdatedToNewOneRehearsal(
Parameters::defaultMemRehearsalIdUpdatedToNewOne()),
89 _generateIds(
Parameters::defaultMemGenerateIds()),
90 _badSignaturesIgnored(
Parameters::defaultMemBadSignaturesIgnored()),
91 _mapLabelsAdded(
Parameters::defaultMemMapLabelsAdded()),
92 _depthAsMask(
Parameters::defaultMemDepthAsMask()),
93 _stereoFromMotion(
Parameters::defaultMemStereoFromMotion()),
94 _imagePreDecimation(
Parameters::defaultMemImagePreDecimation()),
95 _imagePostDecimation(
Parameters::defaultMemImagePostDecimation()),
96 _compressionParallelized(
Parameters::defaultMemCompressionParallelized()),
97 _laserScanDownsampleStepSize(
Parameters::defaultMemLaserScanDownsampleStepSize()),
98 _laserScanVoxelSize(
Parameters::defaultMemLaserScanVoxelSize()),
99 _laserScanNormalK(
Parameters::defaultMemLaserScanNormalK()),
100 _laserScanNormalRadius(
Parameters::defaultMemLaserScanNormalRadius()),
101 _laserScanGroundNormalsUp(
Parameters::defaultIcpPointToPlaneGroundNormalsUp()),
102 _reextractLoopClosureFeatures(
Parameters::defaultRGBDLoopClosureReextractFeatures()),
103 _localBundleOnLoopClosure(
Parameters::defaultRGBDLocalBundleOnLoopClosure()),
104 _invertedReg(
Parameters::defaultRGBDInvertedReg()),
105 _rehearsalMaxDistance(
Parameters::defaultRGBDLinearUpdate()),
106 _rehearsalMaxAngle(
Parameters::defaultRGBDAngularUpdate()),
107 _rehearsalWeightIgnoredWhileMoving(
Parameters::defaultMemRehearsalWeightIgnoredWhileMoving()),
108 _useOdometryFeatures(
Parameters::defaultMemUseOdomFeatures()),
109 _useOdometryGravity(
Parameters::defaultMemUseOdomGravity()),
110 _createOccupancyGrid(
Parameters::defaultRGBDCreateOccupancyGrid()),
111 _visMaxFeatures(
Parameters::defaultVisMaxFeatures()),
112 _imagesAlreadyRectified(
Parameters::defaultRtabmapImagesAlreadyRectified()),
113 _rectifyOnlyFeatures(
Parameters::defaultRtabmapRectifyOnlyFeatures()),
114 _covOffDiagonalIgnored(
Parameters::defaultMemCovOffDiagIgnored()),
115 _detectMarkers(
Parameters::defaultRGBDMarkerDetection()),
116 _markerLinVariance(
Parameters::defaultMarkerVarianceLinear()),
117 _markerAngVariance(
Parameters::defaultMarkerVarianceAngular()),
119 _idMapCount(kIdStart),
121 _lastGlobalLoopClosureId(0),
122 _memoryChanged(
false),
123 _linksChanged(
false),
126 _badSignRatio(
Parameters::defaultKpBadSignRatio()),
127 _tfIdfLikelihoodUsed(
Parameters::defaultKpTfIdfLikelihoodUsed()),
128 _parallelized(
Parameters::defaultKpParallelized()),
144 float corRatio = Parameters::defaultIcpCorrespondenceRatio();
150 UWARN(
"%s is >=0.5, which sets correspondence ratio for proximity detection using " 151 "laser scans to 100% (2 x Ratio). You may lower the ratio to accept proximity " 152 "detection with not full scans overlapping.", Parameters::kIcpCorrespondenceRatio().c_str());
230 bool loadAllNodesInWM = Parameters::defaultMemInitWMWithAllNodes();
234 std::list<Signature*> dbSignatures;
249 for(std::list<Signature*>::reverse_iterator iter=dbSignatures.rbegin(); iter!=dbSignatures.rend(); ++iter)
259 _signatures.insert(std::pair<int, Signature *>((*iter)->id(), *iter));
261 if(!(*iter)->getGroundTruthPose().isNull()) {
262 _groundTruths.insert(std::make_pair((*iter)->id(), (*iter)->getGroundTruthPose()));
265 if(!(*iter)->getLandmarks().empty())
268 for(std::map<int, Link>::const_iterator jter = (*iter)->getLandmarks().begin(); jter!=(*iter)->getLandmarks().end(); ++jter)
270 int landmarkId = jter->first;
273 cv::Mat landmarkSize = jter->second.uncompressUserDataConst();
274 if(!landmarkSize.empty() && landmarkSize.type() == CV_32FC1 && landmarkSize.total()==1)
276 std::pair<std::map<int, float>::iterator,
bool> inserted=
_landmarksSize.insert(std::make_pair(-landmarkId, landmarkSize.at<
float>(0,0)));
279 if(inserted.first->second != landmarkSize.at<
float>(0,0))
281 UWARN(
"Trying to update landmark size buffer for landmark %d with size=%f but " 282 "it has already a different size set. Keeping old size (%f).",
283 -landmarkId, inserted.first->second, landmarkSize.at<
float>(0,0));
288 std::map<int, std::set<int> >::iterator nter =
_landmarksIndex.find(landmarkId);
291 nter->second.insert((*iter)->id());
296 tmp.insert((*iter)->id());
312 UDEBUG(
"Check if all nodes are in Working Memory");
315 for(std::map<int, Link>::const_iterator jter = iter->second->getLinks().begin(); jter!=iter->second->getLinks().end(); ++jter)
326 UDEBUG(
"update odomMaxInf vector");
327 std::multimap<int, Link> links = this->
getAllLinks(
true,
true);
328 for(std::multimap<int, Link>::iterator iter=links.begin(); iter!=links.end(); ++iter)
331 iter->second.infMatrix().cols == 6 &&
332 iter->second.infMatrix().rows == 6)
338 for(
int i=0; i<6; ++i)
340 const double & v = iter->second.infMatrix().at<
double>(i,i);
348 UDEBUG(
"update odomMaxInf vector, done!");
370 UDEBUG(
"Loading dictionary...");
373 UDEBUG(
"load all referenced words in working memory");
375 std::set<int> wordIds;
376 const std::map<int, Signature *> & signatures = this->
getSignatures();
377 for(std::map<int, Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i)
379 const std::multimap<int, int> & words = i->second->getWords();
381 for(std::list<int>::iterator iter=keys.begin(); iter!=keys.end(); ++iter)
385 wordIds.insert(*iter);
390 UDEBUG(
"load words %d", (
int)wordIds.size());
395 std::list<VisualWord*> words;
397 for(std::list<VisualWord*>::iterator iter = words.begin(); iter!=words.end(); ++iter)
424 const std::map<int, Signature *> & signatures = this->
getSignatures();
425 for(std::map<int, Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i)
430 const std::multimap<int, int> & words = s->
getWords();
433 UDEBUG(
"node=%d, word references=%d", s->
id(), words.size());
434 for(std::multimap<int, int>::const_iterator iter = words.begin(); iter!=words.end(); ++iter)
457 parameters.erase(Parameters::kRtabmapWorkingDirectory());
474 void Memory::close(
bool databaseSaved,
bool postInitClosingEvents,
const std::string & ouputDatabasePath)
476 UINFO(
"databaseSaved=%d, postInitClosingEvents=%d", databaseSaved?1:0, postInitClosingEvents?1:0);
479 bool databaseNameChanged =
false;
489 UINFO(
"No changes added to database.");
504 UINFO(
"Saving memory...");
537 UWARN(
"Please call Memory::close() before");
553 ParametersMap::const_iterator iter;
585 UWARN(
"%s and %s cannot be used at the same time, disabling %s...",
586 Parameters::kRGBDLocalBundleOnLoopClosure().c_str(),
587 Parameters::kRGBDInvertedReg().c_str(),
588 Parameters::kRGBDLocalBundleOnLoopClosure().c_str());
638 if((iter=params.find(Parameters::kKpDetectorStrategy())) != params.end())
646 UWARN(
"new detector strategy %d while the vocabulary is already created. This may give problems if feature descriptors are not the same type than the one used in the current vocabulary (a memory reset would be required if so).",
int(detectorStrategy));
650 UINFO(
"new detector strategy %d.",
int(detectorStrategy));
686 if((iter=params.find(Parameters::kRegStrategy())) != params.end())
692 UDEBUG(
"new registration strategy %d",
int(regStrategy));
727 if(
uContains(params, Parameters::kIcpCorrespondenceRatio()))
730 float corRatio = Parameters::defaultIcpCorrespondenceRatio();
736 UWARN(
"%s is >=0.5, which sets correspondence ratio for proximity detection using " 737 "laser scans to 100% (2 x Ratio). You may lower the ratio to accept proximity " 738 "detection with not full scans overlapping.", Parameters::kIcpCorrespondenceRatio().c_str());
760 iter = params.find(Parameters::kMemIncrementalMemory());
761 if(iter != params.end())
763 bool value =
uStr2Bool(iter->second.c_str());
773 UWARN(
"Switching from Mapping to Localization mode, the database will be saved and reloaded.");
780 UWARN(
"Switching from Mapping to Localization mode, the database is reloaded!");
788 int visFeatureType = Parameters::defaultVisFeatureType();
789 int kpDetectorStrategy = Parameters::defaultKpDetectorStrategy();
792 if(visFeatureType != kpDetectorStrategy)
794 UWARN(
"%s is enabled, but %s and %s parameters are not the same! Disabling %s...",
795 Parameters::kMemUseOdomFeatures().c_str(),
796 Parameters::kVisFeatureType().c_str(),
797 Parameters::kKpDetectorStrategy().c_str(),
798 Parameters::kMemUseOdomFeatures().c_str());
823 return update(data,
Transform(), cv::Mat(), std::vector<float>(), stats);
829 const cv::Mat & covariance,
830 const std::vector<float> & velocity,
842 UDEBUG(
"pre-updating...");
844 t=timer.
ticks()*1000;
845 if(stats) stats->
addStatistic(Statistics::kTimingMemPre_update(), t);
846 UDEBUG(
"time preUpdate=%f ms", t);
854 UERROR(
"Failed to create a signature...");
857 if(velocity.size()==6)
859 signature->
setVelocity(velocity[0], velocity[1], velocity[2], velocity[3], velocity[4], velocity[5]);
862 t=timer.
ticks()*1000;
863 if(stats) stats->
addStatistic(Statistics::kTimingMemSignature_creation(), t);
864 UDEBUG(
"time creating signature=%f ms", t);
883 t=timer.
ticks()*1000;
884 if(stats) stats->
addStatistic(Statistics::kTimingMemRehearsal(), t);
885 UDEBUG(
"time rehearsal=%f ms", t);
891 UWARN(
"The working memory is empty and the memory is not " 892 "incremental (Mem/IncrementalMemory=False), no loop closure " 893 "can be detected! Please set Mem/IncrementalMemory=true to increase " 894 "the memory with new images or decrease the STM size (which is %d " 895 "including the new one added).", (
int)
_stMem.size());
902 int notIntermediateNodesCount = 0;
903 for(std::set<int>::iterator iter=
_stMem.begin(); iter!=
_stMem.end(); ++iter)
909 ++notIntermediateNodesCount;
912 std::map<int, int> reducedIds;
920 --notIntermediateNodesCount;
928 reducedIds.insert(std::make_pair(
id, reducedTo));
959 UASSERT(covariance.cols == 6 && covariance.rows == 6 && covariance.type() == CV_64FC1);
960 double maxAngVar = 0.0;
963 maxAngVar = covariance.at<
double>(5,5);
967 maxAngVar =
uMax3(covariance.at<
double>(3,3), covariance.at<
double>(4,4), covariance.at<
double>(5,5));
970 if(maxAngVar != 1.0 && maxAngVar > 0.1)
972 static bool warned =
false;
975 UWARN(
"Very large angular variance (%f) detected! Please fix odometry " 976 "covariance, otherwise poor graph optimizations are " 977 "expected and wrong loop closure detections creating a lot " 978 "of errors in the map could be accepted. This message is only " 979 "printed once.", maxAngVar);
987 infMatrix = cv::Mat::zeros(6,6,CV_64FC1);
988 infMatrix.at<
double>(0,0) = 1.0 / covariance.at<
double>(0,0);
989 infMatrix.at<
double>(1,1) = 1.0 / covariance.at<
double>(1,1);
990 infMatrix.at<
double>(2,2) = 1.0 / covariance.at<
double>(2,2);
991 infMatrix.at<
double>(3,3) = 1.0 / covariance.at<
double>(3,3);
992 infMatrix.at<
double>(4,4) = 1.0 / covariance.at<
double>(4,4);
993 infMatrix.at<
double>(5,5) = 1.0 / covariance.at<
double>(5,5);
997 infMatrix = covariance.inv();
999 if((
uIsFinite(covariance.at<
double>(0,0)) && covariance.at<
double>(0,0)>0.0) &&
1000 !(
uIsFinite(infMatrix.at<
double>(0,0)) && infMatrix.at<
double>(0,0)>0.0))
1002 UERROR(
"Failed to invert the covariance matrix! Covariance matrix should be invertible!");
1003 std::cout <<
"Covariance: " << covariance << std::endl;
1004 infMatrix = cv::Mat::eye(6,6,CV_64FC1);
1007 UASSERT(infMatrix.rows == 6 && infMatrix.cols == 6);
1012 for(
int i=0; i<6; ++i)
1014 const double & v = infMatrix.at<
double>(i,i);
1034 UDEBUG(
"Ignoring neighbor link between %d and %d because they are not in the same map! (%d vs %d)",
1041 std::string tag =
uFormat(
"map%d", signature->
mapId());
1044 UINFO(
"Tagging node %d with label \"%s\"", signature->
id(), tag.c_str());
1046 _labels.insert(std::make_pair(signature->
id(), tag));
1054 std::string tag =
uFormat(
"map%d", signature->
mapId());
1057 UINFO(
"Tagging node %d with label \"%s\"", signature->
id(), tag.c_str());
1059 _labels.insert(std::make_pair(signature->
id(), tag));
1072 UDEBUG(
"%d words ref for the signature %d (weight=%d)", signature->
getWords().size(), signature->
id(), signature->
getWeight());
1087 UDEBUG(
"Inserting node %d in WM...", signature->
id());
1089 _signatures.insert(std::pair<int, Signature*>(signature->
id(), signature));
1097 UERROR(
"Signature is null ?!?");
1103 UDEBUG(
"Inserting node %d from STM in WM...",
id);
1111 const std::multimap<int, Link> & links = s->getLinks();
1112 std::map<int, Link> neighbors;
1113 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
1117 merge = iter->second.to() < s->id() &&
1118 iter->second.to() != iter->second.from() &&
1121 iter->second.userDataCompressed().empty() &&
1126 UDEBUG(
"Reduce %d to %d", s->id(), iter->second.to());
1129 *reducedTo = iter->second.to();
1136 neighbors.insert(*iter);
1141 if(s->getLabel().empty())
1143 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
1146 if(sTo->
id()!=s->id())
1155 for(std::map<int, Link>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
1157 if(!sTo->
hasLink(jter->second.to()))
1159 UDEBUG(
"Merging link %d->%d (type=%d) to link %d->%d (type %d)",
1160 iter->second.from(), iter->second.to(), iter->second.type(),
1161 jter->second.from(), jter->second.to(), jter->second.type());
1177 std::multimap<int, Link> linksCopy = links;
1178 for(std::multimap<int, Link>::iterator iter=linksCopy.begin(); iter!=linksCopy.end(); ++iter)
1183 s->removeLink(iter->first);
1224 bool lookInDatabase)
const 1226 std::multimap<int, Link> links;
1230 const std::multimap<int, Link> & allLinks = s->
getLinks();
1231 for(std::multimap<int, Link>::const_iterator iter = allLinks.begin(); iter!=allLinks.end(); ++iter)
1236 links.insert(*iter);
1243 for(std::multimap<int, Link>::iterator iter=links.begin(); iter!=links.end();)
1248 links.erase(iter++);
1258 UWARN(
"Cannot find signature %d in memory", signatureId);
1265 bool lookInDatabase)
const 1268 std::multimap<int, Link> loopClosures;
1271 const std::multimap<int, Link> & allLinks = s->
getLinks();
1272 for(std::multimap<int, Link>::const_iterator iter = allLinks.begin(); iter!=allLinks.end(); ++iter)
1276 iter->second.from() != iter->second.to() &&
1279 loopClosures.insert(*iter);
1286 for(std::multimap<int, Link>::iterator iter=loopClosures.begin(); iter!=loopClosures.end();)
1292 loopClosures.erase(iter++);
1300 return loopClosures;
1305 bool lookInDatabase,
1306 bool withLandmarks)
const 1308 std::multimap<int, Link> links;
1326 UWARN(
"Cannot find signature %d in memory", signatureId);
1329 else if(signatureId < 0)
1331 int landmarkId = signatureId;
1332 std::map<int, std::set<int> >::const_iterator iter =
_landmarksIndex.find(landmarkId);
1335 for(std::set<int>::const_iterator jter=iter->second.begin(); jter!=iter->second.end(); ++jter)
1340 std::map<int, Link>::const_iterator kter = s->
getLandmarks().find(landmarkId);
1344 links.insert(std::make_pair(s->
id(), kter->second.inverse()));
1351 std::map<int, Link> nodes;
1353 for(std::map<int, Link>::iterator kter=nodes.begin(); kter!=nodes.end(); ++kter)
1355 links.insert(std::make_pair(kter->first, kter->second.inverse()));
1362 std::multimap<int, Link>
Memory::getAllLinks(
bool lookInDatabase,
bool ignoreNullLinks,
bool withLandmarks)
const 1364 std::multimap<int, Link> links;
1373 links.erase(iter->first);
1374 for(std::map<int, Link>::const_iterator jter=iter->second->getLinks().begin();
1375 jter!=iter->second->getLinks().end();
1378 if(!ignoreNullLinks || jter->second.isValid())
1380 links.insert(std::make_pair(iter->first, jter->second));
1385 for(std::map<int, Link>::const_iterator jter=iter->second->getLandmarks().begin();
1386 jter!=iter->second->getLandmarks().end();
1389 if(!ignoreNullLinks || jter->second.isValid())
1391 links.insert(std::make_pair(iter->first, jter->second));
1407 int maxCheckedInDatabase,
1408 bool incrementMarginOnLoop,
1410 bool ignoreIntermediateNodes,
1411 bool ignoreLocalSpaceLoopIds,
1412 const std::set<int> & nodesSet,
1413 double * dbAccessTime
1425 std::map<int, int> ids;
1430 int nbLoadedFromDb = 0;
1431 std::list<int> curentMarginList;
1432 std::set<int> currentMargin;
1433 std::set<int> nextMargin;
1434 nextMargin.insert(signatureId);
1436 std::set<int> ignoredIds;
1437 while((maxGraphDepth == 0 || m < maxGraphDepth) && nextMargin.size())
1440 curentMarginList = std::list<int>(nextMargin.rbegin(), nextMargin.rend());
1443 for(std::list<int>::iterator jter = curentMarginList.begin(); jter!=curentMarginList.end(); ++jter)
1445 if(ids.find(*jter) == ids.end() && (nodesSet.empty() || nodesSet.find(*jter) != nodesSet.end()))
1450 std::multimap<int, Link> tmpLinks;
1451 std::map<int, Link> tmpLandmarks;
1452 const std::multimap<int, Link> * links = &tmpLinks;
1453 const std::map<int, Link> * landmarks = &tmpLandmarks;
1456 if(!ignoreIntermediateNodes || s->
getWeight() != -1)
1458 ids.insert(std::pair<int, int>(*jter, m));
1462 ignoredIds.insert(*jter);
1471 else if(maxCheckedInDatabase == -1 || (maxCheckedInDatabase > 0 &&
_dbDriver && nbLoadedFromDb < maxCheckedInDatabase))
1474 ids.insert(std::pair<int, int>(*jter, m));
1478 if(tmpLinks.empty())
1480 UWARN(
"No links loaded for %d?!", *jter);
1484 for(std::multimap<int, Link>::iterator kter=tmpLinks.begin(); kter!=tmpLinks.end();)
1488 tmpLandmarks.insert(*kter);
1489 tmpLinks.erase(kter++);
1491 else if(kter->second.from() == kter->second.to())
1494 tmpLinks.erase(kter++);
1509 for(std::multimap<int, Link>::const_iterator iter=links->begin(); iter!=links->end(); ++iter)
1512 ignoredIds.find(iter->first) == ignoredIds.end())
1518 if(ignoreIntermediateNodes && s->
getWeight()==-1)
1521 if(currentMargin.insert(iter->first).second)
1523 curentMarginList.push_back(iter->first);
1528 nextMargin.insert(iter->first);
1533 if(incrementMarginOnLoop)
1535 nextMargin.insert(iter->first);
1539 if(currentMargin.insert(iter->first).second)
1541 curentMarginList.push_back(iter->first);
1549 for(std::map<int, Link>::const_iterator iter=landmarks->begin(); iter!=landmarks->end(); ++iter)
1551 const std::map<int, std::set<int> >::const_iterator kter =
_landmarksIndex.find(iter->first);
1554 for(std::set<int>::const_iterator nter=kter->second.begin(); nter!=kter->second.end(); ++nter)
1556 if( !
uContains(ids, *nter) && ignoredIds.find(*nter) == ignoredIds.end())
1558 if(incrementMarginOnLoop)
1560 nextMargin.insert(*nter);
1564 if(currentMargin.insert(*nter).second)
1566 curentMarginList.push_back(*nter);
1584 const std::map<int, Transform> & optimizedPoses,
1591 std::map<int, float> ids;
1592 std::map<int, float> checkedIds;
1593 std::list<int> curentMarginList;
1594 std::set<int> currentMargin;
1595 std::set<int> nextMargin;
1596 nextMargin.insert(signatureId);
1598 Transform referential = optimizedPoses.at(signatureId);
1600 float radiusSqrd = radius*radius;
1601 while((maxGraphDepth == 0 || m < maxGraphDepth) && nextMargin.size())
1603 curentMarginList = std::list<int>(nextMargin.begin(), nextMargin.end());
1606 for(std::list<int>::iterator jter = curentMarginList.begin(); jter!=curentMarginList.end(); ++jter)
1608 if(checkedIds.find(*jter) == checkedIds.end())
1615 const Transform & t = optimizedPoses.at(*jter);
1618 if(radiusSqrd == 0 || distanceSqrd<radiusSqrd)
1620 ids.insert(std::pair<int, float>(*jter,distanceSqrd));
1624 for(std::multimap<int, Link>::const_iterator iter=s->
getLinks().begin(); iter!=s->
getLinks().end(); ++iter)
1627 uContains(optimizedPoses, iter->first) &&
1630 nextMargin.insert(iter->first);
1656 int id = *
_stMem.begin();
1658 if(reducedIds && reducedId > 0)
1660 reducedIds->insert(std::make_pair(
id, reducedId));
1671 std::map<int, double>::iterator iter=
_workingMem.find(signatureId);
1691 std::string version =
"0.0.0";
1701 std::string url =
"";
1721 for(std::map<int, Signature*>::const_iterator iter =
_signatures.begin(); iter!=
_signatures.end(); ++iter)
1723 ids.insert(iter->first);
1768 uFormat(
"The number of signatures don't match! _workingMem=%d, _stMem=%d, _signatures=%d",
1771 UDEBUG(
"Adding statistics after run...");
1776 parameters.erase(Parameters::kRtabmapWorkingDirectory());
1790 for(std::map<int, Signature *>::iterator i=mem.begin(); i!=mem.end(); ++i)
1794 UDEBUG(
"deleting from the working and the short-term memory: %d", i->first);
1861 std::map<int, float> likelihood;
1868 else if(ids.empty())
1870 UWARN(
"ids list is empty");
1874 for(std::list<int>::const_iterator iter = ids.begin(); iter!=ids.end(); ++iter)
1882 UFATAL(
"Signature %d not found in WM ?!?", *iter);
1887 likelihood.insert(likelihood.end(), std::pair<int, float>(*iter, sim));
1890 UDEBUG(
"compute likelihood (similarity)... %f s", timer.
ticks());
1897 std::map<int, float> likelihood;
1898 std::map<int, float> calculatedWordsRatio;
1905 else if(ids.empty())
1907 UWARN(
"ids list is empty");
1911 for(std::list<int>::const_iterator iter = ids.begin(); iter!=ids.end(); ++iter)
1913 likelihood.insert(likelihood.end(), std::pair<int, float>(*iter, 0.0f));
1930 UDEBUG(
"processing... ");
1932 for(std::list<int>::const_iterator i=wordIds.begin(); i!=wordIds.end(); ++i)
1944 logNnw = log10(N/nw);
1947 for(std::map<int, int>::const_iterator j=refs.begin(); j!=refs.end(); ++j)
1949 std::map<int, float>::iterator iter = likelihood.find(j->first);
1950 if(iter != likelihood.end())
1953 ni = this->
getNi(j->first);
1957 iter->second += ( nwi * logNnw ) / ni;
1967 UDEBUG(
"compute likelihood (tf-idf) %f s", timer.
ticks());
1975 std::map<int, int> weights;
1983 UFATAL(
"Location %d must exist in memory", iter->first);
1985 weights.insert(weights.end(), std::make_pair(iter->first, s->
getWeight()));
1989 weights.insert(weights.end(), std::make_pair(iter->first, -1));
1998 std::list<int> signaturesRemoved;
2009 int wordsRemoved = 0;
2016 while(wordsRemoved < newWords)
2019 if(signatures.size())
2024 signaturesRemoved.push_back(s->
id());
2038 UDEBUG(
"newWords=%d, wordsRemoved=%d", newWords, wordsRemoved);
2046 for(std::list<Signature *>::iterator iter=signatures.begin(); iter!=signatures.end(); ++iter)
2048 signaturesRemoved.push_back((*iter)->id());
2053 if((
int)signatures.size() < signaturesAdded)
2055 UWARN(
"Less signatures transferred (%d) than added (%d)! The working memory cannot decrease in size.",
2056 (
int)signatures.size(), signaturesAdded);
2060 UDEBUG(
"signaturesRemoved=%d, _signaturesAdded=%d", (
int)signatures.size(), signaturesAdded);
2063 return signaturesRemoved;
2070 int signatureRemoved = 0;
2083 return signatureRemoved;
2125 for(std::map<int, Transform>::iterator iter=poses.lower_bound(1); iter!=poses.end() && ok; ++iter)
2129 UWARN(
"Node %d not found in working memory", iter->first);
2135 UWARN(
"Optimized poses (%d) and working memory " 2136 "size (%d) don't match. Returning empty optimized " 2137 "poses to force re-update. If you want to use the " 2138 "saved optimized poses, set %s to true",
2141 Parameters::kMemInitWMWithAllNodes().c_str());
2142 return std::map<int, Transform>();
2147 return std::map<int, Transform>();
2168 const cv::Mat & cloud,
2169 const std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > & polygons,
2170 #
if PCL_VERSION_COMPARE(>=, 1, 8, 0)
2171 const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
2173 const std::vector<std::vector<Eigen::Vector2f> > & texCoords,
2175 const cv::Mat & textures)
const 2184 std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > * polygons,
2185 #
if PCL_VERSION_COMPARE(>=, 1, 8, 0)
2186 std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
2188 std::vector<std::vector<Eigen::Vector2f> > * texCoords,
2190 cv::Mat * textures)
const 2230 else if(weight == k.
weight)
2236 else if(age == k.
age)
2251 std::list<Signature *> removableSignatures;
2252 std::map<WeightAgeIdKey, Signature *> weightAgeIdMap;
2255 UDEBUG(
"mem.size()=%d, ignoredIds.size()=%d", (
int)
_workingMem.size(), (int)ignoredIds.size());
2260 bool recentWmImmunized =
false;
2262 int currentRecentWmSize = 0;
2269 ++currentRecentWmSize;
2272 if(currentRecentWmSize>1 && currentRecentWmSize < recentWmMaxSize)
2274 recentWmImmunized =
true;
2276 else if(currentRecentWmSize == 0 &&
_workingMem.size() > 1)
2290 for(std::map<int, double>::const_iterator memIter =
_workingMem.begin(); memIter !=
_workingMem.end(); ++memIter)
2297 else if(memIter->first > 0 && ignoredIds.find(memIter->first) == ignoredIds.end() && (!lastInSTM || !lastInSTM->
hasLink(memIter->first)))
2303 bool foundInSTM =
false;
2304 for(std::map<int, Link>::const_iterator iter = s->
getLinks().begin(); iter!=s->
getLinks().end(); ++iter)
2308 UDEBUG(
"Ignored %d because it has a link (%d) to STM", s->
id(), iter->first);
2330 int recentWmCount = 0;
2333 UDEBUG(
"signatureMap.size()=%d _lastGlobalLoopClosureId=%d currentRecentWmSize=%d recentWmMaxSize=%d",
2335 for(std::map<WeightAgeIdKey, Signature*>::iterator iter=weightAgeIdMap.begin();
2336 iter!=weightAgeIdMap.end();
2339 if(!recentWmImmunized)
2341 UDEBUG(
"weight=%d, id=%d",
2342 iter->second->getWeight(),
2343 iter->second->id());
2344 removableSignatures.push_back(iter->second);
2349 if(currentRecentWmSize - recentWmCount < recentWmMaxSize)
2351 UDEBUG(
"switched recentWmImmunized");
2352 recentWmImmunized =
true;
2358 UDEBUG(
"weight=%d, id=%d",
2359 iter->second->getWeight(),
2360 iter->second->id());
2361 removableSignatures.push_back(iter->second);
2363 if(removableSignatures.size() >= (
unsigned int)count)
2371 ULOGGER_WARN(
"not enough signatures to get an old one...");
2373 return removableSignatures;
2389 int landmarkId = iter->first;
2390 std::map<int, std::set<int> >::iterator nter =
_landmarksIndex.find(landmarkId);
2393 nter->second.erase(s->
id());
2394 if(nter->second.empty())
2405 keepLinkedToGraph =
false;
2409 if(!keepLinkedToGraph)
2412 uFormat(
"Deleting location (%d) outside the " 2413 "STM is not implemented!", s->
id()).c_str());
2414 const std::multimap<int, Link> & links = s->
getLinks();
2415 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
2417 if(iter->second.from() != iter->second.to() && iter->first > 0)
2422 uFormat(
"A neighbor (%d) of the deleted location %d is " 2423 "not found in WM/STM! Are you deleting a location " 2424 "outside the STM?", iter->first, s->
id()).c_str());
2426 if(iter->first > s->
id() && links.size()>1 && sTo->
hasLink(s->
id()))
2428 UWARN(
"Link %d of %d is newer, removing neighbor link " 2429 "may split the map!",
2430 iter->first, s->
id());
2460 for(std::list<int>::const_iterator i=keys.begin(); i!=keys.end(); ++i)
2466 std::vector<VisualWord*> wordToDelete;
2467 wordToDelete.push_back(w);
2471 deletedWords->push_back(w->
id());
2510 if(keepLinkedToGraph)
2536 UDEBUG(
"landmarkId=%d", landmarkId);
2537 std::map<int, Link> nodes;
2540 std::map<int, std::set<int> >::const_iterator iter =
_landmarksIndex.find(landmarkId);
2543 for(std::set<int>::const_iterator jter=iter->second.begin(); jter!=iter->second.end(); ++jter)
2548 std::map<int, Link>::const_iterator kter = s->
getLandmarks().find(landmarkId);
2551 nodes.insert(std::make_pair(s->
id(), kter->second));
2566 UDEBUG(
"label=%s", label.c_str());
2573 if(iter->second->getLabel().compare(label) == 0)
2575 id = iter->second->id();
2579 if(
id == 0 &&
_dbDriver && lookInDatabase)
2599 if(idFound == 0 && label.empty() &&
_labels.find(
id)==
_labels.end())
2601 UWARN(
"Trying to remove label from node %d but it has already no label",
id);
2604 if(idFound == 0 || idFound ==
id)
2611 UWARN(
"Label \"%s\" removed from node %d",
_labels.at(
id).c_str(), id);
2618 UWARN(
"Label \"%s\" set to node %d (previously labeled \"%s\")", label.c_str(), id,
_labels.at(
id).c_str());
2622 UWARN(
"Label \"%s\" set to node %d", label.c_str(), id);
2634 std::list<Signature *> signatures;
2636 if(signatures.size())
2640 UWARN(
"Label \"%s\" removed from node %d",
_labels.at(
id).c_str(), id);
2647 UWARN(
"Label \"%s\" set to node %d (previously labeled \"%s\")", label.c_str(), id,
_labels.at(
id).c_str());
2651 UWARN(
"Label \"%s\" set to node %d", label.c_str(), id);
2656 signatures.front()->setLabel(label);
2663 UERROR(
"Node %d not found, failed to set label \"%s\"!",
id, label.c_str());
2668 UWARN(
"Another node %d has already label \"%s\", cannot set it to node %d", idFound, label.c_str(), id);
2683 UERROR(
"Node %d not found in RAM, failed to set user data (size=%d)!",
id, data.total());
2690 UDEBUG(
"Deleting location %d", locationId);
2700 UDEBUG(
"Saving location data %d", locationId);
2724 UINFO(
"removing link between location %d and %d", oldS->
id(), newS->
id());
2745 bool noChildrenAnymore =
true;
2746 for(std::map<int, Link>::const_iterator iter=newS->
getLinks().begin(); iter!=newS->
getLinks().end(); ++iter)
2750 iter->second.from() != iter->second.to() &&
2751 iter->first < newS->
id())
2753 noChildrenAnymore =
false;
2764 UERROR(
"Signatures %d and %d don't have bidirectional link!", oldS->
id(), newS->
id());
2771 UERROR(
"Signature %d is not in working memory... cannot remove link.", newS->
id());
2775 UERROR(
"Signature %d is not in working memory... cannot remove link.", oldS->
id());
2782 UDEBUG(
"id=%d image=%d scan=%d userData=%d",
id, image?1:0, scan?1:0, userData?1:0);
2799 bool useKnownCorrespondencesIfPossible)
2808 transform =
computeTransform(*fromS, *toS, guess, info, useKnownCorrespondencesIfPossible);
2812 std::string msg =
uFormat(
"Did not find nodes %d and/or %d", fromId, toId);
2828 bool useKnownCorrespondencesIfPossible)
const 2848 cv::Mat imgBuf, depthBuf, userBuf;
2863 std::vector<int> inliersV;
2888 tmpFrom.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
2892 else if(useKnownCorrespondencesIfPossible)
2912 else if(!isNeighborRefining &&
2925 std::multimap<int, int> words;
2926 std::vector<cv::Point3f> words3DMap;
2927 std::vector<cv::KeyPoint> wordsMap;
2928 cv::Mat wordsDescriptorsMap;
2930 const std::multimap<int, Link> & links = fromS.
getLinks();
2934 UDEBUG(
"fromS.getWords()=%d uniques=%d", (
int)fromS.
getWords().size(), (int)wordsFrom.size());
2935 for(std::map<int, int>::const_iterator jter=wordsFrom.begin(); jter!=wordsFrom.end(); ++jter)
2937 const cv::Point3f & pt = fromS.
getWords3()[jter->second];
2940 words.insert(std::make_pair(jter->first, words.size()));
2941 words3DMap.push_back(pt);
2942 wordsMap.push_back(fromS.
getWordsKpts()[jter->second]);
2947 UDEBUG(
"words3DMap=%d", (
int)words3DMap.size());
2949 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
2951 int id = iter->first;
2958 for(std::map<int, int>::const_iterator jter=wordsTo.begin(); jter!=wordsTo.end(); ++jter)
2960 const cv::Point3f & pt = s->
getWords3()[jter->second];
2961 if( jter->first > 0 &&
2963 words.find(jter->first) == words.end())
2965 words.insert(words.end(), std::make_pair(jter->first, words.size()));
2974 UDEBUG(
"words3DMap=%d", (
int)words3DMap.size());
2976 tmpFrom2.
setWords(words, wordsMap, words3DMap, wordsDescriptorsMap);
2980 if(!transform.
isNull() && info && !tmpFrom2.getWords3().empty())
2982 std::map<int, cv::Point3f> points3DMap;
2984 for(std::map<int, int>::iterator iter=wordsMap.begin(); iter!=wordsMap.end(); ++iter)
2986 points3DMap.insert(std::make_pair(iter->first, tmpFrom2.getWords3()[iter->second]));
2988 std::map<int, Transform> bundlePoses;
2989 std::multimap<int, Link> bundleLinks;
2990 std::map<int, std::vector<CameraModel> > bundleModels;
2991 std::map<int, std::map<int, FeatureBA> > wordReferences;
2993 std::multimap<int, Link> links = fromS.
getLinks();
2996 links.insert(std::make_pair(fromS.
id(),
Link()));
2998 int totalWordReferences = 0;
2999 for(std::multimap<int, Link>::iterator iter=links.begin(); iter!=links.end(); ++iter)
3001 int id = iter->first;
3002 if(
id != fromS.
id() || iter->second.transform().isNull())
3006 if(
id == tmpTo.
id())
3016 std::vector<CameraModel> models;
3034 models.push_back(model);
3039 UFATAL(
"no valid camera model to use local bundle adjustment on loop closure!");
3041 bundleModels.insert(std::make_pair(
id, models));
3042 UASSERT(iter->second.isValid() || iter->first == fromS.
id());
3044 if(iter->second.transform().isNull())
3051 bundleLinks.insert(std::make_pair(iter->second.from(), iter->second));
3052 bundlePoses.insert(std::make_pair(
id, iter->second.transform()));
3056 for(std::map<int, int>::const_iterator jter=words.begin(); jter!=words.end(); ++jter)
3058 if(points3DMap.find(jter->first)!=points3DMap.end() &&
3059 (
id == tmpTo.
id() || jter->first > 0))
3062 int cameraIndex = 0;
3065 UASSERT(models[0].imageWidth()>0);
3066 float subImageWidth = models[0].imageWidth();
3067 cameraIndex = int(kpts.pt.x / subImageWidth);
3068 kpts.pt.x = kpts.pt.x - (subImageWidth*float(cameraIndex));
3077 Transform invLocalTransform = models[cameraIndex].localTransform().
inverse();
3080 wordReferences.insert(std::make_pair(jter->first, std::map<int, FeatureBA>()));
3081 wordReferences.at(jter->first).insert(std::make_pair(
id,
FeatureBA(kpts, d, cv::Mat(), cameraIndex)));
3082 ++totalWordReferences;
3092 std::set<int> sbaOutliers;
3097 bundlePoses = sba.
optimizeBA(-toS.
id(), bundlePoses, bundleLinks, bundleModels, points3DMap, wordReferences, &sbaOutliers);
3100 UDEBUG(
"bundleTime=%fs (poses=%d wordRef=%d outliers=%d)", bundleTime.
ticks(), (int)bundlePoses.size(), totalWordReferences, (int)sbaOutliers.size());
3102 UDEBUG(
"Local Bundle Adjustment Before: %s", transform.prettyPrint().c_str());
3103 if(!bundlePoses.rbegin()->second.isNull())
3105 if(sbaOutliers.size())
3107 std::vector<int> newInliers(info->
inliersIDs.size());
3109 for(
unsigned int i=0; i<info->
inliersIDs.size(); ++i)
3111 if(sbaOutliers.find(info->
inliersIDs[i]) == sbaOutliers.end())
3116 newInliers.resize(oi);
3117 UDEBUG(
"BA outliers ratio %f",
float(sbaOutliers.size())/
float(info->
inliersIDs.size()));
3118 info->
inliers = (int)newInliers.size();
3124 transform.setNull();
3128 transform = bundlePoses.rbegin()->second;
3131 transform = transform.to3DoF();
3135 UDEBUG(
"Local Bundle Adjustment After : %s", transform.prettyPrint().c_str());
3144 transform = transform.
inverse();
3167 const std::map<int, Transform> & poses,
3173 UDEBUG(
"%d -> %d, Guess=%s", fromId, toId, (poses.at(fromId).inverse() * poses.at(toId)).prettyPrint().c_str());
3177 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
3179 if(iter->first != fromId)
3184 UDEBUG(
"%d vs %s", fromId, ids.c_str());
3188 std::list<Signature*> scansToLoad;
3189 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
3197 scansToLoad.push_back(s);
3217 float guessNorm = guess.
getNorm();
3222 UINFO(
"Too far scans between %d and %d to compute transformation: guessNorm=%f, scan range from=%f to=%f", fromId, toId, guessNorm, fromScan.
rangeMax(), toScan.
rangeMax());
3229 int maxPoints = fromScan.
size();
3230 pcl::PointCloud<pcl::PointXYZ>::Ptr assembledToClouds(
new pcl::PointCloud<pcl::PointXYZ>);
3231 pcl::PointCloud<pcl::PointNormal>::Ptr assembledToNormalClouds(
new pcl::PointCloud<pcl::PointNormal>);
3232 pcl::PointCloud<pcl::PointXYZI>::Ptr assembledToIClouds(
new pcl::PointCloud<pcl::PointXYZI>);
3233 pcl::PointCloud<pcl::PointXYZINormal>::Ptr assembledToNormalIClouds(
new pcl::PointCloud<pcl::PointXYZINormal>);
3234 pcl::PointCloud<pcl::PointXYZRGB>::Ptr assembledToRGBClouds(
new pcl::PointCloud<pcl::PointXYZRGB>);
3235 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr assembledToNormalRGBClouds(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3236 UDEBUG(
"maxPoints from(%d) = %d", fromId, maxPoints);
3237 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
3239 if(iter->first != fromId)
3288 if(scan.
size() > maxPoints)
3290 UDEBUG(
"maxPoints scan(%d) = %d", iter->first, (
int)scan.
size());
3291 maxPoints = scan.
size();
3301 UWARN(
"Depth2D not found for signature %d", iter->first);
3307 if(assembledToNormalClouds->size())
3311 else if(assembledToClouds->size())
3315 else if(assembledToNormalIClouds->size())
3319 else if(assembledToIClouds->size())
3323 else if(assembledToNormalRGBClouds->size())
3327 UERROR(
"Cannot handle 2d scan with RGB format.");
3334 else if(assembledToRGBClouds->size())
3338 UERROR(
"Cannot handle 2d scan with RGB format.");
3345 UDEBUG(
"assembledScan=%d points", assembledScan.
size());
3374 if(toS->hasLink(link.
from()))
3377 UINFO(
"already linked! to=%d, from=%d", link.
to(), link.
from());
3381 UDEBUG(
"Add link between %d and %d", toS->id(), fromS->id());
3384 fromS->addLink(link);
3401 UASSERT(fromS->getWeight() >= 0 && toS->getWeight() >=0);
3405 fromS->setWeight(fromS->getWeight() + toS->getWeight());
3410 toS->setWeight(toS->getWeight() + fromS->getWeight());
3411 fromS->setWeight(0);
3417 else if(!addInDatabase)
3421 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
from());
3425 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
to());
3431 UDEBUG(
"Add link between %d and %d (db)", link.
from(), link.
to());
3432 fromS->addLink(link);
3437 UDEBUG(
"Add link between %d (db) and %d", link.
from(), link.
to());
3443 UDEBUG(
"Add link between %d (db) and %d (db)", link.
from(), link.
to());
3462 toS->removeLink(link.
from());
3474 UERROR(
"fromId=%d and toId=%d are not linked!", link.
from(), link.
to());
3477 else if(!updateInDatabase)
3481 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
from());
3485 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
to());
3490 UDEBUG(
"Update link between %d and %d (db)", link.
from(), link.
to());
3497 UDEBUG(
"Update link between %d (db) and %d", link.
from(), link.
to());
3498 toS->removeLink(link.
from());
3504 UDEBUG(
"Update link between %d (db) and %d (db)", link.
from(), link.
to());
3515 iter->second->removeVirtualLinks();
3525 const std::multimap<int, Link> & links = s->
getLinks();
3526 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
3537 UERROR(
"Link %d of %d not in WM/STM?!?", iter->first, s->
id());
3545 UERROR(
"Signature %d not in WM/STM?!?", signatureId);
3551 UINFO(
"Dumping memory to directory \"%s\"", directory.c_str());
3552 this->
dumpDictionary((directory+
"/DumpMemoryWordRef.txt").c_str(), (directory+
"/DumpMemoryWordDesc.txt").c_str());
3553 this->
dumpSignatures((directory +
"/DumpMemorySign.txt").c_str(),
false);
3554 this->
dumpSignatures((directory +
"/DumpMemorySign3.txt").c_str(),
true);
3555 this->
dumpMemoryTree((directory +
"/DumpMemoryTree.txt").c_str());
3571 fopen_s(&foutSign, fileNameSign,
"w");
3573 foutSign = fopen(fileNameSign,
"w");
3578 fprintf(foutSign,
"SignatureID WordsID...\n");
3579 const std::map<int, Signature *> & signatures = this->
getSignatures();
3580 for(std::map<int, Signature *>::const_iterator iter=signatures.begin(); iter!=signatures.end(); ++iter)
3582 fprintf(foutSign,
"%d ", iter->first);
3590 const std::multimap<int, int> &
ref = ss->
getWords();
3591 for(std::multimap<int, int>::const_iterator jter=ref.begin(); jter!=ref.end(); ++jter)
3593 const cv::Point3f & pt = ss->
getWords3()[jter->second];
3596 (pt.x != 0 || pt.y != 0 || pt.z != 0))
3598 fprintf(foutSign,
"%d ", (*jter).first);
3605 const std::multimap<int, int> &
ref = ss->
getWords();
3606 for(std::multimap<int, int>::const_iterator jter=ref.begin(); jter!=ref.end(); ++jter)
3608 fprintf(foutSign,
"%d ", (*jter).first);
3612 fprintf(foutSign,
"\n");
3623 fopen_s(&foutTree, fileNameTree,
"w");
3625 foutTree = fopen(fileNameTree,
"w");
3630 fprintf(foutTree,
"SignatureID Weight NbLoopClosureIds LoopClosureIds... NbChildLoopClosureIds ChildLoopClosureIds...\n");
3634 fprintf(foutTree,
"%d %d", i->first, i->second->getWeight());
3636 std::map<int, Link> loopIds, childIds;
3638 for(std::map<int, Link>::const_iterator iter = i->second->getLinks().begin();
3639 iter!=i->second->getLinks().end();
3645 if(iter->first < i->first)
3647 childIds.insert(*iter);
3649 else if(iter->second.from() != iter->second.to())
3651 loopIds.insert(*iter);
3656 fprintf(foutTree,
" %d", (
int)loopIds.size());
3657 for(std::map<int, Link>::const_iterator j=loopIds.begin(); j!=loopIds.end(); ++j)
3659 fprintf(foutTree,
" %d", j->first);
3662 fprintf(foutTree,
" %d", (
int)childIds.size());
3663 for(std::map<int, Link>::const_iterator j=childIds.begin(); j!=childIds.end(); ++j)
3665 fprintf(foutTree,
" %d", j->first);
3668 fprintf(foutTree,
"\n");
3678 unsigned long memoryUsage =
sizeof(
Memory);
3679 memoryUsage +=
_signatures.size() * (
sizeof(int)+
sizeof(std::map<int, Signature *>::iterator)) +
sizeof(std::map<int, Signature *>);
3682 memoryUsage += iter->second->getMemoryUsed(
true);
3688 memoryUsage +=
_stMem.size() * (
sizeof(int)+
sizeof(std::set<int>::iterator)) +
sizeof(std::set<int>);
3689 memoryUsage +=
_workingMem.size() * (
sizeof(int)+
sizeof(
double)+
sizeof(std::map<int, double>::iterator)) +
sizeof(std::map<int, double>);
3690 memoryUsage +=
_groundTruths.size() * (
sizeof(int)+
sizeof(
Transform)+12*
sizeof(float) +
sizeof(std::map<int, Transform>::iterator)) +
sizeof(std::map<int, Transform>);
3691 memoryUsage +=
_labels.size() * (
sizeof(int)+
sizeof(std::string) +
sizeof(std::map<int, std::string>::iterator)) +
sizeof(std::map<int, std::string>);
3692 for(std::map<int, std::string>::const_iterator iter=
_labels.begin(); iter!=
_labels.end(); ++iter)
3694 memoryUsage+=iter->second.size();
3696 memoryUsage +=
_landmarksIndex.size() * (
sizeof(int)+
sizeof(std::set<int>) +
sizeof(std::map<int, std::set<int> >::iterator)) +
sizeof(std::map<int, std::set<int> >);
3699 memoryUsage+=iter->second.size()*(
sizeof(int)+
sizeof(std::set<int>::iterator)) +
sizeof(std::set<int>);
3724 for(std::set<int>::reverse_iterator iter=
_stMem.rbegin(); iter!=
_stMem.rend(); ++iter)
3737 UDEBUG(
"Comparing with signature (%d)...",
id);
3757 if(stats) stats->
addStatistic(Statistics::kMemoryRehearsal_merged(), merged);
3758 if(stats) stats->
addStatistic(Statistics::kMemoryRehearsal_sim(), sim);
3760 UDEBUG(
"merged=%d, sim=%f t=%fs", merged, sim, timer.
ticks());
3764 if(stats) stats->
addStatistic(Statistics::kMemoryRehearsal_merged(), 0);
3765 if(stats) stats->
addStatistic(Statistics::kMemoryRehearsal_sim(), 0);
3777 std::map<int, Link>::const_iterator iter = oldS->
getLinks().find(newS->
id());
3778 if(iter != oldS->
getLinks().end() &&
3781 iter->second.from() != iter->second.to())
3784 UWARN(
"already merged, old=%d, new=%d", oldId, newId);
3789 UINFO(
"Rehearsal merging %d (w=%d) and %d (w=%d)",
3794 bool intermediateMerge =
false;
3795 if(!newS->
getLinks().empty() && !newS->
getLinks().begin()->second.transform().isNull())
3801 newS->
getLinks().begin()->second.transform().getTranslationAndEulerAngles(x,y,z, roll,pitch,yaw);
3810 UINFO(
"Rehearsal ignored because the robot has moved more than %f m or %f rad (\"Mem/RehearsalWeightIgnoredWhileMoving\"=true)",
3814 fullMerge = !isMoving && newS->
hasLink(oldS->
id());
3815 intermediateMerge = !isMoving && !newS->
hasLink(oldS->
id());
3819 fullMerge = newS->
hasLink(oldS->
id()) && newS->
getLinks().begin()->second.transform().isNull();
3821 UDEBUG(
"fullMerge=%s intermediateMerge=%s _idUpdatedToNewOneRehearsal=%s",
3822 fullMerge?
"true":
"false",
3823 intermediateMerge?
"true":
"false",
3836 const std::multimap<int, Link> & links = oldS->
getLinks();
3837 for(std::multimap<int, Link>::const_iterator iter = links.begin(); iter!=links.end(); ++iter)
3839 if(iter->second.from() != iter->second.to())
3841 Link link = iter->second;
3850 s->addLink(mergedLink.
inverse());
3856 UERROR(
"Didn't find neighbor %d of %d in RAM...", link.
to(), oldS->
id());
3905 oldS->
setWeight(intermediateMerge?-1:0);
3916 newS->
setWeight(intermediateMerge?-1:0);
3924 UERROR(
"newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, newId);
3928 UERROR(
"newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, oldId);
3937 int mapId = -1, weight;
3940 std::vector<float> velocity;
3943 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth, velocity, gps, sensors, lookInDatabase);
3953 std::vector<float> velocity;
3956 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth, velocity, gps, sensors, lookInDatabase);
3966 std::vector<float> velocity;
3969 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth, velocity, gps, sensors, lookInDatabase);
3982 std::vector<float> velocity;
3984 getNodeInfo(
id, odomPose, mapId, weight, label, stamp, groundTruth, velocity, gps, sensors, lookInDatabase);
3986 if(gps.
stamp() == 0.0)
3990 std::map<int, int> nearestIds;
3991 nearestIds =
getNeighborsId(
id, maxGraphDepth, lookInDatabase?-1:0,
true,
false,
true);
3992 std::multimap<int, int> nearestIdsSorted;
3993 for(std::map<int, int>::iterator iter=nearestIds.begin(); iter!=nearestIds.end(); ++iter)
3995 nearestIdsSorted.insert(std::make_pair(iter->second, iter->first));
3998 for(std::map<int, int>::iterator iter=nearestIdsSorted.begin(); iter!=nearestIdsSorted.end(); ++iter)
4004 std::list<std::pair<int, Transform> > path =
graph::computePath(s->
id(), id,
this, lookInDatabase);
4005 if(path.size() >= 2)
4009 offsetENU = localToENU*(s->
getPose().
rotation()*path.rbegin()->second);
4014 UWARN(
"Failed to find path %d -> %d", s->
id(), id);
4025 std::string & label,
4028 std::vector<float> & velocity,
4031 bool lookInDatabase)
const 4039 label = std::string(s->
getLabel());
4049 return _dbDriver->
getNodeInfo(signatureId, odomPose, mapId, weight, label, stamp, groundTruth, velocity, gps, sensors);
4085 r.
setRGBDImage(cv::Mat(), cv::Mat(), std::vector<CameraModel>());
4110 std::multimap<int, int> & words,
4111 std::vector<cv::KeyPoint> & wordsKpts,
4112 std::vector<cv::Point3f> & words3,
4113 cv::Mat & wordsDescriptors,
4114 std::vector<GlobalDescriptor> & globalDescriptors)
const 4129 std::list<Signature*> signatures;
4131 ids.push_back(nodeId);
4132 std::set<int> loadedFromTrash;
4134 if(signatures.size())
4136 words = signatures.front()->getWords();
4137 wordsKpts = signatures.front()->getWordsKpts();
4138 words3 = signatures.front()->getWords3();
4139 wordsDescriptors = signatures.front()->getWordsDescriptors();
4140 globalDescriptors = signatures.front()->sensorData().globalDescriptors();
4141 if(loadedFromTrash.size())
4148 delete signatures.front();
4155 std::vector<CameraModel> & models,
4156 std::vector<StereoCameraModel> & stereoModels)
const 4176 UERROR(
"A database must must loaded first...");
4184 const std::map<int, Transform> & poses,
4185 const cv::Mat & map,
4194 UERROR(
"A database must be loaded first...");
4198 if(poses.empty() || poses.lower_bound(1) == poses.end())
4212 for(std::map<int, Transform>::const_iterator iter=poses.lower_bound(1); iter!=poses.end(); ++iter)
4217 UINFO(
"Processing %d grids...", maxPoses);
4218 int processedGrids = 1;
4219 int gridsScansModified = 0;
4220 for(std::map<int, Transform>::const_iterator iter=poses.lower_bound(1); iter!=poses.end(); ++iter, ++processedGrids)
4224 cv::Mat gridObstacles;
4230 data.
uncompressData(0,0,&scan,0,&gridGround,&gridObstacles,&gridEmpty);
4232 if(!gridObstacles.empty())
4235 cv::Mat filtered = cv::Mat(1, gridObstacles.cols, gridObstacles.type());
4237 for(
int i=0; i<gridObstacles.cols; ++i)
4239 const float * ptr = gridObstacles.ptr<
float>(0, i);
4240 cv::Point3f pt(ptr[0], ptr[1], gridObstacles.channels()==2?0:ptr[2]);
4243 int x = int((pt.x - xMin) / cellSize + 0.5f);
4244 int y = int((pt.y - yMin) / cellSize + 0.5f);
4246 if(x>=0 && x<map.cols &&
4249 bool obstacleDetected =
false;
4251 for(
int j=-cropRadius; j<=cropRadius && !obstacleDetected; ++j)
4253 for(
int k=-cropRadius; k<=cropRadius && !obstacleDetected; ++k)
4255 if(x+j>=0 && x+j<map.cols &&
4256 y+k>=0 && y+k<map.rows &&
4257 map.at<
unsigned char>(y+k,x+j) == 100)
4259 obstacleDetected =
true;
4264 if(map.at<
unsigned char>(y,x) != 0 || obstacleDetected)
4273 if(oi != gridObstacles.cols)
4275 UINFO(
"Grid id=%d (%d/%d) filtered %d -> %d", iter->first, processedGrids, maxPoses, gridObstacles.cols, oi);
4276 gridsScansModified += 1;
4280 cv::Mat newObstacles = cv::Mat(filtered,
cv::Range::all(), cv::Range(0, oi));
4281 bool modifyDb =
true;
4303 if(filterScans && !scan.
isEmpty())
4307 cv::Mat filtered = cv::Mat(1, scan.
size(), scan.
dataType());
4309 for(
int i=0; i<scan.
size(); ++i)
4311 const float * ptr = scan.
data().ptr<
float>(0, i);
4312 cv::Point3f pt(ptr[0], ptr[1], scan.
is2d()?0:ptr[2]);
4315 int x = int((pt.x - xMin) / cellSize + 0.5f);
4316 int y = int((pt.y - yMin) / cellSize + 0.5f);
4318 if(x>=0 && x<map.cols &&
4321 bool obstacleDetected =
false;
4323 for(
int j=-cropRadius; j<=cropRadius && !obstacleDetected; ++j)
4325 for(
int k=-cropRadius; k<=cropRadius && !obstacleDetected; ++k)
4327 if(x+j>=0 && x+j<map.cols &&
4328 y+k>=0 && y+k<map.rows &&
4329 map.at<
unsigned char>(y+k,x+j) == 100)
4331 obstacleDetected =
true;
4336 if(map.at<
unsigned char>(y,x) != 0 || obstacleDetected)
4345 if(oi != scan.
size())
4347 UINFO(
"Scan id=%d (%d/%d) filtered %d -> %d", iter->first, processedGrids, maxPoses, (
int)scan.
size(), oi);
4348 gridsScansModified += 1;
4377 bool modifyDb =
true;
4380 s->sensorData().setLaserScan(scan,
true);
4395 return gridsScansModified;
4404 ni = (int)((
Signature *)s)->getWords().size();
4424 id.push_back(to->
id());
4430 UDEBUG(
"Loaded image data from database");
4442 ULOGGER_ERROR(
"Can't merge the signatures because there are not same type.");
4468 data.
imageRaw().type() == CV_8UC1 ||
4469 data.
imageRaw().type() == CV_8UC3);
4477 uFormat(
"image=(%d/%d, type=%d, [accepted=%d,%d]) depth=(%d/%d, type=%d [accepted=%d(depth mm),%d(depth m),%d(stereo)]). " 4478 "For stereo, left and right images should be same size. " 4479 "For RGB-D, depth can be X times smaller than RGB (where X is an integer).",
4488 CV_16UC1, CV_32FC1, CV_8UC1).c_str());
4495 UERROR(
"No camera calibration found, calibrate your camera!");
4505 std::vector<cv::KeyPoint> keypoints;
4506 cv::Mat descriptors;
4517 UERROR(
"Received image ID is null. " 4518 "Please set parameter Mem/GenerateIds to \"true\" or " 4519 "make sure the input source provides image ids (seq).");
4528 UERROR(
"Id of acquired image (%d) is smaller than the last in memory (%d). " 4529 "Please set parameter Mem/GenerateIds to \"true\" or " 4530 "make sure the input source provides image ids (seq) over the last in " 4531 "memory, which is %d.",
4546 UDEBUG(
"Monocular rectification");
4556 for(
unsigned int i=0; i<data.
cameraModels().size(); ++i)
4565 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)...", i);
4567 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)... done!", i);
4573 rectifiedImage.copyTo(cv::Mat(rectifiedImages, cv::Rect(subImageWidth*i, 0, subImageWidth, data.
imageRaw().rows)));
4574 imagesRectified =
true;
4578 UERROR(
"Calibration for camera %d cannot be used to rectify the image. Make sure to do a " 4579 "full calibration. If images are already rectified, set %s parameter back to true.",
4581 Parameters::kRtabmapImagesAlreadyRectified().c_str());
4590 UDEBUG(
"Stereo rectification");
4611 UWARN(
"Initializing rectification maps (only done for the first image received)...");
4613 UWARN(
"Initializing rectification maps (only done for the first image received)...done!");
4621 rectifiedLeft.copyTo(cv::Mat(rectifiedLefts, cv::Rect(subImageWidth*i, 0, subImageWidth, data.
imageRaw().rows)));
4622 rectifiedRight.copyTo(cv::Mat(rectifiedRights, cv::Rect(subImageWidth*i, 0, subImageWidth, data.
rightRaw().rows)));
4623 imagesRectified =
true;
4627 UERROR(
"Calibration for camera %d cannot be used to rectify the image. Make sure to do a " 4628 "full calibration. If images are already rectified, set %s parameter back to true.",
4630 Parameters::kRtabmapImagesAlreadyRectified().c_str());
4643 UERROR(
"Stereo calibration cannot be used to rectify images. Make sure to do a " 4644 "full stereo calibration. If images are already rectified, set %s parameter back to true.",
4645 Parameters::kRtabmapImagesAlreadyRectified().c_str());
4649 if(stats) stats->
addStatistic(Statistics::kTimingMemRectification(), t*1000.0
f);
4650 UDEBUG(
"time rectification = %fs", t);
4662 UDEBUG(
"Start dictionary update thread");
4663 preUpdateThread.
start();
4666 unsigned int preDecimation = 1;
4667 std::vector<cv::Point3f> keypoints3D;
4669 UDEBUG(
"Received kpts=%d kpts3D=%d, descriptors=%d _useOdometryFeatures=%s",
4678 decimatedData = data;
4689 if(targetSize >= data.
depthRaw().rows)
4691 decimationDepth = 1;
4695 decimationDepth = (int)
ceil(
float(data.
depthRaw().rows) /
float(targetSize));
4700 std::vector<CameraModel> cameraModels = decimatedData.
cameraModels();
4701 for(
unsigned int i=0; i<cameraModels.size(); ++i)
4705 if(!cameraModels.empty())
4713 std::vector<StereoCameraModel> stereoCameraModels = decimatedData.
stereoCameraModels();
4714 for(
unsigned int i=0; i<stereoCameraModels.size(); ++i)
4718 if(!stereoCameraModels.empty())
4723 stereoCameraModels);
4727 UINFO(
"Extract features");
4729 if(decimatedData.
imageRaw().channels() == 3)
4731 cv::cvtColor(decimatedData.
imageRaw(), imageMono, CV_BGR2GRAY);
4735 imageMono = decimatedData.
imageRaw();
4741 if(imageMono.rows % decimatedData.
depthRaw().rows == 0 &&
4742 imageMono.cols % decimatedData.
depthRaw().cols == 0 &&
4743 imageMono.rows/decimatedData.
depthRaw().rows == imageMono.cols/decimatedData.
depthRaw().cols)
4749 UWARN(
"%s is true, but RGB size (%dx%d) modulo depth size (%dx%d) is not 0. Ignoring depth mask for feature detection (%s=%d).",
4750 Parameters::kMemDepthAsMask().c_str(),
4751 imageMono.cols, imageMono.rows,
4757 bool useProvided3dPoints =
false;
4760 UDEBUG(
"Using provided keypoints (%d)", (
int)data.
keypoints().size());
4763 useProvided3dPoints = keypoints.size() == data.
keypoints3D().size();
4771 for(
unsigned int i=0; i < keypoints.size(); ++i)
4773 cv::KeyPoint & kpt = keypoints[i];
4776 kpt.pt.x *= decimationRatio;
4777 kpt.pt.y *= decimationRatio;
4778 kpt.size *= decimationRatio;
4779 kpt.octave += log2value;
4781 if(useProvided3dPoints)
4783 keypoints[i].class_id = i;
4805 if(tmpMaxFeatureParameter.size())
4807 tmpMaxFeatureParameter.at(Parameters::kKpMaxFeatures()) =
uNumber2Str(oldMaxFeatures);
4811 if(stats) stats->
addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0
f);
4812 UDEBUG(
"time keypoints (%d) = %fs", (
int)keypoints.size(), t);
4817 if(stats) stats->
addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0
f);
4818 UDEBUG(
"time descriptors (%d) = %fs", descriptors.rows, t);
4821 if(descriptors.rows && descriptors.rows <
_badSignRatio *
float(meanWordsPerLocation))
4823 descriptors = cv::Mat();
4827 if(!imagesRectified && decimatedData.
cameraModels().size())
4829 UASSERT_MSG((
int)keypoints.size() == descriptors.rows,
uFormat(
"%d vs %d", (
int)keypoints.size(), descriptors.rows).c_str());
4830 std::vector<cv::KeyPoint> keypointsValid;
4831 keypointsValid.reserve(keypoints.size());
4832 cv::Mat descriptorsValid;
4833 descriptorsValid.reserve(descriptors.rows);
4838 std::vector<cv::Point2f> pointsIn, pointsOut;
4839 cv::KeyPoint::convert(keypoints,pointsIn);
4842 #if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10))) 4845 cv::Mat D(1, 4, CV_64FC1);
4846 D.at<
double>(0,0) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,0);
4847 D.at<
double>(0,1) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,1);
4848 D.at<
double>(0,2) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,4);
4849 D.at<
double>(0,3) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,5);
4850 cv::fisheye::undistortPoints(pointsIn, pointsOut,
4858 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
4859 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
4864 cv::undistortPoints(pointsIn, pointsOut,
4870 UASSERT(pointsOut.size() == keypoints.size());
4871 for(
unsigned int i=0; i<pointsOut.size(); ++i)
4873 if(pointsOut.at(i).x>=0 && pointsOut.at(i).x<decimatedData.
cameraModels()[0].imageWidth() &&
4874 pointsOut.at(i).y>=0 && pointsOut.at(i).y<decimatedData.
cameraModels()[0].imageHeight())
4876 keypointsValid.push_back(keypoints.at(i));
4877 keypointsValid.back().pt.x = pointsOut.at(i).x;
4878 keypointsValid.back().pt.y = pointsOut.at(i).y;
4879 descriptorsValid.push_back(descriptors.row(i));
4887 for(
unsigned int i=0; i<keypoints.size(); ++i)
4889 int cameraIndex = int(keypoints.at(i).pt.x / subImageWidth);
4891 uFormat(
"cameraIndex=%d, models=%d, kpt.x=%f, subImageWidth=%f (Camera model image width=%d)",
4892 cameraIndex, (
int)decimatedData.
cameraModels().size(), keypoints[i].pt.x, subImageWidth, decimatedData.
cameraModels()[0].imageWidth()).c_str());
4894 std::vector<cv::Point2f> pointsIn, pointsOut;
4895 pointsIn.push_back(cv::Point2f(keypoints.at(i).pt.x-subImageWidth*cameraIndex, keypoints.at(i).pt.y));
4896 if(decimatedData.
cameraModels()[cameraIndex].D_raw().cols == 6)
4898 #if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10))) 4901 cv::Mat D(1, 4, CV_64FC1);
4902 D.at<
double>(0,0) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,0);
4903 D.at<
double>(0,1) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,1);
4904 D.at<
double>(0,2) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,4);
4905 D.at<
double>(0,3) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,5);
4906 cv::fisheye::undistortPoints(pointsIn, pointsOut,
4914 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
4915 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
4920 cv::undistortPoints(pointsIn, pointsOut,
4927 if(pointsOut[0].
x>=0 && pointsOut[0].
x<decimatedData.
cameraModels()[cameraIndex].imageWidth() &&
4928 pointsOut[0].y>=0 && pointsOut[0].y<decimatedData.
cameraModels()[cameraIndex].imageHeight())
4930 keypointsValid.push_back(keypoints.at(i));
4931 keypointsValid.back().pt.x = pointsOut[0].x + subImageWidth*cameraIndex;
4932 keypointsValid.back().pt.y = pointsOut[0].y;
4933 descriptorsValid.push_back(descriptors.row(i));
4938 keypoints = keypointsValid;
4939 descriptors = descriptorsValid;
4942 if(stats) stats->
addStatistic(Statistics::kTimingMemRectification(), t*1000.0f);
4943 UDEBUG(
"time rectification = %fs", t);
4946 if(useProvided3dPoints && keypoints.size() != data.
keypoints3D().size())
4948 UDEBUG(
"Using provided 3d points (%d->%d)", (
int)data.
keypoints3D().size(), (int)keypoints.size());
4949 keypoints3D.resize(keypoints.size());
4950 for(
size_t i=0; i<keypoints.size(); ++i)
4953 keypoints3D[i] = data.
keypoints3D()[keypoints[i].class_id];
4956 else if(useProvided3dPoints && keypoints.size() == data.
keypoints3D().size())
4966 if(stats) stats->
addStatistic(Statistics::kTimingMemKeypoints_3D(), t*1000.0
f);
4967 UDEBUG(
"time keypoints 3D (%d) = %fs", (
int)keypoints3D.size(), t);
4971 else if(
data.imageRaw().empty())
4973 UDEBUG(
"Empty image, cannot extract features...");
4981 UDEBUG(
"Intermediate node detected, don't extract features!");
4986 UINFO(
"Use odometry features: kpts=%d 3d=%d desc=%d (dim=%d, type=%d)",
4987 (
int)
data.keypoints().size(),
4988 (int)
data.keypoints3D().size(),
4989 data.descriptors().rows,
4990 data.descriptors().cols,
4991 data.descriptors().type());
4992 keypoints =
data.keypoints();
4993 keypoints3D =
data.keypoints3D();
4994 descriptors =
data.descriptors().clone();
4996 UASSERT(descriptors.empty() || descriptors.rows == (int)keypoints.size());
4997 UASSERT(keypoints3D.empty() || keypoints3D.size() == keypoints.size());
5000 if((
int)keypoints.size() > maxFeatures)
5005 if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0
f);
5006 UDEBUG(
"time keypoints (%d) = %fs", (
int)keypoints.size(), t);
5008 if(descriptors.empty())
5011 if(
data.imageRaw().channels() == 3)
5013 cv::cvtColor(
data.imageRaw(), imageMono, CV_BGR2GRAY);
5017 imageMono =
data.imageRaw();
5020 UASSERT_MSG(imagesRectified,
"Cannot extract descriptors on not rectified image from keypoints which assumed to be undistorted");
5023 else if(!imagesRectified && !
data.cameraModels().empty())
5025 std::vector<cv::KeyPoint> keypointsValid;
5026 keypointsValid.reserve(keypoints.size());
5027 cv::Mat descriptorsValid;
5028 descriptorsValid.reserve(descriptors.rows);
5029 std::vector<cv::Point3f> keypoints3DValid;
5030 keypoints3DValid.reserve(keypoints3D.size());
5033 if(
data.cameraModels().size() == 1)
5035 std::vector<cv::Point2f> pointsIn, pointsOut;
5036 cv::KeyPoint::convert(keypoints,pointsIn);
5037 if(
data.cameraModels()[0].D_raw().cols == 6)
5039 #if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10))) 5042 cv::Mat D(1, 4, CV_64FC1);
5043 D.at<
double>(0,0) =
data.cameraModels()[0].D_raw().at<
double>(0,0);
5044 D.at<
double>(0,1) =
data.cameraModels()[0].D_raw().at<
double>(0,1);
5045 D.at<
double>(0,2) =
data.cameraModels()[0].D_raw().at<
double>(0,4);
5046 D.at<
double>(0,3) =
data.cameraModels()[0].D_raw().at<
double>(0,5);
5047 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5048 data.cameraModels()[0].K_raw(),
5050 data.cameraModels()[0].R(),
5051 data.cameraModels()[0].P());
5055 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5056 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5061 cv::undistortPoints(pointsIn, pointsOut,
5062 data.cameraModels()[0].K_raw(),
5063 data.cameraModels()[0].D_raw(),
5064 data.cameraModels()[0].R(),
5065 data.cameraModels()[0].P());
5067 UASSERT(pointsOut.size() == keypoints.size());
5068 for(
unsigned int i=0; i<pointsOut.size(); ++i)
5070 if(pointsOut.at(i).x>=0 && pointsOut.at(i).x<
data.cameraModels()[0].imageWidth() &&
5071 pointsOut.at(i).y>=0 && pointsOut.at(i).y<
data.cameraModels()[0].imageHeight())
5073 keypointsValid.push_back(keypoints.at(i));
5074 keypointsValid.back().pt.x = pointsOut.at(i).x;
5075 keypointsValid.back().pt.y = pointsOut.at(i).y;
5076 descriptorsValid.push_back(descriptors.row(i));
5077 if(!keypoints3D.empty())
5079 keypoints3DValid.push_back(keypoints3D.at(i));
5086 float subImageWidth;
5087 if(!
data.imageRaw().empty())
5089 UASSERT(
int((
data.imageRaw().cols/
data.cameraModels().size())*
data.cameraModels().size()) ==
data.imageRaw().cols);
5090 subImageWidth =
data.imageRaw().cols/
data.cameraModels().size();
5095 subImageWidth =
data.cameraModels()[0].imageWidth();
5098 for(
unsigned int i=0; i<keypoints.size(); ++i)
5100 int cameraIndex = int(keypoints.at(i).pt.x / subImageWidth);
5101 UASSERT_MSG(cameraIndex >= 0 && cameraIndex < (
int)
data.cameraModels().size(),
5102 uFormat(
"cameraIndex=%d, models=%d, kpt.x=%f, subImageWidth=%f (Camera model image width=%d)",
5103 cameraIndex, (
int)
data.cameraModels().size(), keypoints[i].pt.x, subImageWidth,
data.cameraModels()[0].imageWidth()).c_str());
5105 std::vector<cv::Point2f> pointsIn, pointsOut;
5106 pointsIn.push_back(cv::Point2f(keypoints.at(i).pt.x-subImageWidth*cameraIndex, keypoints.at(i).pt.y));
5107 if(
data.cameraModels()[cameraIndex].D_raw().cols == 6)
5109 #if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10))) 5112 cv::Mat D(1, 4, CV_64FC1);
5113 D.at<
double>(0,0) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,0);
5114 D.at<
double>(0,1) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,1);
5115 D.at<
double>(0,2) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,4);
5116 D.at<
double>(0,3) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,5);
5117 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5118 data.cameraModels()[cameraIndex].K_raw(),
5120 data.cameraModels()[cameraIndex].R(),
5121 data.cameraModels()[cameraIndex].P());
5125 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5126 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5131 cv::undistortPoints(pointsIn, pointsOut,
5132 data.cameraModels()[cameraIndex].K_raw(),
5133 data.cameraModels()[cameraIndex].D_raw(),
5134 data.cameraModels()[cameraIndex].R(),
5135 data.cameraModels()[cameraIndex].P());
5138 if(pointsOut[0].
x>=0 && pointsOut[0].
x<
data.cameraModels()[cameraIndex].imageWidth() &&
5139 pointsOut[0].y>=0 && pointsOut[0].y<
data.cameraModels()[cameraIndex].imageHeight())
5141 keypointsValid.push_back(keypoints.at(i));
5142 keypointsValid.back().pt.x = pointsOut[0].x + subImageWidth*cameraIndex;
5143 keypointsValid.back().pt.y = pointsOut[0].y;
5144 descriptorsValid.push_back(descriptors.row(i));
5145 if(!keypoints3D.empty())
5147 keypoints3DValid.push_back(keypoints3D.at(i));
5153 keypoints = keypointsValid;
5154 descriptors = descriptorsValid;
5155 keypoints3D = keypoints3DValid;
5158 if(stats) stats->addStatistic(Statistics::kTimingMemRectification(), t*1000.0
f);
5159 UDEBUG(
"time rectification = %fs", t);
5162 if(stats) stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0
f);
5163 UDEBUG(
"time descriptors (%d) = %fs", descriptors.rows, t);
5165 if(keypoints3D.empty() &&
5166 ((!
data.depthRaw().empty() &&
data.cameraModels().size() &&
data.cameraModels()[0].isValidForProjection()) ||
5167 (!
data.rightRaw().empty() &&
data.stereoCameraModels().size() &&
data.stereoCameraModels()[0].isValidForProjection())))
5176 if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_3D(), t*1000.0f);
5177 UDEBUG(
"time keypoints 3D (%d) = %fs", (
int)keypoints3D.size(), t);
5180 if(descriptors.rows && descriptors.rows <
_badSignRatio *
float(meanWordsPerLocation))
5182 descriptors = cv::Mat();
5188 UDEBUG(
"Joining dictionary update thread...");
5189 preUpdateThread.join();
5190 UDEBUG(
"Joining dictionary update thread... thread finished!");
5194 if(stats) stats->addStatistic(Statistics::kTimingMemJoining_dictionary_update(), t*1000.0
f);
5197 UDEBUG(
"time descriptor and memory update (%d of size=%d) = %fs", descriptors.rows, descriptors.cols, t);
5201 UDEBUG(
"time descriptor (%d of size=%d) = %fs", descriptors.rows, descriptors.cols, t);
5204 std::list<int> wordIds;
5205 if(descriptors.rows)
5209 std::vector<bool> inliers;
5210 cv::Mat descriptorsForQuantization = descriptors;
5211 std::vector<int> quantizedToRawIndices;
5214 UASSERT((
int)keypoints.size() == descriptors.rows);
5215 int inliersCount = 0;
5219 for(
size_t i=0; i<inliers.size(); ++i)
5233 descriptorsForQuantization = cv::Mat(inliersCount, descriptors.cols, descriptors.type());
5234 quantizedToRawIndices.resize(inliersCount);
5236 UASSERT((
int)inliers.size() == descriptors.rows);
5237 for(
int k=0; k < descriptors.rows; ++k)
5241 UASSERT(oi < quantizedToRawIndices.size());
5242 if(descriptors.type() == CV_32FC1)
5244 memcpy(descriptorsForQuantization.ptr<
float>(oi), descriptors.ptr<
float>(k), descriptors.cols*
sizeof(
float));
5248 memcpy(descriptorsForQuantization.ptr<
char>(oi), descriptors.ptr<
char>(k), descriptors.cols*
sizeof(
char));
5250 quantizedToRawIndices[oi] = k;
5255 uFormat(
"oi=%d inliersCount=%d (maxFeatures=%d, grid=%dx%d)",
5263 if(wordIds.size() < keypoints.size())
5265 std::vector<int> allWordIds;
5266 allWordIds.resize(keypoints.size(),-1);
5268 for(std::list<int>::iterator iter=wordIds.begin(); iter!=wordIds.end(); ++iter)
5270 allWordIds[quantizedToRawIndices[i]] = *iter;
5274 for(i=0; i<(int)allWordIds.size(); ++i)
5276 if(allWordIds[i] < 0)
5278 allWordIds[i] = negIndex--;
5285 if(stats) stats->addStatistic(Statistics::kTimingMemAdd_new_words(), t*1000.0
f);
5290 UDEBUG(
"id %d is a bad signature",
id);
5293 std::multimap<int, int> words;
5294 std::vector<cv::KeyPoint> wordsKpts;
5295 std::vector<cv::Point3f> words3D;
5296 cv::Mat wordsDescriptors;
5297 int words3DValid = 0;
5298 if(wordIds.size() > 0)
5300 UASSERT(wordIds.size() == keypoints.size());
5301 UASSERT(keypoints3D.size() == 0 || keypoints3D.size() == wordIds.size());
5304 double log2value =
log(
double(preDecimation))/
log(2.0);
5305 for(std::list<int>::iterator iter=wordIds.begin(); iter!=wordIds.end() && i < keypoints.size(); ++iter, ++i)
5307 cv::KeyPoint kpt = keypoints[i];
5311 kpt.pt.x *= decimationRatio;
5312 kpt.pt.y *= decimationRatio;
5313 kpt.size *= decimationRatio;
5314 kpt.octave += log2value;
5316 words.insert(std::make_pair(*iter, words.size()));
5317 wordsKpts.push_back(kpt);
5319 if(keypoints3D.size())
5321 words3D.push_back(keypoints3D.at(i));
5329 wordsDescriptors.push_back(descriptors.row(i));
5337 UDEBUG(
"Detecting markers...");
5338 if(landmarks.empty())
5340 std::vector<CameraModel> models =
data.cameraModels();
5343 for(
size_t i=0; i<
data.stereoCameraModels().size(); ++i)
5345 models.push_back(
data.stereoCameraModels()[i].left());
5349 if(!models.empty() && models[0].isValidForProjection())
5353 for(std::map<int, MarkerInfo>::iterator iter=markers.begin(); iter!=markers.end(); ++iter)
5355 if(iter->first <= 0)
5357 UERROR(
"Invalid marker received! IDs should be > 0 (it is %d). Ignoring this marker.", iter->first);
5360 cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1);
5363 landmarks.insert(std::make_pair(iter->first,
Landmark(iter->first, iter->second.length(), iter->second.pose(), covariance)));
5365 UDEBUG(
"Markers detected = %d", (
int)markers.size());
5369 UWARN(
"No valid camera calibration for marker detection");
5374 UWARN(
"Input data has already landmarks, cannot do marker detection.");
5377 if(stats) stats->addStatistic(Statistics::kTimingMemMarkers_detection(), t*1000.0
f);
5378 UDEBUG(
"time markers detection = %fs", t);
5381 cv::Mat image =
data.imageRaw();
5382 cv::Mat depthOrRightImage =
data.depthOrRightRaw();
5383 std::vector<CameraModel> cameraModels =
data.cameraModels();
5384 std::vector<StereoCameraModel> stereoCameraModels =
data.stereoCameraModels();
5391 image = decimatedData.imageRaw();
5392 depthOrRightImage = decimatedData.depthOrRightRaw();
5393 cameraModels = decimatedData.cameraModels();
5394 stereoCameraModels = decimatedData.stereoCameraModels();
5399 if( !
data.cameraModels().empty() &&
5400 data.cameraModels()[0].imageHeight()>0 &&
5401 data.cameraModels()[0].imageWidth()>0)
5405 if(targetSize >=
data.depthRaw().rows)
5407 decimationDepth = 1;
5411 decimationDepth = (int)
ceil(
float(
data.depthRaw().rows) /
float(targetSize));
5418 for(
unsigned int i=0; i<cameraModels.size(); ++i)
5422 for(
unsigned int i=0; i<stereoCameraModels.size(); ++i)
5428 if(!image.empty() && (depthOrRightImage.cols > image.cols || depthOrRightImage.rows > image.rows))
5430 UWARN(
"Depth image is bigger than RGB image after post decimation, %s=%d is too high! RGB=%dx%d, depth=%dx%d",
5432 image.cols, image.rows, depthOrRightImage.cols, depthOrRightImage.rows);
5436 if(stats) stats->addStatistic(Statistics::kTimingMemPost_decimation(), t*1000.0
f);
5437 UDEBUG(
"time post-decimation = %fs", t);
5442 cameraModels.size() == 1 &&
5444 (words3D.size() == 0 || (words.size() == words3D.size() && words3DValid!=(int)words3D.size())) &&
5449 UDEBUG(
"Generate 3D words using odometry (%s=true and words3DValid=%d/%d)",
5450 Parameters::kMemStereoFromMotion().c_str(), words3DValid, (
int)words3D.size());
5452 if(previousS->getWords().size() > 8 && words.size() > 8 && !previousS->getPose().isNull())
5454 UDEBUG(
"Previous pose(%d) = %s", previousS->id(), previousS->getPose().prettyPrint().c_str());
5455 UDEBUG(
"Current pose(%d) = %s",
id, pose.prettyPrint().c_str());
5461 std::vector<cv::KeyPoint> uniqueWordsKpts;
5462 cv::Mat uniqueWordsDescriptors;
5463 std::multimap<int, int> uniqueWords;
5464 for(std::map<int, int>::iterator iter=uniqueWordsOld.begin(); iter!=uniqueWordsOld.end(); ++iter)
5466 uniqueWords.insert(std::make_pair(iter->first, uniqueWords.size()));
5467 uniqueWordsKpts.push_back(previousS->getWordsKpts()[iter->second]);
5468 uniqueWordsDescriptors.push_back(previousS->getWordsDescriptors().row(iter->second));
5471 cpPrevious.
setWords(uniqueWords, uniqueWordsKpts, std::vector<cv::Point3f>(), uniqueWordsDescriptors);
5474 uniqueWordsKpts.clear();
5475 uniqueWordsDescriptors = cv::Mat();
5476 uniqueWords.clear();
5477 for(std::map<int, int>::iterator iter=uniqueWordsOld.begin(); iter!=uniqueWordsOld.end(); ++iter)
5479 uniqueWords.insert(std::make_pair(iter->first, uniqueWords.size()));
5480 uniqueWordsKpts.push_back(wordsKpts[iter->second]);
5481 uniqueWordsDescriptors.push_back(wordsDescriptors.row(iter->second));
5485 cpCurrent.
setWords(uniqueWords, uniqueWordsKpts, std::vector<cv::Point3f>(), uniqueWordsDescriptors);
5505 std::map<int, cv::KeyPoint> currentWords;
5506 std::map<int, cv::KeyPoint> previousWords;
5507 for(std::map<int, int>::iterator iter=currentUniqueWords.begin(); iter!=currentUniqueWords.end(); ++iter)
5509 currentWords.insert(std::make_pair(iter->first, cpCurrent.
getWordsKpts()[iter->second]));
5511 for(std::map<int, int>::iterator iter=previousUniqueWords.begin(); iter!=previousUniqueWords.end(); ++iter)
5513 previousWords.insert(std::make_pair(iter->first, cpPrevious.
getWordsKpts()[iter->second]));
5521 UDEBUG(
"inliers=%d", (
int)inliers.size());
5524 float bad_point = std::numeric_limits<float>::quiet_NaN ();
5525 UASSERT(words3D.size() == 0 || words.size() == words3D.size());
5526 bool words3DWasEmpty = words3D.empty();
5527 int added3DPointsWithoutDepth = 0;
5528 for(std::multimap<int, int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
5530 std::map<int, cv::Point3f>::iterator jter=inliers.find(iter->first);
5533 if(jter != inliers.end())
5535 words3D.push_back(jter->second);
5536 ++added3DPointsWithoutDepth;
5540 words3D.push_back(cv::Point3f(bad_point,bad_point,bad_point));
5545 words3D[iter->second] = jter->second;
5546 ++added3DPointsWithoutDepth;
5549 UDEBUG(
"added3DPointsWithoutDepth=%d", added3DPointsWithoutDepth);
5550 if(stats) stats->addStatistic(Statistics::kMemoryTriangulated_points(), (
float)added3DPointsWithoutDepth);
5553 UASSERT(words3D.size() == words.size());
5554 if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_3D_motion(), t*1000.0
f);
5555 UDEBUG(
"time keypoints 3D by motion (%d) = %fs", (
int)words3D.size(), t);
5561 if(!isIntermediateNode && laserScan.size())
5563 if(laserScan.rangeMax() == 0.0f)
5565 bool id2d = laserScan.is2d();
5566 float maxRange = 0.0f;
5567 for(
int i=0; i<laserScan.size(); ++i)
5569 const float * ptr = laserScan.data().ptr<
float>(0, i);
5573 r = ptr[0]*ptr[0] + ptr[1]*ptr[1];
5577 r = ptr[0]*ptr[0] + ptr[1]*ptr[1] + ptr[2]*ptr[2];
5586 laserScan=
LaserScan(laserScan.data(), laserScan.maxPoints(),
sqrt(maxRange), laserScan.format(), laserScan.localTransform());
5599 if(stats) stats->addStatistic(Statistics::kTimingMemScan_filtering(), t*1000.0
f);
5600 UDEBUG(
"time normals scan = %fs", t);
5606 UDEBUG(
"Bin data kept: rgb=%d, depth=%d, scan=%d, userData=%d",
5608 depthOrRightImage.empty()?0:1,
5609 laserScan.isEmpty()?0:1,
5610 data.userDataRaw().empty()?0:1);
5612 std::vector<unsigned char> imageBytes;
5613 std::vector<unsigned char> depthBytes;
5615 if(
_saveDepth16Format && !depthOrRightImage.empty() && depthOrRightImage.type() == CV_32FC1)
5617 UWARN(
"Save depth data to 16 bits format: depth type detected is 32FC1, use 16UC1 depth format to avoid this conversion (or set parameter \"Mem/SaveDepth16Format\"=false to use 32bits format).");
5621 cv::Mat compressedImage;
5622 cv::Mat compressedDepth;
5623 cv::Mat compressedScan;
5624 cv::Mat compressedUserData;
5635 if(!depthOrRightImage.empty())
5639 if(!laserScan.isEmpty())
5641 ctLaserScan.start();
5643 if(!
data.userDataRaw().empty())
5653 compressedDepth = ctDepth.getCompressedData();
5654 compressedScan = ctLaserScan.getCompressedData();
5655 compressedUserData = ctUserData.getCompressedData();
5660 compressedDepth =
compressImage2(depthOrRightImage, depthOrRightImage.type() == CV_32FC1 || depthOrRightImage.type() == CV_16UC1?std::string(
".png"):
_rgbCompressionFormat);
5667 isIntermediateNode?-1:0,
5672 !stereoCameraModels.empty()?
5674 laserScan.angleIncrement() == 0.0f?
5676 laserScan.maxPoints(),
5677 laserScan.rangeMax(),
5679 laserScan.localTransform()):
5682 laserScan.rangeMin(),
5683 laserScan.rangeMax(),
5684 laserScan.angleMin(),
5685 laserScan.angleMax(),
5686 laserScan.angleIncrement(),
5687 laserScan.localTransform()),
5693 compressedUserData):
5695 laserScan.angleIncrement() == 0.0f?
5697 laserScan.maxPoints(),
5698 laserScan.rangeMax(),
5700 laserScan.localTransform()):
5703 laserScan.rangeMin(),
5704 laserScan.rangeMax(),
5705 laserScan.angleMin(),
5706 laserScan.angleMax(),
5707 laserScan.angleIncrement(),
5708 laserScan.localTransform()),
5714 compressedUserData));
5718 UDEBUG(
"Bin data kept: scan=%d, userData=%d",
5719 laserScan.isEmpty()?0:1,
5720 data.userDataRaw().empty()?0:1);
5723 cv::Mat compressedScan;
5724 cv::Mat compressedUserData;
5729 if(!
data.userDataRaw().empty() && !isIntermediateNode)
5733 if(!laserScan.isEmpty() && !isIntermediateNode)
5735 ctLaserScan.start();
5740 compressedScan = ctLaserScan.getCompressedData();
5741 compressedUserData = ctUserData.getCompressedData();
5751 isIntermediateNode?-1:0,
5756 !stereoCameraModels.empty()?
5758 laserScan.angleIncrement() == 0.0f?
5760 laserScan.maxPoints(),
5761 laserScan.rangeMax(),
5763 laserScan.localTransform()):
5766 laserScan.rangeMin(),
5767 laserScan.rangeMax(),
5768 laserScan.angleMin(),
5769 laserScan.angleMax(),
5770 laserScan.angleIncrement(),
5771 laserScan.localTransform()),
5777 compressedUserData):
5779 laserScan.angleIncrement() == 0.0f?
5781 laserScan.maxPoints(),
5782 laserScan.rangeMax(),
5784 laserScan.localTransform()):
5787 laserScan.rangeMin(),
5788 laserScan.rangeMax(),
5789 laserScan.angleMin(),
5790 laserScan.angleMax(),
5791 laserScan.angleIncrement(),
5792 laserScan.localTransform()),
5798 compressedUserData));
5806 if(!cameraModels.empty())
5817 UDEBUG(
"data.groundTruth() =%s",
data.groundTruth().prettyPrint().c_str());
5818 UDEBUG(
"data.gps() =%s",
data.gps().stamp()?
"true":
"false");
5819 UDEBUG(
"data.envSensors() =%d", (
int)
data.envSensors().size());
5820 UDEBUG(
"data.globalDescriptors()=%d", (
int)
data.globalDescriptors().size());
5827 if(stats) stats->addStatistic(Statistics::kTimingMemCompressing_data(), t*1000.0
f);
5828 UDEBUG(
"time compressing data (id=%d) %fs",
id, t);
5840 cv::Mat ground, obstacles, empty;
5841 float cellSize = 0.0f;
5842 cv::Point3f viewPoint(0,0,0);
5848 if(stats) stats->addStatistic(Statistics::kTimingMemOccupancy_grid(), t*1000.0
f);
5849 UDEBUG(
"time grid map = %fs", t);
5851 else if(
data.gridCellSize() != 0.0f)
5854 data.gridGroundCellsRaw(),
5855 data.gridObstacleCellsRaw(),
5856 data.gridEmptyCellsRaw(),
5857 data.gridCellSize(),
5858 data.gridViewPoint());
5863 if(!
data.globalPose().isNull() &&
data.globalPoseCovariance().cols==6 &&
data.globalPoseCovariance().rows==6 &&
data.globalPoseCovariance().cols==CV_64FC1)
5866 UDEBUG(
"Added global pose prior: %s",
data.globalPose().prettyPrint().c_str());
5868 if(
data.gps().stamp() > 0.0)
5870 UWARN(
"GPS constraint ignored as global pose is also set.");
5873 else if(
data.gps().stamp() > 0.0)
5880 data.gps().error() > 0.0)
5885 UINFO(
"Added GPS origin: long=%f lat=%f alt=%f bearing=%f error=%f",
data.gps().longitude(),
data.gps().latitude(),
data.gps().altitude(),
data.gps().bearing(),
data.gps().error());
5888 Transform gpsPose(pt.x, pt.y, pose.z(), 0, 0, -(
data.gps().bearing()-90.0)*
M_PI/180.0);
5889 cv::Mat gpsInfMatrix = cv::Mat::eye(6,6,CV_64FC1)/9999.0;
5891 UDEBUG(
"Added GPS prior: x=%f y=%f z=%f yaw=%f", gpsPose.
x(), gpsPose.
y(), gpsPose.
z(), gpsPose.
theta());
5893 gpsInfMatrix.at<
double>(0,0) = gpsInfMatrix.at<
double>(1,1) = 1.0/
data.gps().error();
5894 gpsInfMatrix.at<
double>(2,2) = 1;
5899 UERROR(
"Invalid GPS value: long=%f lat=%f alt=%f bearing=%f error=%f",
data.gps().longitude(),
data.gps().latitude(),
data.gps().altitude(),
data.gps().bearing(),
data.gps().error());
5907 UDEBUG(
"Added gravity constraint from odom pose: %s", pose.rotation().prettyPrint().c_str());
5909 else if(!
data.imu().localTransform().isNull() &&
5910 (
data.imu().orientation()[0] != 0 ||
5911 data.imu().orientation()[1] != 0 ||
5912 data.imu().orientation()[2] != 0 ||
5913 data.imu().orientation()[3] != 0))
5921 UDEBUG(
"Added gravity constraint: %s", orientation.prettyPrint().c_str());
5925 for(Landmarks::const_iterator iter = landmarks.begin(); iter!=landmarks.end(); ++iter)
5927 if(iter->second.id() > 0)
5929 int landmarkId = -iter->first;
5930 cv::Mat landmarkSize;
5931 if(iter->second.size() > 0.0f)
5933 landmarkSize = cv::Mat(1,1,CV_32FC1);
5934 landmarkSize.at<
float>(0,0) = iter->second.size();
5936 std::pair<std::map<int, float>::iterator,
bool> inserted=
_landmarksSize.insert(std::make_pair(iter->first, iter->second.size()));
5937 if(!inserted.second)
5939 if(inserted.first->second != landmarkSize.at<
float>(0,0))
5941 UWARN(
"Trying to update landmark size buffer for landmark %d with size=%f but " 5942 "it has already a different size set. Keeping old size (%f).",
5943 -landmarkId, inserted.first->second, landmarkSize.at<
float>(0,0));
5949 Transform landmarkPose = iter->second.pose();
5955 if(fabs(tx.
z()) > 0.9)
5959 else if(fabs(ty.
z()) > 0.9)
5965 Link landmark(s->
id(), landmarkId,
Link::kLandmark, landmarkPose, iter->second.covariance().inv(), landmarkSize);
5969 std::map<int, std::set<int> >::iterator nter =
_landmarksIndex.find(landmarkId);
5972 nter->second.insert(s->
id());
5977 tmp.insert(s->
id());
5983 UERROR(
"Invalid landmark received! IDs should be > 0 (it is %d). Ignoring this landmark.", iter->second.id());
5992 UDEBUG(
"id=%d", signatureId);
5997 const std::multimap<int, int> & words = ss->
getWords();
6001 for(std::list<int>::const_iterator i=keys.begin(); i!=keys.end(); ++i)
6016 if(removedWords.size())
6021 for(
unsigned int i=0; i<removedWords.size(); ++i)
6029 delete removedWords[i];
6037 UDEBUG(
"size=%d", signatureIds.size());
6041 std::map<int, int> refsToChange;
6043 std::set<int> oldWordIds;
6044 std::list<Signature *> surfSigns;
6045 for(std::list<int>::const_iterator i=signatureIds.begin(); i!=signatureIds.end(); ++i)
6050 surfSigns.push_back(ss);
6054 for(std::list<int>::const_iterator k=uniqueKeys.begin(); k!=uniqueKeys.end(); ++k)
6058 oldWordIds.insert(oldWordIds.end(), *k);
6066 UWARN(
"Dictionary is fixed, but some words retrieved have not been found!?");
6069 UDEBUG(
"oldWordIds.size()=%d, getOldIds time=%fs", oldWordIds.size(), timer.ticks());
6072 std::list<VisualWord *> vws;
6078 UDEBUG(
"loading words(%d) time=%fs", oldWordIds.size(), timer.ticks());
6084 std::vector<int> vwActiveIds =
_vwd->
findNN(vws);
6085 UDEBUG(
"find active ids (number=%d) time=%fs", vws.size(), timer.ticks());
6087 for(std::list<VisualWord *>::iterator iterVws=vws.begin(); iterVws!=vws.end(); ++iterVws)
6089 if(vwActiveIds[i] > 0)
6092 refsToChange.insert(refsToChange.end(), std::pair<int, int>((*iterVws)->id(), vwActiveIds[i]));
6093 if((*iterVws)->isSaved())
6109 UDEBUG(
"Added %d to dictionary, time=%fs", vws.size()-refsToChange.size(), timer.ticks());
6112 for(std::map<int, int>::const_iterator iter=refsToChange.begin(); iter != refsToChange.end(); ++iter)
6115 for(std::list<Signature *>::iterator j=surfSigns.begin(); j!=surfSigns.end(); ++j)
6117 (*j)->changeWordsRef(iter->first, iter->second);
6120 UDEBUG(
"changing ref, total=%d, time=%fs", refsToChange.size(), timer.ticks());
6126 for(std::list<Signature *>::iterator j=surfSigns.begin(); j!=surfSigns.end(); ++j)
6128 const std::vector<int> & keys =
uKeys((*j)->getWords());
6132 for(
unsigned int i=0; i<keys.size(); ++i)
6139 (*j)->setEnabled(
true);
6144 UDEBUG(
"%d words total ref added from %d signatures, time=%fs...", count, surfSigns.size(), timer.ticks());
6155 std::list<int> idsToLoad;
6156 std::map<int, int>::iterator wmIter;
6157 for(std::list<int>::const_iterator i=ids.begin(); i!=ids.end(); ++i)
6161 if(!maxLoaded || idsToLoad.size() < maxLoaded)
6163 idsToLoad.push_back(*i);
6164 UINFO(
"Loading location %d from database...", *i);
6169 UDEBUG(
"idsToLoad = %d", idsToLoad.size());
6171 std::list<Signature *> reactivatedSigns;
6177 std::list<int> idsLoaded;
6178 for(std::list<Signature *>::iterator i=reactivatedSigns.begin(); i!=reactivatedSigns.end(); ++i)
6180 if(!(*i)->getLandmarks().empty())
6183 for(std::map<int, Link>::const_iterator iter = (*i)->getLandmarks().begin(); iter!=(*i)->getLandmarks().end(); ++iter)
6185 int landmarkId = iter->first;
6188 cv::Mat landmarkSize = iter->second.uncompressUserDataConst();
6189 if(!landmarkSize.empty() && landmarkSize.type() == CV_32FC1 && landmarkSize.total()==1)
6191 std::pair<std::map<int, float>::iterator,
bool> inserted=
_landmarksSize.insert(std::make_pair(-landmarkId, landmarkSize.at<
float>(0,0)));
6192 if(!inserted.second)
6194 if(inserted.first->second != landmarkSize.at<
float>(0,0))
6196 UWARN(
"Trying to update landmark size buffer for landmark %d with size=%f but " 6197 "it has already a different size set. Keeping old size (%f).",
6198 -landmarkId, inserted.first->second, landmarkSize.at<
float>(0,0));
6203 std::map<int, std::set<int> >::iterator nter =
_landmarksIndex.find(landmarkId);
6206 nter->second.insert((*i)->id());
6211 tmp.insert((*i)->id());
6217 idsLoaded.push_back((*i)->id());
6223 return std::set<int>(idsToLoad.begin(), idsToLoad.end());
6229 const std::set<int> & ids,
6230 std::map<int, Transform> & poses,
6231 std::multimap<int, Link> & links,
6232 bool lookInDatabase,
6233 bool landmarksAdded)
6236 for(std::set<int>::const_iterator iter=ids.begin(); iter!=ids.end(); ++iter)
6241 poses.insert(std::make_pair(*iter, pose));
6245 for(std::set<int>::const_iterator iter=ids.begin(); iter!=ids.end(); ++iter)
6249 std::multimap<int, Link> tmpLinks =
getLinks(*iter, lookInDatabase,
true);
6250 for(std::multimap<int, Link>::iterator jter=tmpLinks.begin(); jter!=tmpLinks.end(); ++jter)
6252 std::multimap<int, Link>::iterator addedLinksIterator =
graph::findLink(links, *iter, jter->first);
6253 if( jter->second.isValid() &&
6254 (addedLinksIterator == links.end() || addedLinksIterator->second.from()==addedLinksIterator->second.to()) &&
6257 if(!lookInDatabase &&
6265 Link link = jter->second;
6272 std::multimap<int, Link>::iterator uter = n.upper_bound(s->
id());
6278 link = link.
merge(uter->second, uter->second.type());
6279 poses.erase(s->
id());
6289 links.insert(std::make_pair(*iter, link));
6293 links.insert(std::make_pair(*iter, jter->second));
6298 links.insert(std::make_pair(*iter, jter->second));
6300 else if(landmarksAdded)
6304 poses.insert(std::make_pair(jter->first, poses.at(*iter) * jter->second.transform()));
6306 links.insert(std::make_pair(jter->first, jter->second.inverse()));
GLM_FUNC_DECL genType log(genType const &x)
bool getNodeInfo(int signatureId, Transform &odomPose, int &mapId, int &weight, std::string &label, double &stamp, Transform &groundTruth, std::vector< float > &velocity, GPS &gps, EnvSensors &sensors, bool lookInDatabase=false) const
std::list< K > uUniqueKeys(const std::multimap< K, V > &mm)
GLM_FUNC_DECL T roll(detail::tquat< T, P > const &x)
bool RTABMAP_EXP isFinite(const cv::Point3f &pt)
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
void removeLink(int idA, int idB)
int getMinVisualCorrespondences() const
OccupancyGrid * _occupancy
Link merge(const Link &link, Type outputType) const
float getMinDepth() const
bool labelSignature(int id, const std::string &label)
void clearCompressedData(bool images=true, bool scan=true, bool userData=true)
Transform computeTransformationMod(Signature &from, Signature &to, Transform guess=Transform::getIdentity(), RegistrationInfo *info=0) const
int cleanupLocalGrids(const std::map< int, Transform > &poses, const cv::Mat &map, float xMin, float yMin, float cellSize, int cropRadius=1, bool filterScans=false)
void saveOptimizedMesh(const cv::Mat &cloud, const std::vector< std::vector< std::vector< RTABMAP_PCL_INDEX > > > &polygons=std::vector< std::vector< std::vector< RTABMAP_PCL_INDEX > > >(), const std::vector< std::vector< Eigen::Vector2f > > &texCoords=std::vector< std::vector< Eigen::Vector2f > >(), const cv::Mat &textures=cv::Mat()) const
const cv::Size & imageSize() const
std::map< K, V > uMultimapToMapUnique(const std::multimap< K, V > &m)
std::map< int, int > getNeighborsId(int signatureId, int maxGraphDepth, int maxCheckedInDatabase=-1, bool incrementMarginOnLoop=false, bool ignoreLoopIds=false, bool ignoreIntermediateNodes=false, bool ignoreLocalSpaceLoopIds=false, const std::set< int > &nodesSet=std::set< int >(), double *dbAccessTime=0) const
void loadLastNodes(std::list< Signature *> &signatures) const
void clearRawData(bool images=true, bool scan=true, bool userData=true)
void asyncSave(Signature *s)
cv::Mat load2DMap(float &xMin, float &yMin, float &cellSize) const
static void limitKeypoints(std::vector< cv::KeyPoint > &keypoints, int maxKeypoints)
Signature * _lastSignature
void addSignatureToWmFromLTM(Signature *signature)
void getAllLabels(std::map< int, std::string > &labels) const
virtual Feature2D::Type getType() const =0
void save2DMap(const cv::Mat &map, float xMin, float yMin, float cellSize) const
void setOccupancyGrid(const cv::Mat &ground, const cv::Mat &obstacles, const cv::Mat &empty, float cellSize, const cv::Point3f &viewPoint)
float _similarityThreshold
float getMaxDepth() const
bool operator<(const WeightAgeIdKey &k) const
int getLastSignatureId() const
void getLastMapId(int &mapId) const
const double & stamp() const
std::multimap< int, Link >::iterator RTABMAP_EXP findLink(std::multimap< int, Link > &links, int from, int to, bool checkBothWays=true, Link::Type type=Link::kUndef)
float getCellSize() const
static void post(UEvent *event, bool async=true, const UEventsSender *sender=0)
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
std::string getDatabaseUrl() const
const Transform & getGroundTruthPose() const
const std::vector< cv::Point3f > & keypoints3D() const
void load(VWDictionary *dictionary, bool lastStateOnly=true) const
cv::Mat loadPreviewImage() const
std::vector< K > uKeys(const std::multimap< K, V > &mm)
void loadWords(const std::set< int > &wordIds, std::list< VisualWord *> &vws)
void updateLaserScan(int nodeId, const LaserScan &scan)
std::map< int, int > getWeights() const
const std::vector< float > & getVelocity() const
bool _localizationDataSaved
void setLaserScan(const LaserScan &laserScan, bool clearPreviousData=true)
virtual bool isInMemory() const
void setIterations(int iterations)
bool _imagesAlreadyRectified
std::map< int, cv::Point3f > RTABMAP_EXP generateWords3DMono(const std::map< int, cv::KeyPoint > &kpts, const std::map< int, cv::KeyPoint > &previousKpts, const CameraModel &cameraModel, Transform &cameraTransform, float ransacReprojThreshold=3.0f, float ransacConfidence=0.99f, const std::map< int, cv::Point3f > &refGuess3D=std::map< int, cv::Point3f >(), double *variance=0, std::vector< int > *matchesOut=0)
const LaserScan & laserScanCompressed() const
virtual void parseParameters(const ParametersMap ¶meters)
bool memoryChanged() const
void removeVirtualLinks(int signatureId)
#define ULOGGER_INFO(...)
void removeRawData(int id, bool image=true, bool scan=true, bool userData=true)
Signature * _getSignature(int id) const
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
void getInvertedIndexNi(int signatureId, int &ni) const
const Signature * getLastWorkingSignature() const
std::map< int, Transform > loadOptimizedPoses(Transform *lastlocalizationPose) const
pcl::PointCloud< pcl::PointXYZRGBNormal >::Ptr RTABMAP_EXP laserScanToPointCloudRGBNormal(const LaserScan &laserScan, const Transform &transform=Transform(), unsigned char r=100, unsigned char g=100, unsigned char b=100)
std::pair< std::string, std::string > ParametersPair
void saveOptimizedPoses(const std::map< int, Transform > &optimizedPoses, const Transform &lastlocalizationPose) const
const VisualWord * getWord(int id) const
bool isIncremental() const
const cv::Mat & getWordsDescriptors() const
bool UTILITE_EXP uStr2Bool(const char *str)
std::map< int, MarkerInfo > detect(const cv::Mat &image, const std::vector< CameraModel > &models, const cv::Mat &depth=cv::Mat(), const std::map< int, float > &markerLengths=std::map< int, float >(), cv::Mat *imageWithDetections=0)
bool _transferSortingByWeightId
std::map< int, float > _landmarksSize
bool isGridFromDepth() const
void generateGraph(const std::string &fileName, const std::set< int > &ids=std::set< int >())
bool _tfIdfLikelihoodUsed
const cv::Mat & depthOrRightRaw() const
void setReducedIds(const std::map< int, int > &reducedIds)
void getNodeCalibration(int nodeId, std::vector< CameraModel > &models, std::vector< StereoCameraModel > &stereoModels) const
unsigned long getMemoryUsed() const
Transform getOdomPose(int signatureId, bool lookInDatabase=false) const
Transform computeTransformation(const Signature &from, const Signature &to, Transform guess=Transform::getIdentity(), RegistrationInfo *info=0) const
void getMetricConstraints(const std::set< int > &ids, std::map< int, Transform > &poses, std::multimap< int, Link > &links, bool lookInDatabase=false, bool landmarksAdded=false)
void saveOptimizedMesh(const cv::Mat &cloud, const std::vector< std::vector< std::vector< RTABMAP_PCL_INDEX > > > &polygons=std::vector< std::vector< std::vector< RTABMAP_PCL_INDEX > > >(), const std::vector< std::vector< Eigen::Vector2f > > &texCoords=std::vector< std::vector< Eigen::Vector2f > >(), const cv::Mat &textures=cv::Mat()) const
Signature * createSignature(const SensorData &data, const Transform &pose, Statistics *stats=0)
std::map< int, Landmark > Landmarks
const cv::Mat & userDataCompressed() const
VisualWord * getUnusedWord(int id) const
GLM_FUNC_DECL bool all(vecType< bool, P > const &v)
void removeWords(const std::vector< VisualWord *> &words)
void setRGBDImage(const cv::Mat &rgb, const cv::Mat &depth, const CameraModel &model, bool clearPreviousData=true)
const std::vector< StereoCameraModel > & stereoCameraModels() const
bool _compressionParallelized
virtual std::list< int > addNewWords(const cv::Mat &descriptors, int signatureId)
const cv::Mat & data() const
std::map< std::string, std::string > ParametersMap
const std::vector< cv::KeyPoint > & keypoints() const
void removeVirtualLinks()
const std::vector< cv::Point3f > & getWords3() const
std::multimap< int, Link > RTABMAP_EXP filterLinks(const std::multimap< int, Link > &links, Link::Type filteredType, bool inverted=false)
void close(bool databaseSaved=true, bool postInitClosingEvents=false, const std::string &ouputDatabasePath="")
void setCameraModels(const std::vector< CameraModel > &models)
Transform computeIcpTransform(const Signature &fromS, const Signature &toS, Transform guess, RegistrationInfo *info=0) const
Basic mathematics functions.
void addWordRef(int wordId, int signatureId)
void exportDictionary(const char *fileNameReferences, const char *fileNameDescriptors) const
void setGPS(const GPS &gps)
const std::map< int, VisualWord * > & getVisualWords() const
std::vector< int > inliersIDs
std::map< int, Link > getNodesObservingLandmark(int landmarkId, bool lookInDatabase) const
Memory(const ParametersMap ¶meters=ParametersMap())
Some conversion functions.
Registration * _registrationPipeline
float compareTo(const Signature &signature) const
void loadLinks(int signatureId, std::multimap< int, Link > &links, Link::Type type=Link::kUndef) const
int getSignatureIdByLabel(const std::string &label, bool lookInDatabase=true) const
unsigned int getUnusedWordsSize() const
const std::map< int, Signature * > & getSignatures() const
const std::string & getLabel() const
bool isBinDataKept() const
GLM_FUNC_DECL T pitch(detail::tquat< T, P > const &x)
void deleteLocation(int locationId, std::list< int > *deletedWords=0)
bool isIncremental() const
void getNodesObservingLandmark(int landmarkId, std::map< int, Link > &nodes) const
double getEmptyTrashesTime() const
unsigned long getMemoryUsed() const
bool isIncrementalFlann() const
void addInfoAfterRun(int stMemSize, int lastSignAdded, int processMemUsed, int databaseMemUsed, int dictionarySize, const ParametersMap ¶meters) const
const std::vector< GlobalDescriptor > & globalDescriptors() const
void addStatistics(const Statistics &statistics, bool saveWmState) const
bool _reextractLoopClosureFeatures
std::vector< cv::KeyPoint > generateKeypoints(const cv::Mat &image, const cv::Mat &mask=cv::Mat())
void setEnabled(bool enabled)
virtual std::map< int, Transform > optimizeBA(int rootId, const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const std::map< int, std::vector< CameraModel > > &models, std::map< int, cv::Point3f > &points3DMap, const std::map< int, std::map< int, FeatureBA > > &wordReferences, std::set< int > *outliers=0)
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP laserScanToPointCloud(const LaserScan &laserScan, const Transform &transform=Transform())
std::multimap< int, Link > getNeighborLinks(int signatureId, bool lookInDatabase=false) const
double getDbSavingTime() const
void generateGraph(const std::string &fileName, const std::set< int > &ids=std::set< int >(), const std::map< int, Signature *> &otherSignatures=std::map< int, Signature *>())
std::map< int, Transform > loadOptimizedPoses(Transform *lastlocalizationPose=0) const
void saveOptimizedPoses(const std::map< int, Transform > &optimizedPoses, const Transform &lastlocalizationPose) const
void saveLocationData(int locationId)
float gridCellSize() const
PreUpdateThread(VWDictionary *vwp)
void getLastNodeId(int &id) const
bool isBadSignature() const
const Signature * getSignature(int id) const
bool init(const std::string &dbUrl, bool dbOverwritten=false, const ParametersMap ¶meters=ParametersMap(), bool postInitClosingEvents=false)
void getGPS(int id, GPS &gps, Transform &offsetENU, bool lookInDatabase, int maxGraphDepth=0) const
const std::map< int, Link > & getLandmarks() const
cv::Mat RTABMAP_EXP interpolate(const cv::Mat &image, int factor, float depthErrorRatio=0.02f)
bool uIsFinite(const T &value)
void moveToTrash(Signature *s, bool keepLinkedToGraph=true, std::list< int > *deletedWords=0)
bool openConnection(const std::string &url, bool overwritten=false)
void getAllLinks(std::multimap< int, Link > &links, bool ignoreNullLinks=true, bool withLandmarks=false) const
const std::vector< cv::KeyPoint > & getWordsKpts() const
std::map< int, std::string > _labels
#define UASSERT(condition)
std::vector< cv::Point3f > generateKeypoints3D(const SensorData &data, const std::vector< cv::KeyPoint > &keypoints) const
int getNi(int signatureId) const
void setLastWordId(int id)
float _laserScanGroundNormalsUp
void saveStatistics(const Statistics &statistics, bool saveWMState)
unsigned long getMemoryUsed() const
const double & bearing() const
std::set< int > reactivateSignatures(const std::list< int > &ids, unsigned int maxLoaded, double &timeDbAccess)
pcl::PointCloud< pcl::PointXYZRGB >::Ptr RTABMAP_EXP laserScanToPointCloudRGB(const LaserScan &laserScan, const Transform &transform=Transform(), unsigned char r=100, unsigned char g=100, unsigned char b=100)
unsigned int _imagePreDecimation
unsigned int _imagePostDecimation
virtual void parseParameters(const ParametersMap ¶meters)
const std::vector< CameraModel > & cameraModels() const
LaserScan RTABMAP_EXP commonFiltering(const LaserScan &scan, int downsamplingStep, float rangeMin=0.0f, float rangeMax=0.0f, float voxelSize=0.0f, int normalK=0, float normalRadius=0.0f, float groundNormalsUp=0.0f)
const cv::Mat & getCompressedData() const
T uMax3(const T &a, const T &b, const T &c)
void removeLinks(bool keepSelfReferringLinks=false)
virtual void dumpSignatures(const char *fileNameSign, bool words3D) const
static Feature2D * create(const ParametersMap ¶meters=ParametersMap())
Transform computeTransform(Signature &fromS, Signature &toS, Transform guess, RegistrationInfo *info=0, bool useKnownCorrespondencesIfPossible=false) const
void setWeight(int weight)
const std::multimap< int, Link > & getLinks() const
bool isScanRequired() const
void addLandmark(const Link &landmark)
void save2DMap(const cv::Mat &map, float xMin, float yMin, float cellSize) const
bool getNodeInfo(int signatureId, Transform &pose, int &mapId, int &weight, std::string &label, double &stamp, Transform &groundTruthPose, std::vector< float > &velocity, GPS &gps, EnvSensors &sensors) const
#define UASSERT_MSG(condition, msg_str)
void closeConnection(bool save=true, const std::string &outputUrl="")
pcl::PointCloud< pcl::PointXYZINormal >::Ptr RTABMAP_EXP laserScanToPointCloudINormal(const LaserScan &laserScan, const Transform &transform=Transform(), float intensity=0.0f)
bool update(const SensorData &data, Statistics *stats=0)
float _laserScanDownsampleStepSize
const cv::Mat & imageRaw() const
void rehearsal(Signature *signature, Statistics *stats=0)
cv::Mat RTABMAP_EXP decimate(const cv::Mat &image, int d)
bool getCalibration(int signatureId, std::vector< CameraModel > &models, std::vector< StereoCameraModel > &stereoModels) const
void getAllNodeIds(std::set< int > &ids, bool ignoreChildren=false, bool ignoreBadSignatures=false, bool ignoreIntermediateNodes=false) const
void savePreviewImage(const cv::Mat &image) const
const EnvSensors & envSensors() const
cv::Mat loadPreviewImage() const
int getTotalActiveReferences() const
void disableWordsRef(int signatureId)
virtual void parseParameters(const ParametersMap ¶meters)
const cv::Mat & descriptors() const
bool hasLink(int idTo, Link::Type type=Link::kUndef) const
const std::map< int, int > & getReferences() const
unsigned int getNotIndexedWordsCount() const
std::vector< int > findNN(const std::list< VisualWord *> &vws) const
void getNodeData(int signatureId, SensorData &data, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const
bool isImageRequired() const
std::list< V > uVectorToList(const std::vector< V > &v)
WeightAgeIdKey(int w, double a, int i)
void setWordsDescriptors(const cv::Mat &descriptors)
const Transform & localTransform() const
static void filterKeypointsByDepth(std::vector< cv::KeyPoint > &keypoints, const cv::Mat &depth, float minDepth, float maxDepth)
bool _localBundleOnLoopClosure
void setVelocity(float vx, float vy, float vz, float vroll, float vpitch, float vyaw)
RegistrationIcp * _registrationIcpMulti
void clear(bool printWarningsIfNotEmpty=true)
void updateLink(const Link &link)
LaserScan laserScanFromPointCloud(const PointCloud2T &cloud, bool filterNaNs, bool is2D, const Transform &transform)
std::list< std::pair< int, Transform > > RTABMAP_EXP computePath(const std::map< int, rtabmap::Transform > &poses, const std::multimap< int, int > &links, int from, int to, bool updateNewCosts=false)
static const int kIdStart
std::map< int, float > getNeighborsIdRadius(int signatureId, float radius, const std::map< int, Transform > &optimizedPoses, int maxGraphDepth) const
void setStereoImage(const cv::Mat &left, const cv::Mat &right, const StereoCameraModel &stereoCameraModel, bool clearPreviousData=true)
bool _createOccupancyGrid
std::list< int > forget(const std::set< int > &ignoredIds=std::set< int >())
cv::Mat RTABMAP_EXP compressData2(const cv::Mat &data)
static const int kIdInvalid
static ULogger::Level level()
void moveSignatureToWMFromSTM(int id, int *reducedTo=0)
std::list< Signature * > getRemovableSignatures(int count, const std::set< int > &ignoredIds=std::set< int >())
std::multimap< int, Link > getLoopClosureLinks(int signatureId, bool lookInDatabase=false) const
float _laserScanVoxelSize
void setEnvSensors(const EnvSensors &sensors)
bool _rectifyOnlyFeatures
GeodeticCoords toGeodeticCoords() const
bool uContains(const std::list< V > &list, const V &value)
SensorData getNodeData(int locationId, bool images, bool scan, bool userData, bool occupancyGrid) const
int getDatabaseMemoryUsed() const
void setPose(const Transform &pose)
void setSaved(bool saved)
void setLabel(const std::string &label)
static DBDriver * create(const ParametersMap ¶meters=ParametersMap())
std::map< int, Transform > _groundTruths
bool _saveIntermediateNodeData
std::vector< CameraModel > _rectCameraModels
void setUserData(const cv::Mat &userData, bool clearPreviousData=true)
void enableWordsRef(const std::list< int > &signatureIds)
int incrementMapId(std::map< int, int > *reducedIds=0)
void dumpDictionary(const char *fileNameRef, const char *fileNameDesc) const
virtual void dumpMemory(std::string directory) const
void uSleep(unsigned int ms)
void removeAllVirtualLinks()
static const ParametersMap & getDefaultParameters()
const cv::Point3f & gridViewPoint() const
bool _notLinkedNodesKeptInDb
virtual void parseParameters(const ParametersMap ¶meters)
static Registration * create(const ParametersMap ¶meters)
bool _badSignaturesIgnored
std::string _rgbCompressionFormat
const LaserScan & laserScanRaw() const
cv::Mat generateDescriptors(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
void getLastWordId(int &id) const
void setGlobalDescriptors(const std::vector< GlobalDescriptor > &descriptors)
bool _useOdometryFeatures
static const int kIdVirtual
SensorData & sensorData()
MarkerDetector * _markerDetector
void loadNodeData(Signature *signature, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const
void updateLink(const Link &link, bool updateInDatabase=false)
float _rehearsalMaxDistance
bool isUserDataRequired() const
void loadSignatures(const std::list< int > &ids, std::list< Signature *> &signatures, std::set< int > *loadedFromTrash=0)
bool rehearsalMerge(int oldId, int newId)
int getMapId(int id, bool lookInDatabase=false) const
void setWords(const std::multimap< int, int > &words, const std::vector< cv::KeyPoint > &keypoints, const std::vector< cv::Point3f > &words3, const cv::Mat &descriptors)
pcl::PointCloud< pcl::PointNormal >::Ptr RTABMAP_EXP laserScanToPointCloudNormal(const LaserScan &laserScan, const Transform &transform=Transform())
static long int getMemoryUsage()
std::vector< StereoCameraModel > _rectStereoCameraModels
std::string getDatabaseVersion() const
void createLocalMap(const Signature &node, cv::Mat &groundCells, cv::Mat &obstacleCells, cv::Mat &emptyCells, cv::Point3f &viewPoint)
virtual void parseParameters(const ParametersMap ¶meters)
void updateOccupancyGrid(int nodeId, const cv::Mat &ground, const cv::Mat &obstacles, const cv::Mat &empty, float cellSize, const cv::Point3f &viewpoint)
const cv::Mat & userDataCompressed() const
#define ULOGGER_WARN(...)
const Transform & getPose() const
ULogger class and convenient macros.
void removeAllWordRef(int wordId, int signatureId)
bool _idUpdatedToNewOneRehearsal
unsigned long getMemoryUsed() const
void parseParameters(const ParametersMap ¶meters)
cv::Mat loadOptimizedMesh(std::vector< std::vector< std::vector< RTABMAP_PCL_INDEX > > > *polygons=0, std::vector< std::vector< Eigen::Vector2f > > *texCoords=0, cv::Mat *textures=0) const
void setTimestampUpdateEnabled(bool enabled)
GLM_FUNC_DECL T yaw(detail::tquat< T, P > const &x)
std::map< int, float > computeLikelihood(const Signature *signature, const std::list< int > &ids)
RegistrationVis * _registrationVis
void dumpMemoryTree(const char *fileNameTree) const
float _laserScanNormalRadius
double transVariance(bool minimum=true) const
void parseParameters(const ParametersMap ¶meters)
void addLink(const Link &link)
bool hasIntensity() const
virtual const ParametersMap & getParameters() const
cv::Mat load2DMap(float &xMin, float &yMin, float &cellSize) const
void setGroundTruth(const Transform &pose)
std::multimap< int, Link > getLinks(int signatureId, bool lookInDatabase=false, bool withLandmarks=false) const
cv::Mat RTABMAP_EXP cvtDepthFromFloat(const cv::Mat &depth32F)
Transform getGroundTruthPose(int signatureId, bool lookInDatabase=false) const
std::string getDatabaseVersion() const
void getNodeIdByLabel(const std::string &label, int &id) const
void savePreviewImage(const cv::Mat &image) const
std::multimap< int, Link > getAllLinks(bool lookInDatabase, bool ignoreNullLinks=true, bool withLandmarks=false) const
std::map< EnvSensor::Type, EnvSensor > EnvSensors
cv::Mat loadOptimizedMesh(std::vector< std::vector< std::vector< RTABMAP_PCL_INDEX > > > *polygons=0, std::vector< std::vector< Eigen::Vector2f > > *texCoords=0, cv::Mat *textures=0) const
float angleIncrement() const
ParametersMap parameters_
static std::string formatName(const Format &format)
std::map< int, std::set< int > > _landmarksIndex
void updateAge(int signatureId)
std::vector< VisualWord * > getUnusedWords() const
pcl::PointCloud< pcl::PointXYZI >::Ptr RTABMAP_EXP laserScanToPointCloudI(const LaserScan &laserScan, const Transform &transform=Transform(), float intensity=0.0f)
const Transform & transform() const
std::map< int, Signature * > _signatures
void join(bool killFirst=false)
int getMaxFeatures() const
void removeLink(int idTo)
virtual void addWord(VisualWord *vw)
std::vector< double > _odomMaxInf
void addLink(const Link &link)
bool _rehearsalWeightIgnoredWhileMoving
bool _covOffDiagonalIgnored
#define ULOGGER_ERROR(...)
void copyData(const Signature *from, Signature *to)
const VWDictionary * getVWDictionary() const
std::set< int > getAllSignatureIds(bool ignoreChildren=true) const
int _lastGlobalLoopClosureId
Transform computeIcpTransformMulti(int newId, int oldId, const std::map< int, Transform > &poses, RegistrationInfo *info=0)
void addSignatureToStm(Signature *signature, const cv::Mat &covariance)
virtual ~PreUpdateThread()
std::string UTILITE_EXP uFormat(const char *fmt,...)
std::string UTILITE_EXP uNumber2Str(unsigned int number)
virtual void parseParameters(const ParametersMap ¶meters)
bool setUserData(int id, const cv::Mat &data)
bool isInSTM(int signatureId) const
GLM_FUNC_DECL genType ceil(genType const &x)
virtual void parseParameters(const ParametersMap ¶meters)
std::map< int, double > _workingMem
const cv::Mat & imageCompressed() const
Transform localTransform() const
LaserScan RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud< pcl::PointXYZ > &cloud, const Transform &transform=Transform(), bool filterNaNs=true)
V uValue(const std::map< K, V > &m, const K &key, const V &defaultValue=V())
void emptyTrashes(bool async=false)
void setFeatures(const std::vector< cv::KeyPoint > &keypoints, const std::vector< cv::Point3f > &keypoints3D, const cv::Mat &descriptors)
const std::string & getUrl() const
void getNodeWordsAndGlobalDescriptors(int nodeId, std::multimap< int, int > &words, std::vector< cv::KeyPoint > &wordsKpts, std::vector< cv::Point3f > &words3, cv::Mat &wordsDescriptors, std::vector< GlobalDescriptor > &globalDescriptors) const
void loadDataFromDb(bool postInitClosingEvents)
cv::Mat getImageCompressed(int signatureId) const
bool addLink(const Link &link, bool addInDatabase=false)
unsigned int getIndexedWordsCount() const
GLM_FUNC_DECL detail::tmat4x4< T, P > orientation(detail::tvec3< T, P > const &Normal, detail::tvec3< T, P > const &Up)
void addStatistic(const std::string &name, float value)
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
const std::multimap< int, int > & getWords() const
cv::Mat RTABMAP_EXP compressImage2(const cv::Mat &image, const std::string &format=".png")