62 #include <pcl/io/pcd_io.h>
63 #include <pcl/common/common.h>
65 #include <opencv2/imgproc/types_c.h>
76 _similarityThreshold(
Parameters::defaultMemRehearsalSimilarity()),
77 _binDataKept(
Parameters::defaultMemBinDataKept()),
78 _rawDescriptorsKept(
Parameters::defaultMemRawDescriptorsKept()),
79 _saveDepth16Format(
Parameters::defaultMemSaveDepth16Format()),
80 _notLinkedNodesKeptInDb(
Parameters::defaultMemNotLinkedNodesKept()),
81 _saveIntermediateNodeData(
Parameters::defaultMemIntermediateNodeDataKept()),
82 _rgbCompressionFormat(
Parameters::defaultMemImageCompressionFormat()),
83 _depthCompressionFormat(
Parameters::defaultMemDepthCompressionFormat()),
84 _incrementalMemory(
Parameters::defaultMemIncrementalMemory()),
85 _localizationDataSaved(
Parameters::defaultMemLocalizationDataSaved()),
86 _reduceGraph(
Parameters::defaultMemReduceGraph()),
87 _maxStMemSize(
Parameters::defaultMemSTMSize()),
88 _recentWmRatio(
Parameters::defaultMemRecentWmRatio()),
89 _transferSortingByWeightId(
Parameters::defaultMemTransferSortingByWeightId()),
90 _idUpdatedToNewOneRehearsal(
Parameters::defaultMemRehearsalIdUpdatedToNewOne()),
91 _generateIds(
Parameters::defaultMemGenerateIds()),
92 _badSignaturesIgnored(
Parameters::defaultMemBadSignaturesIgnored()),
93 _mapLabelsAdded(
Parameters::defaultMemMapLabelsAdded()),
94 _depthAsMask(
Parameters::defaultMemDepthAsMask()),
95 _maskFloorThreshold(
Parameters::defaultMemDepthMaskFloorThr()),
96 _stereoFromMotion(
Parameters::defaultMemStereoFromMotion()),
97 _imagePreDecimation(
Parameters::defaultMemImagePreDecimation()),
98 _imagePostDecimation(
Parameters::defaultMemImagePostDecimation()),
99 _compressionParallelized(
Parameters::defaultMemCompressionParallelized()),
100 _laserScanDownsampleStepSize(
Parameters::defaultMemLaserScanDownsampleStepSize()),
101 _laserScanVoxelSize(
Parameters::defaultMemLaserScanVoxelSize()),
102 _laserScanNormalK(
Parameters::defaultMemLaserScanNormalK()),
103 _laserScanNormalRadius(
Parameters::defaultMemLaserScanNormalRadius()),
104 _laserScanGroundNormalsUp(
Parameters::defaultIcpPointToPlaneGroundNormalsUp()),
105 _reextractLoopClosureFeatures(
Parameters::defaultRGBDLoopClosureReextractFeatures()),
106 _localBundleOnLoopClosure(
Parameters::defaultRGBDLocalBundleOnLoopClosure()),
107 _invertedReg(
Parameters::defaultRGBDInvertedReg()),
108 _rehearsalMaxDistance(
Parameters::defaultRGBDLinearUpdate()),
109 _rehearsalMaxAngle(
Parameters::defaultRGBDAngularUpdate()),
110 _rehearsalWeightIgnoredWhileMoving(
Parameters::defaultMemRehearsalWeightIgnoredWhileMoving()),
111 _useOdometryFeatures(
Parameters::defaultMemUseOdomFeatures()),
112 _useOdometryGravity(
Parameters::defaultMemUseOdomGravity()),
113 _rotateImagesUpsideUp(
Parameters::defaultMemRotateImagesUpsideUp()),
114 _createOccupancyGrid(
Parameters::defaultRGBDCreateOccupancyGrid()),
115 _visMaxFeatures(
Parameters::defaultVisMaxFeatures()),
117 _imagesAlreadyRectified(
Parameters::defaultRtabmapImagesAlreadyRectified()),
118 _rectifyOnlyFeatures(
Parameters::defaultRtabmapRectifyOnlyFeatures()),
119 _covOffDiagonalIgnored(
Parameters::defaultMemCovOffDiagIgnored()),
120 _detectMarkers(
Parameters::defaultRGBDMarkerDetection()),
121 _markerLinVariance(
Parameters::defaultMarkerVarianceLinear()),
122 _markerAngVariance(
Parameters::defaultMarkerVarianceAngular()),
124 _idMapCount(kIdStart),
126 _lastGlobalLoopClosureId(0),
127 _memoryChanged(
false),
128 _linksChanged(
false),
131 _badSignRatio(
Parameters::defaultKpBadSignRatio()),
132 _tfIdfLikelihoodUsed(
Parameters::defaultKpTfIdfLikelihoodUsed()),
133 _parallelized(
Parameters::defaultKpParallelized()),
150 float corRatio = Parameters::defaultIcpCorrespondenceRatio();
156 UWARN(
"%s is >=0.5, which sets correspondence ratio for proximity detection using "
157 "laser scans to 100% (2 x Ratio). You may lower the ratio to accept proximity "
158 "detection with not full scans overlapping.", Parameters::kIcpCorrespondenceRatio().
c_str());
236 bool loadAllNodesInWM = Parameters::defaultMemInitWMWithAllNodes();
240 std::list<Signature*> dbSignatures;
255 for(std::list<Signature*>::reverse_iterator
iter=dbSignatures.rbegin();
iter!=dbSignatures.rend(); ++
iter)
267 if(!(*iter)->getGroundTruthPose().isNull()) {
268 _groundTruths.insert(std::make_pair((*iter)->id(), (*iter)->getGroundTruthPose()));
271 if(!(*iter)->getLandmarks().empty())
274 for(std::map<int, Link>::const_iterator jter = (*iter)->getLandmarks().begin(); jter!=(*iter)->getLandmarks().end(); ++jter)
276 int landmarkId = jter->first;
279 cv::Mat landmarkSize = jter->second.uncompressUserDataConst();
280 if(!landmarkSize.empty() && landmarkSize.type() == CV_32FC1 && landmarkSize.total()==1)
282 std::pair<std::map<int, float>::iterator,
bool> inserted=
_landmarksSize.insert(std::make_pair(-landmarkId, landmarkSize.at<
float>(0,0)));
285 if(inserted.first->second != landmarkSize.at<
float>(0,0))
287 UWARN(
"Trying to update landmark size buffer for landmark %d with size=%f but "
288 "it has already a different size set. Keeping old size (%f).",
289 -landmarkId, inserted.first->second, landmarkSize.at<
float>(0,0));
294 UDEBUG(
"Caching landmark size %f for %d", landmarkSize.at<
float>(0,0), -landmarkId);
301 nter->second.insert((*iter)->id());
306 tmp.insert((*iter)->id());
322 UDEBUG(
"Check if all nodes are in Working Memory");
325 for(std::map<int, Link>::const_iterator jter =
iter->second->getLinks().begin(); jter!=
iter->second->getLinks().end(); ++jter)
336 UDEBUG(
"update odomMaxInf vector");
337 std::multimap<int, Link> links = this->
getAllLinks(
true,
true);
338 for(std::multimap<int, Link>::iterator
iter=links.begin();
iter!=links.end(); ++
iter)
341 iter->second.infMatrix().cols == 6 &&
342 iter->second.infMatrix().rows == 6)
348 for(
int i=0;
i<6; ++
i)
350 const double &
v =
iter->second.infMatrix().at<
double>(
i,
i);
358 UDEBUG(
"update odomMaxInf vector, done!");
380 UDEBUG(
"Loading dictionary...");
383 UDEBUG(
"load all referenced words in working memory");
385 std::set<int> wordIds;
386 const std::map<int, Signature *> & signatures = this->
getSignatures();
387 for(std::map<int, Signature *>::const_iterator
i=signatures.begin();
i!=signatures.end(); ++
i)
389 const std::multimap<int, int> & words =
i->second->getWords();
395 wordIds.insert(*
iter);
400 UDEBUG(
"load words %d", (
int)wordIds.size());
405 std::list<VisualWord*> words;
407 for(std::list<VisualWord*>::iterator
iter = words.begin();
iter!=words.end(); ++
iter)
434 const std::map<int, Signature *> & signatures = this->
getSignatures();
435 for(std::map<int, Signature *>::const_iterator
i=signatures.begin();
i!=signatures.end(); ++
i)
440 const std::multimap<int, int> & words =
s->getWords();
443 UDEBUG(
"node=%d, word references=%d",
s->id(), words.size());
444 for(std::multimap<int, int>::const_iterator
iter = words.begin();
iter!=words.end(); ++
iter)
467 parameters.erase(Parameters::kRtabmapWorkingDirectory());
484 void Memory::close(
bool databaseSaved,
bool postInitClosingEvents,
const std::string & ouputDatabasePath)
486 UINFO(
"databaseSaved=%d, postInitClosingEvents=%d", databaseSaved?1:0, postInitClosingEvents?1:0);
489 bool databaseNameChanged =
false;
499 UINFO(
"No changes added to database.");
514 UINFO(
"Saving memory...");
547 UWARN(
"Please call Memory::close() before");
563 ParametersMap::const_iterator
iter;
597 UWARN(
"%s and %s cannot be used at the same time, disabling %s...",
598 Parameters::kRGBDLocalBundleOnLoopClosure().
c_str(),
599 Parameters::kRGBDInvertedReg().
c_str(),
600 Parameters::kRGBDLocalBundleOnLoopClosure().
c_str());
660 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));
664 UINFO(
"new detector strategy %d.",
int(detectorStrategy));
706 UDEBUG(
"new registration strategy %d",
int(regStrategy));
744 float corRatio = Parameters::defaultIcpCorrespondenceRatio();
750 UWARN(
"%s is >=0.5, which sets correspondence ratio for proximity detection using "
751 "laser scans to 100% (2 x Ratio). You may lower the ratio to accept proximity "
752 "detection with not full scans overlapping.", Parameters::kIcpCorrespondenceRatio().
c_str());
772 int globalDescriptorStrategy = -1;
774 if(globalDescriptorStrategy != -1 &&
790 iter =
params.find(Parameters::kMemIncrementalMemory());
803 UWARN(
"Switching from Mapping to Localization mode, the database will be saved and reloaded.");
810 UWARN(
"Switching from Mapping to Localization mode, the database is reloaded!");
818 int visFeatureType = Parameters::defaultVisFeatureType();
819 int kpDetectorStrategy = Parameters::defaultKpDetectorStrategy();
822 if(visFeatureType != kpDetectorStrategy)
824 UWARN(
"%s is enabled, but %s and %s parameters are not the same! Disabling %s...",
825 Parameters::kMemUseOdomFeatures().
c_str(),
826 Parameters::kVisFeatureType().
c_str(),
827 Parameters::kKpDetectorStrategy().
c_str(),
828 Parameters::kMemUseOdomFeatures().
c_str());
859 const cv::Mat & covariance,
860 const std::vector<float> & velocity,
872 UDEBUG(
"pre-updating...");
874 t=
timer.ticks()*1000;
875 if(
stats)
stats->addStatistic(Statistics::kTimingMemPre_update(),
t);
876 UDEBUG(
"time preUpdate=%f ms",
t);
884 UERROR(
"Failed to create a signature...");
893 if(
stats)
stats->addStatistic(Statistics::kTimingMemSignature_creation(),
t);
894 UDEBUG(
"time creating signature=%f ms",
t);
914 if(
stats)
stats->addStatistic(Statistics::kTimingMemRehearsal(),
t);
915 UDEBUG(
"time rehearsal=%f ms",
t);
921 UWARN(
"The working memory is empty and the memory is not "
922 "incremental (Mem/IncrementalMemory=False), no loop closure "
923 "can be detected! Please set Mem/IncrementalMemory=true to increase "
924 "the memory with new images or decrease the STM size (which is %d "
925 "including the new one added).", (
int)
_stMem.size());
932 int notIntermediateNodesCount = 0;
937 if(
s->getWeight() >= 0)
939 ++notIntermediateNodesCount;
942 std::map<int, int> reducedIds;
948 if(
s->getWeight() >= 0)
950 --notIntermediateNodesCount;
958 reducedIds.insert(std::make_pair(
id, reducedTo));
989 UASSERT(covariance.cols == 6 && covariance.rows == 6 && covariance.type() == CV_64FC1);
990 double maxAngVar = 0.0;
993 maxAngVar = covariance.at<
double>(5,5);
997 maxAngVar =
uMax3(covariance.at<
double>(3,3), covariance.at<
double>(4,4), covariance.at<
double>(5,5));
1000 if(maxAngVar != 1.0 && maxAngVar > 0.1)
1002 static bool warned =
false;
1005 UWARN(
"Very large angular variance (%f) detected! Please fix odometry "
1006 "covariance, otherwise poor graph optimizations are "
1007 "expected and wrong loop closure detections creating a lot "
1008 "of errors in the map could be accepted. This message is only "
1009 "printed once.", maxAngVar);
1017 infMatrix = cv::Mat::zeros(6,6,CV_64FC1);
1018 infMatrix.at<
double>(0,0) = 1.0 / covariance.at<
double>(0,0);
1019 infMatrix.at<
double>(1,1) = 1.0 / covariance.at<
double>(1,1);
1020 infMatrix.at<
double>(2,2) = 1.0 / covariance.at<
double>(2,2);
1021 infMatrix.at<
double>(3,3) = 1.0 / covariance.at<
double>(3,3);
1022 infMatrix.at<
double>(4,4) = 1.0 / covariance.at<
double>(4,4);
1023 infMatrix.at<
double>(5,5) = 1.0 / covariance.at<
double>(5,5);
1027 infMatrix = covariance.inv();
1029 if((
uIsFinite(covariance.at<
double>(0,0)) && covariance.at<
double>(0,0)>0.0) &&
1030 !(
uIsFinite(infMatrix.at<
double>(0,0)) && infMatrix.at<
double>(0,0)>0.0))
1032 UERROR(
"Failed to invert the covariance matrix! Covariance matrix should be invertible!");
1033 std::cout <<
"Covariance: " << covariance << std::endl;
1034 infMatrix = cv::Mat::eye(6,6,CV_64FC1);
1037 UASSERT(infMatrix.rows == 6 && infMatrix.cols == 6);
1042 for(
int i=0;
i<6; ++
i)
1044 const double &
v = infMatrix.at<
double>(
i,
i);
1064 UDEBUG(
"Ignoring neighbor link between %d and %d because they are not in the same map! (%d vs %d)",
1071 std::string tag =
uFormat(
"map%d", signature->
mapId());
1074 UINFO(
"Tagging node %d with label \"%s\"", signature->
id(), tag.c_str());
1076 _labels.insert(std::make_pair(signature->
id(), tag));
1084 std::string tag =
uFormat(
"map%d", signature->
mapId());
1087 UINFO(
"Tagging node %d with label \"%s\"", signature->
id(), tag.c_str());
1089 _labels.insert(std::make_pair(signature->
id(), tag));
1102 UDEBUG(
"%d words ref for the signature %d (weight=%d)", signature->
getWords().size(), signature->
id(), signature->
getWeight());
1117 UDEBUG(
"Inserting node %d in WM...", signature->
id());
1119 _signatures.insert(std::pair<int, Signature*>(signature->
id(), signature));
1127 UERROR(
"Signature is null ?!?");
1133 UDEBUG(
"Inserting node %d from STM in WM...",
id);
1141 const std::multimap<int, Link> & links =
s->getLinks();
1142 std::map<int, Link> neighbors;
1143 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
1147 merge =
iter->second.to() <
s->id() &&
1148 iter->second.to() !=
iter->second.from() &&
1151 iter->second.userDataCompressed().empty() &&
1156 UDEBUG(
"Reduce %d to %d",
s->id(),
iter->second.to());
1159 *reducedTo =
iter->second.to();
1166 neighbors.insert(*
iter);
1171 if(
s->getLabel().empty())
1173 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
1176 if(sTo->
id()!=
s->id())
1185 for(std::map<int, Link>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
1187 if(!sTo->
hasLink(jter->second.to()))
1189 UDEBUG(
"Merging link %d->%d (type=%d) to link %d->%d (type %d)",
1190 iter->second.from(),
iter->second.to(),
iter->second.type(),
1191 jter->second.from(), jter->second.to(), jter->second.type());
1192 Link l =
iter->second.inverse().merge(
1207 std::multimap<int, Link> linksCopy = links;
1208 for(std::multimap<int, Link>::iterator
iter=linksCopy.begin();
iter!=linksCopy.end(); ++
iter)
1213 s->removeLink(
iter->first);
1257 bool lookInDatabase)
const
1259 std::multimap<int, Link> links;
1263 const std::multimap<int, Link> & allLinks =
s->getLinks();
1264 for(std::multimap<int, Link>::const_iterator
iter = allLinks.begin();
iter!=allLinks.end(); ++
iter)
1269 links.insert(*
iter);
1276 for(std::multimap<int, Link>::iterator
iter=links.begin();
iter!=links.end();)
1281 links.erase(
iter++);
1291 UWARN(
"Cannot find signature %d in memory", signatureId);
1298 bool lookInDatabase)
const
1301 std::multimap<int, Link> loopClosures;
1304 const std::multimap<int, Link> & allLinks =
s->getLinks();
1305 for(std::multimap<int, Link>::const_iterator
iter = allLinks.begin();
iter!=allLinks.end(); ++
iter)
1309 iter->second.from() !=
iter->second.to() &&
1312 loopClosures.insert(*
iter);
1319 for(std::multimap<int, Link>::iterator
iter=loopClosures.begin();
iter!=loopClosures.end();)
1325 loopClosures.erase(
iter++);
1333 return loopClosures;
1338 bool lookInDatabase,
1339 bool withLandmarks)
const
1341 std::multimap<int, Link> links;
1347 links =
s->getLinks();
1350 links.insert(
s->getLandmarks().begin(),
s->getLandmarks().end());
1359 UWARN(
"Cannot find signature %d in memory", signatureId);
1362 else if(signatureId < 0)
1364 int landmarkId = signatureId;
1368 for(std::set<int>::const_iterator jter=
iter->second.begin(); jter!=
iter->second.end(); ++jter)
1373 std::map<int, Link>::const_iterator kter =
s->getLandmarks().find(landmarkId);
1374 if(kter !=
s->getLandmarks().end())
1377 links.insert(std::make_pair(
s->id(), kter->second.inverse()));
1384 std::map<int, Link>
nodes;
1386 for(std::map<int, Link>::iterator kter=
nodes.begin(); kter!=
nodes.end(); ++kter)
1388 links.insert(std::make_pair(kter->first, kter->second.inverse()));
1395 std::multimap<int, Link>
Memory::getAllLinks(
bool lookInDatabase,
bool ignoreNullLinks,
bool withLandmarks)
const
1397 std::multimap<int, Link> links;
1406 links.erase(
iter->first);
1407 for(std::map<int, Link>::const_iterator jter=
iter->second->getLinks().begin();
1408 jter!=
iter->second->getLinks().end();
1411 if(!ignoreNullLinks || jter->second.isValid())
1413 links.insert(std::make_pair(
iter->first, jter->second));
1418 for(std::map<int, Link>::const_iterator jter=
iter->second->getLandmarks().begin();
1419 jter!=
iter->second->getLandmarks().end();
1422 if(!ignoreNullLinks || jter->second.isValid())
1424 links.insert(std::make_pair(
iter->first, jter->second));
1440 int maxCheckedInDatabase,
1441 bool incrementMarginOnLoop,
1443 bool ignoreIntermediateNodes,
1444 bool ignoreLocalSpaceLoopIds,
1445 const std::set<int> & nodesSet,
1446 double * dbAccessTime
1458 std::map<int, int> ids;
1463 int nbLoadedFromDb = 0;
1464 std::list<int> curentMarginList;
1465 std::set<int> currentMargin;
1466 std::set<int> nextMargin;
1467 nextMargin.insert(signatureId);
1469 std::set<int> ignoredIds;
1470 while((maxGraphDepth == 0 ||
m < maxGraphDepth) && nextMargin.size())
1473 curentMarginList = std::list<int>(nextMargin.rbegin(), nextMargin.rend());
1476 for(std::list<int>::iterator jter = curentMarginList.begin(); jter!=curentMarginList.end(); ++jter)
1478 if(ids.find(*jter) == ids.end() && (nodesSet.empty() || nodesSet.find(*jter) != nodesSet.end()))
1483 std::multimap<int, Link> tmpLinks;
1484 std::map<int, Link> tmpLandmarks;
1485 const std::multimap<int, Link> * links = &tmpLinks;
1486 const std::map<int, Link> * landmarks = &tmpLandmarks;
1489 if(!ignoreIntermediateNodes ||
s->getWeight() != -1)
1491 ids.insert(std::pair<int, int>(*jter,
m));
1495 ignoredIds.insert(*jter);
1498 links = &
s->getLinks();
1501 landmarks = &
s->getLandmarks();
1504 else if(maxCheckedInDatabase == -1 || (maxCheckedInDatabase > 0 &&
_dbDriver && nbLoadedFromDb < maxCheckedInDatabase))
1507 ids.insert(std::pair<int, int>(*jter,
m));
1511 if(tmpLinks.empty())
1513 UWARN(
"No links loaded for %d?!", *jter);
1517 for(std::multimap<int, Link>::iterator kter=tmpLinks.begin(); kter!=tmpLinks.end();)
1521 tmpLandmarks.insert(*kter);
1522 tmpLinks.erase(kter++);
1524 else if(kter->second.from() == kter->second.to())
1527 tmpLinks.erase(kter++);
1537 *dbAccessTime +=
timer.getElapsedTime();
1542 for(std::multimap<int, Link>::const_iterator
iter=links->begin();
iter!=links->end(); ++
iter)
1545 ignoredIds.find(
iter->first) == ignoredIds.end())
1551 if(ignoreIntermediateNodes &&
s->getWeight()==-1)
1554 if(currentMargin.insert(
iter->first).second)
1556 curentMarginList.push_back(
iter->first);
1561 nextMargin.insert(
iter->first);
1566 if(incrementMarginOnLoop)
1568 nextMargin.insert(
iter->first);
1572 if(currentMargin.insert(
iter->first).second)
1574 curentMarginList.push_back(
iter->first);
1582 for(std::map<int, Link>::const_iterator
iter=landmarks->begin();
iter!=landmarks->end(); ++
iter)
1584 const std::map<int, std::set<int> >::const_iterator kter =
_landmarksIndex.find(
iter->first);
1587 for(std::set<int>::const_iterator nter=kter->second.begin(); nter!=kter->second.end(); ++nter)
1589 if( !
uContains(ids, *nter) && ignoredIds.find(*nter) == ignoredIds.end())
1591 if(incrementMarginOnLoop)
1593 nextMargin.insert(*nter);
1597 if(currentMargin.insert(*nter).second)
1599 curentMarginList.push_back(*nter);
1617 const std::map<int, Transform> & optimizedPoses,
1624 std::map<int, float> ids;
1625 std::map<int, float> checkedIds;
1626 std::list<int> curentMarginList;
1627 std::set<int> currentMargin;
1628 std::set<int> nextMargin;
1629 nextMargin.insert(signatureId);
1631 Transform referential = optimizedPoses.at(signatureId);
1633 float radiusSqrd = radius*radius;
1634 while((maxGraphDepth == 0 ||
m < maxGraphDepth) && nextMargin.size())
1636 curentMarginList = std::list<int>(nextMargin.begin(), nextMargin.end());
1639 for(std::list<int>::iterator jter = curentMarginList.begin(); jter!=curentMarginList.end(); ++jter)
1641 if(checkedIds.find(*jter) == checkedIds.end())
1648 const Transform &
t = optimizedPoses.at(*jter);
1651 if(radiusSqrd == 0 || distanceSqrd<radiusSqrd)
1653 ids.insert(std::pair<int, float>(*jter,distanceSqrd));
1657 for(std::multimap<int, Link>::const_iterator
iter=
s->getLinks().begin();
iter!=
s->getLinks().end(); ++
iter)
1663 nextMargin.insert(
iter->first);
1689 int id = *
_stMem.begin();
1691 if(reducedIds && reducedId > 0)
1693 reducedIds->insert(std::make_pair(
id, reducedId));
1724 std::string
version =
"0.0.0";
1734 std::string
url =
"";
1756 ids.insert(
iter->first);
1801 uFormat(
"The number of signatures don't match! _workingMem=%d, _stMem=%d, _signatures=%d",
1804 UDEBUG(
"Adding statistics after run...");
1809 parameters.erase(Parameters::kRtabmapWorkingDirectory());
1823 for(std::map<int, Signature *>::iterator
i=mem.begin();
i!=mem.end(); ++
i)
1827 UDEBUG(
"deleting from the working and the short-term memory: %d",
i->first);
1894 std::map<int, float> likelihood;
1901 else if(ids.empty())
1903 UWARN(
"ids list is empty");
1907 for(std::list<int>::const_iterator
iter = ids.begin();
iter!=ids.end(); ++
iter)
1915 UFATAL(
"Signature %d not found in WM ?!?", *
iter);
1920 likelihood.insert(likelihood.end(), std::pair<int, float>(*
iter, sim));
1923 UDEBUG(
"compute likelihood (similarity)... %f s",
timer.ticks());
1930 std::map<int, float> likelihood;
1931 std::map<int, float> calculatedWordsRatio;
1938 else if(ids.empty())
1940 UWARN(
"ids list is empty");
1944 for(std::list<int>::const_iterator
iter = ids.begin();
iter!=ids.end(); ++
iter)
1946 likelihood.insert(likelihood.end(), std::pair<int, float>(*
iter, 0.0f));
1963 UDEBUG(
"processing... ");
1965 for(std::list<int>::const_iterator
i=wordIds.begin();
i!=wordIds.end(); ++
i)
1980 for(std::map<int, int>::const_iterator
j=refs.begin();
j!=refs.end(); ++
j)
1982 std::map<int, float>::iterator
iter = likelihood.find(
j->first);
1983 if(
iter != likelihood.end())
1986 ni = this->
getNi(
j->first);
1990 iter->second += ( nwi * logNnw ) / ni;
2000 UDEBUG(
"compute likelihood (tf-idf) %f s",
timer.ticks());
2008 std::map<int, int> weights;
2016 UFATAL(
"Location %d must exist in memory",
iter->first);
2018 weights.insert(weights.end(), std::make_pair(
iter->first,
s->getWeight()));
2022 weights.insert(weights.end(), std::make_pair(
iter->first, -1));
2031 std::list<int> signaturesRemoved;
2042 int wordsRemoved = 0;
2049 while(wordsRemoved < newWords)
2052 if(signatures.size())
2057 signaturesRemoved.push_back(
s->id());
2071 UDEBUG(
"newWords=%d, wordsRemoved=%d", newWords, wordsRemoved);
2079 for(std::list<Signature *>::iterator
iter=signatures.begin();
iter!=signatures.end(); ++
iter)
2081 signaturesRemoved.push_back((*iter)->id());
2086 if((
int)signatures.size() < signaturesAdded)
2088 UWARN(
"Less signatures transferred (%d) than added (%d)! The working memory cannot decrease in size.",
2089 (
int)signatures.size(), signaturesAdded);
2093 UDEBUG(
"signaturesRemoved=%d, _signaturesAdded=%d", (
int)signatures.size(), signaturesAdded);
2096 return signaturesRemoved;
2103 int signatureRemoved = 0;
2116 return signatureRemoved;
2158 for(std::map<int, Transform>::iterator
iter=poses.lower_bound(1);
iter!=poses.end() && ok; ++
iter)
2162 UWARN(
"Node %d not found in working memory",
iter->first);
2168 UWARN(
"Optimized poses (%d) and working memory "
2169 "size (%d) don't match. Returning empty optimized "
2170 "poses to force re-update. If you want to use the "
2171 "saved optimized poses, set %s to true",
2174 Parameters::kMemInitWMWithAllNodes().c_str());
2175 return std::map<int, Transform>();
2180 return std::map<int, Transform>();
2201 const cv::Mat & cloud,
2202 const std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > & polygons,
2203 #
if PCL_VERSION_COMPARE(>=, 1, 8, 0)
2206 const std::vector<std::vector<Eigen::Vector2f> > & texCoords,
2208 const cv::Mat & textures)
const
2217 std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > * polygons,
2218 #
if PCL_VERSION_COMPARE(>=, 1, 8, 0)
2221 std::vector<std::vector<Eigen::Vector2f> > * texCoords,
2223 cv::Mat * textures)
const
2284 std::list<Signature *> removableSignatures;
2285 std::map<WeightAgeIdKey, Signature *> weightAgeIdMap;
2288 UDEBUG(
"mem.size()=%d, ignoredIds.size()=%d", (
int)
_workingMem.size(), (
int)ignoredIds.size());
2293 bool recentWmImmunized =
false;
2295 int currentRecentWmSize = 0;
2302 ++currentRecentWmSize;
2305 if(currentRecentWmSize>1 && currentRecentWmSize < recentWmMaxSize)
2307 recentWmImmunized =
true;
2309 else if(currentRecentWmSize == 0 &&
_workingMem.size() > 1)
2323 for(std::map<int, double>::const_iterator memIter =
_workingMem.begin(); memIter !=
_workingMem.end(); ++memIter)
2330 else if(memIter->first > 0 && ignoredIds.find(memIter->first) == ignoredIds.end() && (!lastInSTM || !lastInSTM->
hasLink(memIter->first)))
2336 bool foundInSTM =
false;
2337 for(std::map<int, Link>::const_iterator
iter =
s->getLinks().begin();
iter!=
s->getLinks().end(); ++
iter)
2341 UDEBUG(
"Ignored %d because it has a link (%d) to STM",
s->id(),
iter->first);
2363 int recentWmCount = 0;
2366 UDEBUG(
"signatureMap.size()=%d _lastGlobalLoopClosureId=%d currentRecentWmSize=%d recentWmMaxSize=%d",
2368 for(std::map<WeightAgeIdKey, Signature*>::iterator
iter=weightAgeIdMap.begin();
2369 iter!=weightAgeIdMap.end();
2372 if(!recentWmImmunized)
2374 UDEBUG(
"weight=%d, id=%d",
2375 iter->second->getWeight(),
2376 iter->second->id());
2377 removableSignatures.push_back(
iter->second);
2382 if(currentRecentWmSize - recentWmCount < recentWmMaxSize)
2384 UDEBUG(
"switched recentWmImmunized");
2385 recentWmImmunized =
true;
2391 UDEBUG(
"weight=%d, id=%d",
2392 iter->second->getWeight(),
2393 iter->second->id());
2394 removableSignatures.push_back(
iter->second);
2396 if(removableSignatures.size() >= (
unsigned int)
count)
2404 ULOGGER_WARN(
"not enough signatures to get an old one...");
2406 return removableSignatures;
2418 if(!
s->getLandmarks().empty())
2420 for(std::map<int, Link>::const_iterator
iter=
s->getLandmarks().begin();
iter!=
s->getLandmarks().end(); ++
iter)
2422 int landmarkId =
iter->first;
2426 nter->second.erase(
s->id());
2427 if(nter->second.empty())
2438 keepLinkedToGraph =
false;
2442 if(!keepLinkedToGraph)
2445 uFormat(
"Deleting location (%d) outside the "
2446 "STM is not implemented!",
s->id()).c_str());
2447 const std::multimap<int, Link> & links =
s->getLinks();
2448 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
2450 if(
iter->second.from() !=
iter->second.to() &&
iter->first > 0)
2455 uFormat(
"A neighbor (%d) of the deleted location %d is "
2456 "not found in WM/STM! Are you deleting a location "
2457 "outside the STM?",
iter->first,
s->id()).c_str());
2459 if(
iter->first >
s->id() && links.size()>1 && sTo->
hasLink(
s->id()))
2461 UWARN(
"Link %d of %d is newer, removing neighbor link "
2462 "may split the map!",
2463 iter->first,
s->id());
2476 s->removeLinks(
true);
2477 s->removeLandmarks();
2493 for(std::list<int>::const_iterator
i=
keys.begin();
i!=
keys.end(); ++
i)
2499 std::vector<VisualWord*> wordToDelete;
2500 wordToDelete.push_back(
w);
2504 deletedWords->push_back(
w->id());
2543 if(keepLinkedToGraph)
2569 UDEBUG(
"landmarkId=%d", landmarkId);
2570 std::map<int, Link>
nodes;
2576 for(std::set<int>::const_iterator jter=
iter->second.begin(); jter!=
iter->second.end(); ++jter)
2581 std::map<int, Link>::const_iterator kter =
s->getLandmarks().find(landmarkId);
2582 if(kter !=
s->getLandmarks().end())
2584 nodes.insert(std::make_pair(
s->id(), kter->second));
2599 UDEBUG(
"label=%s", label.c_str());
2606 if(
iter->second->getLabel().compare(label) == 0)
2608 id =
iter->second->id();
2612 if(
id == 0 &&
_dbDriver && lookInDatabase)
2632 if(idFound == 0 && label.empty() &&
_labels.find(
id)==
_labels.end())
2634 UWARN(
"Trying to remove label from node %d but it has already no label",
id);
2637 if(idFound == 0 || idFound ==
id)
2644 UWARN(
"Label \"%s\" removed from node %d",
_labels.at(
id).c_str(),
id);
2651 UWARN(
"Label \"%s\" set to node %d (previously labeled \"%s\")", label.c_str(),
id,
_labels.at(
id).c_str());
2655 UWARN(
"Label \"%s\" set to node %d", label.c_str(),
id);
2667 std::list<Signature *> signatures;
2669 if(signatures.size())
2673 UWARN(
"Label \"%s\" removed from node %d",
_labels.at(
id).c_str(),
id);
2680 UWARN(
"Label \"%s\" set to node %d (previously labeled \"%s\")", label.c_str(),
id,
_labels.at(
id).c_str());
2684 UWARN(
"Label \"%s\" set to node %d", label.c_str(),
id);
2689 signatures.front()->setLabel(label);
2696 UERROR(
"Node %d not found, failed to set label \"%s\"!",
id, label.c_str());
2701 UWARN(
"Another node %d has already label \"%s\", cannot set it to node %d", idFound, label.c_str(),
id);
2711 s->sensorData().setUserData(
data);
2716 UERROR(
"Node %d not found in RAM, failed to set user data (size=%d)!",
id,
data.total());
2723 UDEBUG(
"Deleting location %d", locationId);
2733 UDEBUG(
"Saving location data %d", locationId);
2757 UINFO(
"removing link between location %d and %d", oldS->
id(), newS->
id());
2778 bool noChildrenAnymore =
true;
2783 iter->second.from() !=
iter->second.to() &&
2784 iter->first < newS->
id())
2786 noChildrenAnymore =
false;
2797 UERROR(
"Signatures %d and %d don't have bidirectional link!", oldS->
id(), newS->
id());
2802 int landmarkId = newId<0?newId:oldId;
2804 s->removeLandmark(newId<0?newId:oldId);
2810 nter->second.erase(
s->id());
2817 UERROR(
"Signature %d is not in working memory... cannot remove link.", newS->
id());
2821 UERROR(
"Signature %d is not in working memory... cannot remove link.", oldS->
id());
2828 UDEBUG(
"id=%d image=%d scan=%d userData=%d",
id, image?1:0, scan?1:0, userData?1:0);
2832 s->sensorData().clearRawData(
2845 bool useKnownCorrespondencesIfPossible)
2858 std::string
msg =
uFormat(
"Did not find nodes %d and/or %d", fromId, toId);
2874 bool useKnownCorrespondencesIfPossible)
const
2894 cv::Mat imgBuf, depthBuf, userBuf;
2909 std::vector<int> inliersV;
2934 tmpFrom.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
2938 else if(useKnownCorrespondencesIfPossible)
2958 else if(!isNeighborRefining &&
2971 std::multimap<int, int> words;
2972 std::vector<cv::Point3f> words3DMap;
2973 std::vector<cv::KeyPoint> wordsMap;
2974 cv::Mat wordsDescriptorsMap;
2976 const std::multimap<int, Link> & links = fromS.
getLinks();
2980 UDEBUG(
"fromS.getWords()=%d uniques=%d", (
int)fromS.
getWords().size(), (
int)wordsFrom.size());
2981 for(std::map<int, int>::const_iterator jter=wordsFrom.begin(); jter!=wordsFrom.end(); ++jter)
2983 const cv::Point3f & pt = fromS.
getWords3()[jter->second];
2986 words.insert(std::make_pair(jter->first, words.size()));
2987 words3DMap.push_back(pt);
2988 wordsMap.push_back(fromS.
getWordsKpts()[jter->second]);
2993 UDEBUG(
"words3DMap=%d", (
int)words3DMap.size());
2995 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
2997 int id =
iter->first;
3001 if(s && !
s->getWords3().empty())
3004 for(std::map<int, int>::const_iterator jter=wordsTo.begin(); jter!=wordsTo.end(); ++jter)
3006 const cv::Point3f & pt =
s->getWords3()[jter->second];
3007 if( jter->first > 0 &&
3009 words.find(jter->first) == words.end())
3011 words.insert(words.end(), std::make_pair(jter->first, words.size()));
3013 wordsMap.push_back(
s->getWordsKpts()[jter->second]);
3014 wordsDescriptorsMap.push_back(
s->getWordsDescriptors().row(jter->second));
3020 UDEBUG(
"words3DMap=%d", (
int)words3DMap.size());
3022 tmpFrom2.
setWords(words, wordsMap, words3DMap, wordsDescriptorsMap);
3028 std::map<int, cv::Point3f> points3DMap;
3030 for(std::map<int, int>::iterator
iter=wordsMap.begin();
iter!=wordsMap.end(); ++
iter)
3032 points3DMap.insert(std::make_pair(
iter->first, tmpFrom2.
getWords3()[
iter->second]));
3034 std::map<int, Transform> bundlePoses;
3035 std::multimap<int, Link> bundleLinks;
3036 std::map<int, std::vector<CameraModel> > bundleModels;
3037 std::map<int, std::map<int, FeatureBA> > wordReferences;
3039 std::multimap<int, Link> links = fromS.
getLinks();
3042 links.insert(std::make_pair(fromS.
id(),
Link()));
3044 int totalWordReferences = 0;
3045 for(std::multimap<int, Link>::iterator
iter=links.begin();
iter!=links.end(); ++
iter)
3047 int id =
iter->first;
3048 if(
id != fromS.
id() ||
iter->second.transform().isNull())
3052 if(
id == tmpTo.
id())
3062 std::vector<CameraModel> models;
3063 if(
s->sensorData().cameraModels().size() >= 1 &&
s->sensorData().cameraModels().at(0).isValidForProjection())
3065 models =
s->sensorData().cameraModels();
3067 else if(
s->sensorData().stereoCameraModels().size() >= 1 &&
s->sensorData().stereoCameraModels().at(0).isValidForProjection())
3069 for(
size_t i=0;
i<
s->sensorData().stereoCameraModels().
size(); ++
i)
3077 model.localTransform(),
3078 -
s->sensorData().stereoCameraModels()[
i].baseline()*
model.fx(),
3080 models.push_back(
model);
3085 UFATAL(
"no valid camera model to use local bundle adjustment on loop closure!");
3087 bundleModels.insert(std::make_pair(
id, models));
3090 if(
iter->second.transform().isNull())
3097 bundleLinks.insert(std::make_pair(
iter->second.from(),
iter->second));
3098 bundlePoses.insert(std::make_pair(
id,
iter->second.transform()));
3102 for(std::map<int, int>::const_iterator jter=words.begin(); jter!=words.end(); ++jter)
3104 if(points3DMap.find(jter->first)!=points3DMap.end() &&
3105 (
id == tmpTo.
id() || jter->first > 0))
3107 cv::KeyPoint kpts =
s->getWordsKpts()[jter->second];
3108 int cameraIndex = 0;
3111 UASSERT(models[0].imageWidth()>0);
3112 float subImageWidth = models[0].imageWidth();
3113 cameraIndex =
int(kpts.pt.x / subImageWidth);
3114 kpts.pt.x = kpts.pt.x - (subImageWidth*
float(cameraIndex));
3119 if( !
s->getWords3().empty() &&
3123 Transform invLocalTransform = models[cameraIndex].localTransform().
inverse();
3126 wordReferences.insert(std::make_pair(jter->first, std::map<int, FeatureBA>()));
3127 wordReferences.at(jter->first).insert(std::make_pair(
id,
FeatureBA(kpts,
d, cv::Mat(), cameraIndex)));
3128 ++totalWordReferences;
3138 std::set<int> sbaOutliers;
3143 bundlePoses = sba.
optimizeBA(-toS.
id(), bundlePoses, bundleLinks, bundleModels, points3DMap, wordReferences, &sbaOutliers);
3146 UDEBUG(
"bundleTime=%fs (poses=%d wordRef=%d outliers=%d)", bundleTime.
ticks(), (
int)bundlePoses.size(), totalWordReferences, (
int)sbaOutliers.size());
3148 UDEBUG(
"Local Bundle Adjustment Before: %s",
transform.prettyPrint().c_str());
3149 if(!bundlePoses.rbegin()->second.isNull())
3151 if(sbaOutliers.size())
3153 std::vector<int> newInliers(
info->inliersIDs.size());
3155 for(
unsigned int i=0;
i<
info->inliersIDs.size(); ++
i)
3157 if(sbaOutliers.find(
info->inliersIDs[
i]) == sbaOutliers.end())
3159 newInliers[oi++] =
info->inliersIDs[
i];
3162 newInliers.resize(oi);
3163 UDEBUG(
"BA outliers ratio %f",
float(sbaOutliers.size())/
float(
info->inliersIDs.size()));
3164 info->inliers = (
int)newInliers.size();
3165 info->inliersIDs = newInliers;
3174 transform = bundlePoses.rbegin()->second;
3181 UDEBUG(
"Local Bundle Adjustment After : %s",
transform.prettyPrint().c_str());
3195 std::string
msg =
uFormat(
"Missing visual features or missing raw data to compute them. Transform cannot be estimated.");
3222 const std::map<int, Transform> & poses,
3228 UDEBUG(
"%d -> %d, Guess=%s", fromId, toId, (poses.at(fromId).inverse() * poses.at(toId)).prettyPrint().c_str());
3232 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
3234 if(
iter->first != fromId)
3239 UDEBUG(
"%d vs %s", fromId, ids.c_str());
3243 std::list<Signature*> scansToLoad;
3244 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
3249 if(
s->sensorData().imageCompressed().empty() &&
3250 s->sensorData().laserScanCompressed().isEmpty())
3252 scansToLoad.push_back(
s);
3272 float guessNorm = guess.
getNorm();
3277 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());
3284 int maxPoints = fromScan.
size();
3285 pcl::PointCloud<pcl::PointXYZ>::Ptr assembledToClouds(
new pcl::PointCloud<pcl::PointXYZ>);
3286 pcl::PointCloud<pcl::PointNormal>::Ptr assembledToNormalClouds(
new pcl::PointCloud<pcl::PointNormal>);
3287 pcl::PointCloud<pcl::PointXYZI>::Ptr assembledToIClouds(
new pcl::PointCloud<pcl::PointXYZI>);
3288 pcl::PointCloud<pcl::PointXYZINormal>::Ptr assembledToNormalIClouds(
new pcl::PointCloud<pcl::PointXYZINormal>);
3289 pcl::PointCloud<pcl::PointXYZRGB>::Ptr assembledToRGBClouds(
new pcl::PointCloud<pcl::PointXYZRGB>);
3290 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr assembledToNormalRGBClouds(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3291 UDEBUG(
"maxPoints from(%d) = %d", fromId, maxPoints);
3292 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
3294 if(
iter->first != fromId)
3300 s->sensorData().uncompressData(0, 0, &scan);
3343 if(scan.
size() > maxPoints)
3345 UDEBUG(
"maxPoints scan(%d) = %d",
iter->first, (
int)scan.
size());
3346 maxPoints = scan.
size();
3356 UWARN(
"Depth2D not found for signature %d",
iter->first);
3362 if(assembledToNormalClouds->size())
3366 else if(assembledToClouds->size())
3370 else if(assembledToNormalIClouds->size())
3374 else if(assembledToIClouds->size())
3378 else if(assembledToNormalRGBClouds->size())
3382 UERROR(
"Cannot handle 2d scan with RGB format.");
3389 else if(assembledToRGBClouds->size())
3393 UERROR(
"Cannot handle 2d scan with RGB format.");
3400 UDEBUG(
"assembledScan=%d points", assembledScan.
size());
3432 UINFO(
"already linked! to=%d, from=%d", link.
to(), link.
from());
3436 UDEBUG(
"Add link between %d and %d", toS->
id(), fromS->
id());
3472 else if(!addInDatabase)
3476 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
from());
3480 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
to());
3486 UDEBUG(
"Add link between %d and %d (db)", link.
from(), link.
to());
3492 UDEBUG(
"Add link between %d (db) and %d", link.
from(), link.
to());
3498 UDEBUG(
"Add link between %d (db) and %d (db)", link.
from(), link.
to());
3529 UERROR(
"fromId=%d and toId=%d are not linked!", link.
from(), link.
to());
3532 else if(!updateInDatabase)
3536 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
from());
3540 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
to());
3545 UDEBUG(
"Update link between %d and %d (db)", link.
from(), link.
to());
3552 UDEBUG(
"Update link between %d (db) and %d", link.
from(), link.
to());
3559 UDEBUG(
"Update link between %d (db) and %d (db)", link.
from(), link.
to());
3570 iter->second->removeVirtualLinks();
3580 const std::multimap<int, Link> & links =
s->getLinks();
3581 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
3592 UERROR(
"Link %d of %d not in WM/STM?!?",
iter->first,
s->id());
3596 s->removeVirtualLinks();
3600 UERROR(
"Signature %d not in WM/STM?!?", signatureId);
3606 UINFO(
"Dumping memory to directory \"%s\"", directory.c_str());
3626 fopen_s(&foutSign, fileNameSign,
"w");
3628 foutSign = fopen(fileNameSign,
"w");
3633 fprintf(foutSign,
"SignatureID WordsID...\n");
3634 const std::map<int, Signature *> & signatures = this->
getSignatures();
3635 for(std::map<int, Signature *>::const_iterator
iter=signatures.begin();
iter!=signatures.end(); ++
iter)
3637 fprintf(foutSign,
"%d ",
iter->first);
3645 const std::multimap<int, int> &
ref = ss->
getWords();
3646 for(std::multimap<int, int>::const_iterator jter=
ref.begin(); jter!=
ref.end(); ++jter)
3648 const cv::Point3f & pt = ss->
getWords3()[jter->second];
3650 if(pcl::isFinite(pt) &&
3651 (pt.x != 0 || pt.y != 0 || pt.z != 0))
3653 fprintf(foutSign,
"%d ", (*jter).first);
3660 const std::multimap<int, int> &
ref = ss->
getWords();
3661 for(std::multimap<int, int>::const_iterator jter=
ref.begin(); jter!=
ref.end(); ++jter)
3663 fprintf(foutSign,
"%d ", (*jter).first);
3667 fprintf(foutSign,
"\n");
3678 fopen_s(&foutTree, fileNameTree,
"w");
3680 foutTree = fopen(fileNameTree,
"w");
3685 fprintf(foutTree,
"SignatureID Weight NbLoopClosureIds LoopClosureIds... NbChildLoopClosureIds ChildLoopClosureIds...\n");
3689 fprintf(foutTree,
"%d %d",
i->first,
i->second->getWeight());
3691 std::map<int, Link> loopIds, childIds;
3693 for(std::map<int, Link>::const_iterator
iter =
i->second->getLinks().begin();
3694 iter!=
i->second->getLinks().end();
3700 if(
iter->first <
i->first)
3702 childIds.insert(*
iter);
3704 else if(
iter->second.from() !=
iter->second.to())
3706 loopIds.insert(*
iter);
3711 fprintf(foutTree,
" %d", (
int)loopIds.size());
3712 for(std::map<int, Link>::const_iterator
j=loopIds.begin();
j!=loopIds.end(); ++
j)
3714 fprintf(foutTree,
" %d",
j->first);
3717 fprintf(foutTree,
" %d", (
int)childIds.size());
3718 for(std::map<int, Link>::const_iterator
j=childIds.begin();
j!=childIds.end(); ++
j)
3720 fprintf(foutTree,
" %d",
j->first);
3723 fprintf(foutTree,
"\n");
3733 unsigned long memoryUsage =
sizeof(
Memory);
3734 memoryUsage +=
_signatures.size() * (
sizeof(
int)+
sizeof(std::map<int, Signature *>::iterator)) +
sizeof(std::map<int, Signature *>);
3737 memoryUsage +=
iter->second->getMemoryUsed(
true);
3743 memoryUsage +=
_stMem.size() * (
sizeof(
int)+
sizeof(std::set<int>::iterator)) +
sizeof(std::set<int>);
3744 memoryUsage +=
_workingMem.size() * (
sizeof(
int)+
sizeof(
double)+
sizeof(std::map<int, double>::iterator)) +
sizeof(std::map<int, double>);
3745 memoryUsage +=
_groundTruths.size() * (
sizeof(
int)+
sizeof(
Transform)+12*
sizeof(
float) +
sizeof(std::map<int, Transform>::iterator)) +
sizeof(std::map<int, Transform>);
3746 memoryUsage +=
_labels.size() * (
sizeof(
int)+
sizeof(std::string) +
sizeof(std::map<int, std::string>::iterator)) +
sizeof(std::map<int, std::string>);
3749 memoryUsage+=
iter->second.size();
3751 memoryUsage +=
_landmarksIndex.size() * (
sizeof(
int)+
sizeof(std::set<int>) +
sizeof(std::map<int, std::set<int> >
::iterator)) +
sizeof(std::map<int, std::set<int> >);
3754 memoryUsage+=
iter->second.size()*(
sizeof(
int)+
sizeof(std::set<int>::iterator)) +
sizeof(std::set<int>);
3783 if(
s->getWeight() >= 0 &&
s->id() != signature->
id())
3792 UDEBUG(
"Comparing with signature (%d)...",
id);
3812 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_merged(), merged);
3813 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_sim(), sim);
3815 UDEBUG(
"merged=%d, sim=%f t=%fs", merged, sim,
timer.ticks());
3819 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_merged(), 0);
3820 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_sim(), 0);
3832 std::map<int, Link>::const_iterator
iter = oldS->
getLinks().find(newS->
id());
3836 iter->second.from() !=
iter->second.to())
3839 UWARN(
"already merged, old=%d, new=%d", oldId, newId);
3844 UINFO(
"Rehearsal merging %d (w=%d) and %d (w=%d)",
3849 bool intermediateMerge =
false;
3850 if(!newS->
getLinks().empty() && !newS->
getLinks().begin()->second.transform().isNull())
3865 UINFO(
"Rehearsal ignored because the robot has moved more than %f m or %f rad (\"Mem/RehearsalWeightIgnoredWhileMoving\"=true)",
3869 fullMerge = !isMoving && newS->
hasLink(oldS->
id());
3870 intermediateMerge = !isMoving && !newS->
hasLink(oldS->
id());
3874 fullMerge = newS->
hasLink(oldS->
id()) && newS->
getLinks().begin()->second.transform().isNull();
3876 UDEBUG(
"fullMerge=%s intermediateMerge=%s _idUpdatedToNewOneRehearsal=%s",
3877 fullMerge?
"true":
"false",
3878 intermediateMerge?
"true":
"false",
3891 const std::multimap<int, Link> & links = oldS->
getLinks();
3892 for(std::multimap<int, Link>::const_iterator
iter = links.begin();
iter!=links.end(); ++
iter)
3894 if(
iter->second.from() !=
iter->second.to())
3904 s->removeLink(oldS->
id());
3911 UERROR(
"Didn't find neighbor %d of %d in RAM...", link.
to(), oldS->
id());
3960 oldS->
setWeight(intermediateMerge?-1:0);
3971 newS->
setWeight(intermediateMerge?-1:0);
3979 UERROR(
"newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, newId);
3983 UERROR(
"newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, oldId);
3992 int mapId = -1, weight;
3998 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
4011 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
4024 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
4039 getNodeInfo(
id, odomPose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
4041 if(gps.
stamp() == 0.0)
4045 std::map<int, int> nearestIds;
4046 nearestIds =
getNeighborsId(
id, maxGraphDepth, lookInDatabase?-1:0,
true,
false,
true);
4047 std::multimap<int, int> nearestIdsSorted;
4048 for(std::map<int, int>::iterator
iter=nearestIds.begin();
iter!=nearestIds.end(); ++
iter)
4050 nearestIdsSorted.insert(std::make_pair(
iter->second,
iter->first));
4053 for(std::map<int, int>::iterator
iter=nearestIdsSorted.begin();
iter!=nearestIdsSorted.end(); ++
iter)
4057 if(
s->sensorData().gps().stamp() > 0.0)
4060 if(
path.size() >= 2)
4062 gps =
s->sensorData().gps();
4064 offsetENU = localToENU*(
s->getPose().rotation()*
path.rbegin()->second);
4069 UWARN(
"Failed to find path %d -> %d",
s->id(),
id);
4080 std::string & label,
4083 std::vector<float> & velocity,
4086 bool lookInDatabase)
const
4091 odomPose =
s->getPose().clone();
4093 weight =
s->getWeight();
4094 label = std::string(
s->getLabel());
4095 stamp =
s->getStamp();
4096 groundTruth =
s->getGroundTruthPose().clone();
4097 velocity = std::vector<float>(
s->getVelocity());
4098 gps =
GPS(
s->sensorData().gps());
4099 sensors =
EnvSensors(
s->sensorData().envSensors());
4115 image =
s->sensorData().imageCompressed();
4121 image =
data.imageCompressed();
4131 if(
s && (!
s->isSaved() ||
4132 ((!images || !
s->sensorData().imageCompressed().empty()) &&
4133 (!scan || !
s->sensorData().laserScanCompressed().isEmpty()) &&
4134 (!userData || !
s->sensorData().userDataCompressed().empty()) &&
4135 (!occupancyGrid ||
s->sensorData().gridCellSize() != 0.0f))))
4137 r =
s->sensorData();
4140 r.
setRGBDImage(cv::Mat(), cv::Mat(), std::vector<CameraModel>());
4165 std::multimap<int, int> & words,
4166 std::vector<cv::KeyPoint> & wordsKpts,
4167 std::vector<cv::Point3f> & words3,
4168 cv::Mat & wordsDescriptors,
4169 std::vector<GlobalDescriptor> & globalDescriptors)
const
4175 words =
s->getWords();
4176 wordsKpts =
s->getWordsKpts();
4177 words3 =
s->getWords3();
4178 wordsDescriptors =
s->getWordsDescriptors();
4179 globalDescriptors =
s->sensorData().globalDescriptors();
4184 std::list<Signature*> signatures;
4186 ids.push_back(nodeId);
4187 std::set<int> loadedFromTrash;
4189 if(signatures.size())
4191 words = signatures.front()->getWords();
4192 wordsKpts = signatures.front()->getWordsKpts();
4193 words3 = signatures.front()->getWords3();
4194 wordsDescriptors = signatures.front()->getWordsDescriptors();
4195 globalDescriptors = signatures.front()->sensorData().globalDescriptors();
4196 if(loadedFromTrash.size())
4203 delete signatures.front();
4210 std::vector<CameraModel> & models,
4211 std::vector<StereoCameraModel> & stereoModels)
const
4217 models =
s->sensorData().cameraModels();
4218 stereoModels =
s->sensorData().stereoCameraModels();
4231 UERROR(
"A database must must loaded first...");
4239 const std::map<int, Transform> & poses,
4240 const cv::Mat & map,
4249 UERROR(
"A database must be loaded first...");
4253 if(poses.empty() || poses.lower_bound(1) == poses.end())
4267 for(std::map<int, Transform>::const_iterator
iter=poses.lower_bound(1);
iter!=poses.end(); ++
iter)
4272 UINFO(
"Processing %d grids...", maxPoses);
4273 int processedGrids = 1;
4274 int gridsScansModified = 0;
4275 for(std::map<int, Transform>::const_iterator
iter=poses.lower_bound(1);
iter!=poses.end(); ++
iter, ++processedGrids)
4279 cv::Mat gridObstacles;
4285 data.uncompressData(0,0,&scan,0,&gridGround,&gridObstacles,&gridEmpty);
4287 if(!gridObstacles.empty())
4290 cv::Mat filtered = cv::Mat(1, gridObstacles.cols, gridObstacles.type());
4292 for(
int i=0;
i<gridObstacles.cols; ++
i)
4294 const float * ptr = gridObstacles.ptr<
float>(0,
i);
4295 cv::Point3f pt(ptr[0], ptr[1], gridObstacles.channels()==2?0:ptr[2]);
4298 int x =
int((pt.x - xMin) / cellSize + 0.5f);
4299 int y =
int((pt.y - yMin) / cellSize + 0.5f);
4301 if(
x>=0 &&
x<map.cols &&
4304 bool obstacleDetected =
false;
4306 for(
int j=-cropRadius;
j<=cropRadius && !obstacleDetected; ++
j)
4308 for(
int k=-cropRadius; k<=cropRadius && !obstacleDetected; ++k)
4310 if(
x+
j>=0 &&
x+
j<map.cols &&
4311 y+k>=0 &&
y+k<map.rows &&
4312 map.at<
unsigned char>(
y+k,
x+
j) == 100)
4314 obstacleDetected =
true;
4319 if(map.at<
unsigned char>(
y,
x) != 0 || obstacleDetected)
4328 if(oi != gridObstacles.cols)
4330 UINFO(
"Grid id=%d (%d/%d) filtered %d -> %d",
iter->first, processedGrids, maxPoses, gridObstacles.cols, oi);
4331 gridsScansModified += 1;
4335 cv::Mat newObstacles = cv::Mat(filtered,
cv::Range::all(), cv::Range(0, oi));
4336 bool modifyDb =
true;
4339 s->sensorData().setOccupancyGrid(gridGround, newObstacles, gridEmpty, cellSize,
data.gridViewPoint());
4353 data.gridViewPoint());
4358 if(filterScans && !scan.
isEmpty())
4362 cv::Mat filtered = cv::Mat(1, scan.
size(), scan.
dataType());
4364 for(
int i=0;
i<scan.
size(); ++
i)
4366 const float * ptr = scan.
data().ptr<
float>(0,
i);
4367 cv::Point3f pt(ptr[0], ptr[1], scan.
is2d()?0:ptr[2]);
4370 int x =
int((pt.x - xMin) / cellSize + 0.5f);
4371 int y =
int((pt.y - yMin) / cellSize + 0.5f);
4373 if(
x>=0 &&
x<map.cols &&
4376 bool obstacleDetected =
false;
4378 for(
int j=-cropRadius;
j<=cropRadius && !obstacleDetected; ++
j)
4380 for(
int k=-cropRadius; k<=cropRadius && !obstacleDetected; ++k)
4382 if(
x+
j>=0 &&
x+
j<map.cols &&
4383 y+k>=0 &&
y+k<map.rows &&
4384 map.at<
unsigned char>(
y+k,
x+
j) == 100)
4386 obstacleDetected =
true;
4391 if(map.at<
unsigned char>(
y,
x) != 0 || obstacleDetected)
4400 if(oi != scan.
size())
4402 UINFO(
"Scan id=%d (%d/%d) filtered %d -> %d",
iter->first, processedGrids, maxPoses, (
int)scan.
size(), oi);
4403 gridsScansModified += 1;
4432 bool modifyDb =
true;
4435 s->sensorData().setLaserScan(scan,
true);
4450 return gridsScansModified;
4479 id.push_back(to->
id());
4485 UDEBUG(
"Loaded image data from database");
4497 ULOGGER_ERROR(
"Can't merge the signatures because there are not same type.");
4523 data.imageRaw().type() == CV_8UC1 ||
4524 data.imageRaw().type() == CV_8UC3);
4526 ( (
data.depthOrRightRaw().type() == CV_16UC1 ||
4527 data.depthOrRightRaw().type() == CV_32FC1 ||
4528 data.depthOrRightRaw().type() == CV_8UC1)
4530 ( (
data.imageRaw().empty() &&
data.depthOrRightRaw().type() != CV_8UC1) ||
4531 (
data.depthOrRightRaw().rows <=
data.imageRaw().rows &&
data.depthOrRightRaw().cols <=
data.imageRaw().cols))),
4532 uFormat(
"image=(%d/%d, type=%d, [accepted=%d,%d]) depth=(%d/%d, type=%d [accepted=%d(depth mm),%d(depth m),%d(stereo)]). "
4533 "For stereo, left and right images should be same size. "
4534 "For RGB-D, depth can be X times smaller than RGB (where X is an integer).",
4535 data.imageRaw().cols,
4536 data.imageRaw().rows,
4537 data.imageRaw().type(),
4540 data.depthOrRightRaw().cols,
4541 data.depthOrRightRaw().rows,
4542 data.depthOrRightRaw().type(),
4543 CV_16UC1, CV_32FC1, CV_8UC1).c_str());
4545 if(!
data.depthOrRightRaw().empty() &&
4546 data.cameraModels().empty() &&
4547 data.stereoCameraModels().empty() &&
4550 UERROR(
"No camera calibration found, calibrate your camera!");
4560 std::vector<cv::KeyPoint> keypoints;
4561 cv::Mat descriptors;
4562 bool isIntermediateNode =
data.id() < 0;
4572 UERROR(
"Received image ID is null. "
4573 "Please set parameter Mem/GenerateIds to \"true\" or "
4574 "make sure the input source provides image ids (seq).");
4583 UERROR(
"Id of acquired image (%d) is smaller than the last in memory (%d). "
4584 "Please set parameter Mem/GenerateIds to \"true\" or "
4585 "make sure the input source provides image ids (seq) over the last in "
4586 "memory, which is %d.",
4599 if(
data.cameraModels().size())
4601 UDEBUG(
"Monocular rectification");
4603 UASSERT(
int((
data.imageRaw().cols/
data.cameraModels().size())*
data.cameraModels().size()) ==
data.imageRaw().cols);
4604 int subImageWidth =
data.imageRaw().cols/
data.cameraModels().size();
4605 cv::Mat rectifiedImages(
data.imageRaw().size(),
data.imageRaw().type());
4611 for(
unsigned int i=0;
i<
data.cameraModels().
size(); ++
i)
4613 if(
data.cameraModels()[
i].isValidForRectification())
4620 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)...",
i);
4622 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)... done!",
i);
4627 cv::Mat rectifiedImage =
_rectCameraModels[
i].rectifyImage(cv::Mat(
data.imageRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4628 rectifiedImage.copyTo(cv::Mat(rectifiedImages, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4629 imagesRectified =
true;
4633 UERROR(
"Calibration for camera %d cannot be used to rectify the image. Make sure to do a "
4634 "full calibration. If images are already rectified, set %s parameter back to true.",
4636 Parameters::kRtabmapImagesAlreadyRectified().
c_str());
4637 std::cout <<
data.cameraModels()[
i] << std::endl;
4641 data.setRGBDImage(rectifiedImages,
data.depthOrRightRaw(),
data.cameraModels());
4643 else if(
data.stereoCameraModels().size())
4645 UDEBUG(
"Stereo rectification");
4646 UASSERT(
int((
data.imageRaw().cols/
data.stereoCameraModels().size())*
data.stereoCameraModels().size()) ==
data.imageRaw().cols);
4647 int subImageWidth =
data.imageRaw().cols/
data.stereoCameraModels().size();
4648 UASSERT(subImageWidth ==
data.rightRaw().cols/(
int)
data.stereoCameraModels().size());
4649 cv::Mat rectifiedLefts(
data.imageRaw().size(),
data.imageRaw().type());
4650 cv::Mat rectifiedRights(
data.rightRaw().size(),
data.rightRaw().type());
4657 for(
unsigned int i=0;
i<
data.stereoCameraModels().
size(); ++
i)
4659 if(
data.stereoCameraModels()[
i].isValidForRectification())
4666 UWARN(
"Initializing rectification maps (only done for the first image received)...");
4668 UWARN(
"Initializing rectification maps (only done for the first image received)...done!");
4674 cv::Mat rectifiedLeft =
_rectStereoCameraModels[
i].left().rectifyImage(cv::Mat(
data.imageRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4675 cv::Mat rectifiedRight =
_rectStereoCameraModels[
i].right().rectifyImage(cv::Mat(
data.rightRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.rightRaw().rows)));
4676 rectifiedLeft.copyTo(cv::Mat(rectifiedLefts, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4677 rectifiedRight.copyTo(cv::Mat(rectifiedRights, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.rightRaw().rows)));
4678 imagesRectified =
true;
4682 UERROR(
"Calibration for camera %d cannot be used to rectify the image. Make sure to do a "
4683 "full calibration. If images are already rectified, set %s parameter back to true.",
4685 Parameters::kRtabmapImagesAlreadyRectified().
c_str());
4686 std::cout <<
data.stereoCameraModels()[
i] << std::endl;
4691 data.setStereoImage(
4694 data.stereoCameraModels());
4698 UERROR(
"Stereo calibration cannot be used to rectify images. Make sure to do a "
4699 "full stereo calibration. If images are already rectified, set %s parameter back to true.",
4700 Parameters::kRtabmapImagesAlreadyRectified().
c_str());
4704 if(
stats)
stats->addStatistic(Statistics::kTimingMemRectification(),
t*1000.0
f);
4705 UDEBUG(
"time rectification = %fs",
t);
4717 UDEBUG(
"Start dictionary update thread");
4718 preUpdateThread.
start();
4724 UASSERT(
int((
data.imageRaw().cols/
data.cameraModels().size())*
data.cameraModels().size()) ==
data.imageRaw().cols);
4725 int subInputImageWidth =
data.imageRaw().cols/
data.cameraModels().size();
4726 int subInputDepthWidth =
data.depthRaw().cols/
data.cameraModels().size();
4727 int subOutputImageWidth = 0;
4728 int subOutputDepthWidth = 0;
4729 cv::Mat rotatedColorImages;
4730 cv::Mat rotatedDepthImages;
4731 std::vector<CameraModel> rotatedCameraModels;
4732 bool allOutputSizesAreOkay =
true;
4733 bool atLeastOneCameraRotated =
false;
4734 for(
size_t i=0;
i<
data.cameraModels().
size(); ++
i)
4736 UDEBUG(
"Rotating camera %ld",
i);
4737 cv::Mat rgb = cv::Mat(
data.imageRaw(), cv::Rect(subInputImageWidth*
i, 0, subInputImageWidth,
data.imageRaw().rows));
4738 cv::Mat depth = !
data.depthRaw().empty()?cv::Mat(
data.depthRaw(), cv::Rect(subInputDepthWidth*
i, 0, subInputDepthWidth,
data.depthRaw().rows)):cv::Mat();
4741 if(rotatedColorImages.empty())
4743 rotatedColorImages = cv::Mat(cv::Size(rgb.cols *
data.cameraModels().size(), rgb.rows), rgb.type());
4744 subOutputImageWidth = rgb.cols;;
4747 rotatedDepthImages = cv::Mat(cv::Size(depth.cols *
data.cameraModels().size(), depth.rows), depth.type());
4748 subOutputDepthWidth = depth.cols;
4751 else if(rgb.cols != subOutputImageWidth || depth.cols != subOutputDepthWidth ||
4752 rgb.rows != rotatedColorImages.rows || depth.rows != rotatedDepthImages.rows)
4754 UWARN(
"Rotated image for camera index %d (rgb=%dx%d depth=%dx%d) doesn't tally "
4755 "with the first camera (rgb=%dx%d, depth=%dx%d). Aborting upside up rotation, "
4756 "will use original image orientation. Set parameter %s to false to avoid "
4760 depth.cols, depth.rows,
4761 subOutputImageWidth, rotatedColorImages.rows,
4762 subOutputDepthWidth, rotatedDepthImages.rows,
4763 Parameters::kMemRotateImagesUpsideUp().c_str());
4764 allOutputSizesAreOkay =
false;
4767 rgb.copyTo(cv::Mat(rotatedColorImages, cv::Rect(subOutputImageWidth*
i, 0, subOutputImageWidth, rgb.rows)));
4770 depth.copyTo(cv::Mat(rotatedDepthImages, cv::Rect(subOutputDepthWidth*
i, 0, subOutputDepthWidth, depth.rows)));
4772 rotatedCameraModels.push_back(
model);
4774 if(allOutputSizesAreOkay && atLeastOneCameraRotated)
4776 data.setRGBDImage(rotatedColorImages, rotatedDepthImages, rotatedCameraModels);
4779 if(!
data.keypoints().empty() || !
data.keypoints3D().empty() || !
data.descriptors().empty())
4783 static bool warned =
false;
4786 UWARN(
"Because parameter %s is enabled, parameter %s is inhibited as "
4787 "features have to be regenerated. To avoid this warning, set "
4788 "explicitly %s to false. This message is only "
4790 Parameters::kMemRotateImagesUpsideUp().
c_str(),
4791 Parameters::kMemUseOdomFeatures().
c_str(),
4792 Parameters::kMemUseOdomFeatures().
c_str());
4796 data.setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
4802 static bool warned =
false;
4805 UWARN(
"Parameter %s can only be used with RGB-only or RGB-D cameras. "
4806 "Ignoring upside up rotation. This message is only printed once.",
4807 Parameters::kMemRotateImagesUpsideUp().
c_str());
4812 unsigned int preDecimation = 1;
4813 std::vector<cv::Point3f> keypoints3D;
4815 UDEBUG(
"Received kpts=%d kpts3D=%d, descriptors=%d _useOdometryFeatures=%s",
4818 data.keypoints().empty() ||
4819 (
int)
data.keypoints().size() !=
data.descriptors().rows ||
4824 decimatedData =
data;
4829 if( !
data.cameraModels().empty() &&
4830 data.cameraModels()[0].imageHeight()>0 &&
4831 data.cameraModels()[0].imageWidth()>0)
4835 if(targetSize >=
data.depthRaw().rows)
4837 decimationDepth = 1;
4841 decimationDepth = (
int)
ceil(
float(
data.depthRaw().rows) /
float(targetSize));
4846 std::vector<CameraModel> cameraModels = decimatedData.
cameraModels();
4847 for(
unsigned int i=0;
i<cameraModels.size(); ++
i)
4851 if(!cameraModels.empty())
4859 std::vector<StereoCameraModel> stereoCameraModels = decimatedData.
stereoCameraModels();
4860 for(
unsigned int i=0;
i<stereoCameraModels.size(); ++
i)
4864 if(!stereoCameraModels.empty())
4869 stereoCameraModels);
4873 UINFO(
"Extract features");
4875 if(decimatedData.
imageRaw().channels() == 3)
4877 cv::cvtColor(decimatedData.
imageRaw(), imageMono, CV_BGR2GRAY);
4881 imageMono = decimatedData.
imageRaw();
4887 if(imageMono.rows % decimatedData.
depthRaw().rows == 0 &&
4888 imageMono.cols % decimatedData.
depthRaw().cols == 0 &&
4889 imageMono.rows/decimatedData.
depthRaw().rows == imageMono.cols/decimatedData.
depthRaw().cols)
4891 depthMask = decimatedData.
depthRaw();
4901 depthMask = depthBelow;
4907 UDEBUG(
"Masking floor done.");
4914 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).",
4915 Parameters::kMemDepthAsMask().
c_str(),
4916 imageMono.cols, imageMono.rows,
4922 bool useProvided3dPoints =
false;
4925 UDEBUG(
"Using provided keypoints (%d)", (
int)
data.keypoints().size());
4926 keypoints =
data.keypoints();
4928 useProvided3dPoints = keypoints.size() ==
data.keypoints3D().size();
4936 for(
unsigned int i=0;
i < keypoints.size(); ++
i)
4938 cv::KeyPoint & kpt = keypoints[
i];
4941 kpt.pt.x *= decimationRatio;
4942 kpt.pt.y *= decimationRatio;
4943 kpt.size *= decimationRatio;
4944 kpt.octave += log2value;
4946 if(useProvided3dPoints)
4948 keypoints[
i].class_id =
i;
4970 if(tmpMaxFeatureParameter.size())
4972 tmpMaxFeatureParameter.at(Parameters::kKpMaxFeatures()) =
uNumber2Str(oldMaxFeatures);
4976 if(
stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_detection(),
t*1000.0
f);
4977 UDEBUG(
"time keypoints (%d) = %fs", (
int)keypoints.size(),
t);
4982 if(
stats)
stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(),
t*1000.0
f);
4983 UDEBUG(
"time descriptors (%d) = %fs", descriptors.rows,
t);
4986 if(descriptors.rows && descriptors.rows <
_badSignRatio *
float(meanWordsPerLocation))
4988 descriptors = cv::Mat();
4992 if(!imagesRectified && decimatedData.
cameraModels().size())
4994 UASSERT_MSG((
int)keypoints.size() == descriptors.rows,
uFormat(
"%d vs %d", (
int)keypoints.size(), descriptors.rows).c_str());
4995 std::vector<cv::KeyPoint> keypointsValid;
4996 keypointsValid.reserve(keypoints.size());
4997 cv::Mat descriptorsValid;
4998 descriptorsValid.reserve(descriptors.rows);
5003 std::vector<cv::Point2f> pointsIn, pointsOut;
5004 cv::KeyPoint::convert(keypoints,pointsIn);
5007 #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)))
5010 cv::Mat
D(1, 4, CV_64FC1);
5011 D.at<
double>(0,0) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,0);
5012 D.at<
double>(0,1) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,1);
5013 D.at<
double>(0,2) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,4);
5014 D.at<
double>(0,3) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,5);
5015 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5023 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5024 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5029 cv::undistortPoints(pointsIn, pointsOut,
5035 UASSERT(pointsOut.size() == keypoints.size());
5036 for(
unsigned int i=0;
i<pointsOut.size(); ++
i)
5038 if(pointsOut.at(
i).x>=0 && pointsOut.at(
i).x<decimatedData.
cameraModels()[0].imageWidth() &&
5039 pointsOut.at(
i).y>=0 && pointsOut.at(
i).y<decimatedData.
cameraModels()[0].imageHeight())
5041 keypointsValid.push_back(keypoints.at(
i));
5042 keypointsValid.back().pt.x = pointsOut.at(
i).x;
5043 keypointsValid.back().pt.y = pointsOut.at(
i).y;
5044 descriptorsValid.push_back(descriptors.row(
i));
5052 for(
unsigned int i=0;
i<keypoints.size(); ++
i)
5054 int cameraIndex =
int(keypoints.at(
i).pt.x / subImageWidth);
5056 uFormat(
"cameraIndex=%d, models=%d, kpt.x=%f, subImageWidth=%f (Camera model image width=%d)",
5057 cameraIndex, (
int)decimatedData.
cameraModels().size(), keypoints[
i].pt.x, subImageWidth, decimatedData.
cameraModels()[0].imageWidth()).c_str());
5059 std::vector<cv::Point2f> pointsIn, pointsOut;
5060 pointsIn.push_back(cv::Point2f(keypoints.at(
i).pt.x-subImageWidth*cameraIndex, keypoints.at(
i).pt.y));
5061 if(decimatedData.
cameraModels()[cameraIndex].D_raw().cols == 6)
5063 #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)))
5066 cv::Mat
D(1, 4, CV_64FC1);
5067 D.at<
double>(0,0) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,0);
5068 D.at<
double>(0,1) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,1);
5069 D.at<
double>(0,2) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,4);
5070 D.at<
double>(0,3) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,5);
5071 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5079 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5080 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5085 cv::undistortPoints(pointsIn, pointsOut,
5092 if(pointsOut[0].
x>=0 && pointsOut[0].
x<decimatedData.
cameraModels()[cameraIndex].imageWidth() &&
5093 pointsOut[0].y>=0 && pointsOut[0].y<decimatedData.
cameraModels()[cameraIndex].imageHeight())
5095 keypointsValid.push_back(keypoints.at(
i));
5096 keypointsValid.back().pt.x = pointsOut[0].x + subImageWidth*cameraIndex;
5097 keypointsValid.back().pt.y = pointsOut[0].y;
5098 descriptorsValid.push_back(descriptors.row(
i));
5103 keypoints = keypointsValid;
5104 descriptors = descriptorsValid;
5107 if(
stats)
stats->addStatistic(Statistics::kTimingMemRectification(),
t*1000.0
f);
5108 UDEBUG(
"time rectification = %fs",
t);
5111 if(useProvided3dPoints && keypoints.size() !=
data.keypoints3D().size())
5113 UDEBUG(
"Using provided 3d points (%d->%d)", (
int)
data.keypoints3D().size(), (
int)keypoints.size());
5114 keypoints3D.resize(keypoints.size());
5115 for(
size_t i=0;
i<keypoints.size(); ++
i)
5117 UASSERT(keypoints[
i].class_id < (
int)
data.keypoints3D().size());
5118 keypoints3D[
i] =
data.keypoints3D()[keypoints[
i].class_id];
5121 else if(useProvided3dPoints && keypoints.size() ==
data.keypoints3D().size())
5123 UDEBUG(
"Using provided 3d points (%d)", (
int)
data.keypoints3D().size());
5124 keypoints3D =
data.keypoints3D();
5131 if(
stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_3D(),
t*1000.0
f);
5132 UDEBUG(
"time keypoints 3D (%d) = %fs", (
int)keypoints3D.size(),
t);
5140 else if(
data.imageRaw().empty())
5142 UDEBUG(
"Empty image, cannot extract features...");
5144 else if(_feature2D->getMaxFeatures() < 0)
5146 UDEBUG(
"_feature2D->getMaxFeatures()(%d<0) so don't extract any features...", _feature2D->getMaxFeatures());
5150 UDEBUG(
"Intermediate node detected, don't extract features!");
5153 else if(_feature2D->getMaxFeatures() >= 0 && !isIntermediateNode)
5155 UINFO(
"Use odometry features: kpts=%d 3d=%d desc=%d (dim=%d, type=%d)",
5156 (
int)
data.keypoints().size(),
5157 (
int)
data.keypoints3D().size(),
5158 data.descriptors().rows,
5159 data.descriptors().cols,
5160 data.descriptors().type());
5161 keypoints =
data.keypoints();
5162 keypoints3D =
data.keypoints3D();
5163 descriptors =
data.descriptors().clone();
5165 UASSERT(descriptors.empty() || descriptors.rows == (
int)keypoints.size());
5166 UASSERT(keypoints3D.empty() || keypoints3D.size() == keypoints.size());
5168 int maxFeatures = _rawDescriptorsKept&&!pose.isNull()&&_feature2D->getMaxFeatures()>0&&_feature2D->getMaxFeatures()<_visMaxFeatures?_visMaxFeatures:_feature2D->getMaxFeatures();
5169 bool ssc = _rawDescriptorsKept&&!pose.isNull()&&_feature2D->getMaxFeatures()>0&&_feature2D->getMaxFeatures()<_visMaxFeatures?_visSSC:_feature2D->getSSC();
5170 if((
int)keypoints.size() > maxFeatures)
5172 if(
data.cameraModels().size()==1 ||
data.stereoCameraModels().size()==1)
5173 _feature2D->limitKeypoints(keypoints, keypoints3D, descriptors, maxFeatures,
data.cameraModels().size()?
data.cameraModels()[0].imageSize():
data.stereoCameraModels()[0].left().imageSize(), ssc);
5175 _feature2D->limitKeypoints(keypoints, keypoints3D, descriptors, maxFeatures);
5178 if(stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0f);
5179 UDEBUG(
"time keypoints (%d) = %fs", (
int)keypoints.size(), t);
5181 if(descriptors.empty())
5184 if(
data.imageRaw().channels() == 3)
5186 cv::cvtColor(
data.imageRaw(), imageMono, CV_BGR2GRAY);
5190 imageMono =
data.imageRaw();
5193 UASSERT_MSG(imagesRectified,
"Cannot extract descriptors on not rectified image from keypoints which assumed to be undistorted");
5194 descriptors = _feature2D->generateDescriptors(imageMono, keypoints);
5196 else if(!imagesRectified && !
data.cameraModels().empty())
5198 std::vector<cv::KeyPoint> keypointsValid;
5199 keypointsValid.reserve(keypoints.size());
5200 cv::Mat descriptorsValid;
5201 descriptorsValid.reserve(descriptors.rows);
5202 std::vector<cv::Point3f> keypoints3DValid;
5203 keypoints3DValid.reserve(keypoints3D.size());
5206 if(
data.cameraModels().size() == 1)
5208 std::vector<cv::Point2f> pointsIn, pointsOut;
5209 cv::KeyPoint::convert(keypoints,pointsIn);
5210 if(
data.cameraModels()[0].D_raw().cols == 6)
5212 #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)))
5215 cv::Mat
D(1, 4, CV_64FC1);
5216 D.at<
double>(0,0) =
data.cameraModels()[0].D_raw().at<
double>(0,0);
5217 D.at<
double>(0,1) =
data.cameraModels()[0].D_raw().at<
double>(0,1);
5218 D.at<
double>(0,2) =
data.cameraModels()[0].D_raw().at<
double>(0,4);
5219 D.at<
double>(0,3) =
data.cameraModels()[0].D_raw().at<
double>(0,5);
5220 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5221 data.cameraModels()[0].K_raw(),
5223 data.cameraModels()[0].R(),
5224 data.cameraModels()[0].P());
5228 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5229 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5234 cv::undistortPoints(pointsIn, pointsOut,
5235 data.cameraModels()[0].K_raw(),
5236 data.cameraModels()[0].D_raw(),
5237 data.cameraModels()[0].R(),
5238 data.cameraModels()[0].P());
5240 UASSERT(pointsOut.size() == keypoints.size());
5241 for(
unsigned int i=0;
i<pointsOut.size(); ++
i)
5243 if(pointsOut.at(i).x>=0 && pointsOut.at(i).x<
data.cameraModels()[0].imageWidth() &&
5244 pointsOut.at(i).y>=0 && pointsOut.at(i).y<
data.cameraModels()[0].imageHeight())
5246 keypointsValid.push_back(keypoints.at(i));
5247 keypointsValid.back().pt.x = pointsOut.at(i).x;
5248 keypointsValid.back().pt.y = pointsOut.at(i).y;
5249 descriptorsValid.push_back(descriptors.row(i));
5250 if(!keypoints3D.empty())
5252 keypoints3DValid.push_back(keypoints3D.at(i));
5259 float subImageWidth;
5260 if(!
data.imageRaw().empty())
5262 UASSERT(
int((
data.imageRaw().cols/
data.cameraModels().size())*
data.cameraModels().size()) ==
data.imageRaw().cols);
5263 subImageWidth =
data.imageRaw().cols/
data.cameraModels().size();
5268 subImageWidth =
data.cameraModels()[0].imageWidth();
5271 for(
unsigned int i=0;
i<keypoints.size(); ++
i)
5273 int cameraIndex =
int(keypoints.at(i).pt.x / subImageWidth);
5274 UASSERT_MSG(cameraIndex >= 0 && cameraIndex < (
int)
data.cameraModels().size(),
5275 uFormat(
"cameraIndex=%d, models=%d, kpt.x=%f, subImageWidth=%f (Camera model image width=%d)",
5276 cameraIndex, (
int)
data.cameraModels().size(), keypoints[i].pt.x, subImageWidth,
data.cameraModels()[0].imageWidth()).c_str());
5278 std::vector<cv::Point2f> pointsIn, pointsOut;
5279 pointsIn.push_back(cv::Point2f(keypoints.at(i).pt.x-subImageWidth*cameraIndex, keypoints.at(i).pt.y));
5280 if(
data.cameraModels()[cameraIndex].D_raw().cols == 6)
5282 #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)))
5285 cv::Mat
D(1, 4, CV_64FC1);
5286 D.at<
double>(0,0) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,0);
5287 D.at<
double>(0,1) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,1);
5288 D.at<
double>(0,2) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,4);
5289 D.at<
double>(0,3) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,5);
5290 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5291 data.cameraModels()[cameraIndex].K_raw(),
5293 data.cameraModels()[cameraIndex].R(),
5294 data.cameraModels()[cameraIndex].P());
5298 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5299 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5304 cv::undistortPoints(pointsIn, pointsOut,
5305 data.cameraModels()[cameraIndex].K_raw(),
5306 data.cameraModels()[cameraIndex].D_raw(),
5307 data.cameraModels()[cameraIndex].R(),
5308 data.cameraModels()[cameraIndex].P());
5311 if(pointsOut[0].x>=0 && pointsOut[0].x<
data.cameraModels()[cameraIndex].imageWidth() &&
5312 pointsOut[0].y>=0 && pointsOut[0].y<
data.cameraModels()[cameraIndex].imageHeight())
5314 keypointsValid.push_back(keypoints.at(i));
5315 keypointsValid.back().pt.x = pointsOut[0].x + subImageWidth*cameraIndex;
5316 keypointsValid.back().pt.y = pointsOut[0].y;
5317 descriptorsValid.push_back(descriptors.row(i));
5318 if(!keypoints3D.empty())
5320 keypoints3DValid.push_back(keypoints3D.at(i));
5326 keypoints = keypointsValid;
5327 descriptors = descriptorsValid;
5328 keypoints3D = keypoints3DValid;
5331 if(stats)
stats->addStatistic(Statistics::kTimingMemRectification(), t*1000.0f);
5332 UDEBUG(
"time rectification = %fs", t);
5335 if(stats)
stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0f);
5336 UDEBUG(
"time descriptors (%d) = %fs", descriptors.rows, t);
5338 if(keypoints3D.empty() &&
5339 ((!
data.depthRaw().empty() &&
data.cameraModels().size() &&
data.cameraModels()[0].isValidForProjection()) ||
5340 (!
data.rightRaw().empty() &&
data.stereoCameraModels().size() &&
data.stereoCameraModels()[0].isValidForProjection())))
5342 keypoints3D = _feature2D->generateKeypoints3D(data, keypoints);
5344 if(_feature2D->getMinDepth() > 0.0f || _feature2D->getMaxDepth() > 0.0f)
5346 _feature2D->filterKeypointsByDepth(keypoints, descriptors, keypoints3D, _feature2D->getMinDepth(), _feature2D->getMaxDepth());
5349 if(stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_3D(), t*1000.0f);
5350 UDEBUG(
"time keypoints 3D (%d) = %fs", (
int)keypoints3D.size(), t);
5352 UDEBUG(
"ratio=%f, meanWordsPerLocation=%d", _badSignRatio, meanWordsPerLocation);
5353 if(descriptors.rows && descriptors.rows < _badSignRatio *
float(meanWordsPerLocation))
5355 descriptors = cv::Mat();
5361 UDEBUG(
"Joining dictionary update thread...");
5362 preUpdateThread.join();
5363 UDEBUG(
"Joining dictionary update thread... thread finished!");
5367 if(stats)
stats->addStatistic(Statistics::kTimingMemJoining_dictionary_update(), t*1000.0f);
5370 UDEBUG(
"time descriptor and memory update (%d of size=%d) = %fs", descriptors.rows, descriptors.cols, t);
5374 UDEBUG(
"time descriptor (%d of size=%d) = %fs", descriptors.rows, descriptors.cols, t);
5377 std::list<int> wordIds;
5378 if(descriptors.rows)
5382 std::vector<bool> inliers;
5383 cv::Mat descriptorsForQuantization = descriptors;
5384 std::vector<int> quantizedToRawIndices;
5385 if(_feature2D->getMaxFeatures()>0 && descriptors.rows > _feature2D->getMaxFeatures())
5387 UASSERT((
int)keypoints.size() == descriptors.rows);
5388 int inliersCount = 0;
5389 if((_feature2D->getGridRows() > 1 || _feature2D->getGridCols() > 1) &&
5390 (decimatedData.cameraModels().size()==1 || decimatedData.stereoCameraModels().size()==1 ||
5391 data.cameraModels().size()==1 ||
data.stereoCameraModels().size()==1))
5393 Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures(),
5394 decimatedData.cameraModels().size()?decimatedData.cameraModels()[0].imageSize():
5395 decimatedData.stereoCameraModels().size()?decimatedData.stereoCameraModels()[0].left().imageSize():
5396 data.cameraModels().size()?
data.cameraModels()[0].imageSize():
data.stereoCameraModels()[0].left().imageSize(),
5397 _feature2D->getGridRows(), _feature2D->getGridCols(), _feature2D->getSSC());
5401 if(_feature2D->getGridRows() > 1 || _feature2D->getGridCols() > 1)
5403 UWARN(
"Ignored %s and %s parameters as they cannot be used for multi-cameras setup or uncalibrated camera.",
5404 Parameters::kKpGridCols().
c_str(), Parameters::kKpGridRows().
c_str());
5406 if(decimatedData.cameraModels().size()==1 || decimatedData.stereoCameraModels().size()==1 ||
5407 data.cameraModels().size()==1 ||
data.stereoCameraModels().size()==1)
5409 Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures(),
5410 decimatedData.cameraModels().size()?decimatedData.cameraModels()[0].imageSize():
5411 decimatedData.stereoCameraModels().size()?decimatedData.stereoCameraModels()[0].left().imageSize():
5412 data.cameraModels().size()?
data.cameraModels()[0].imageSize():
data.stereoCameraModels()[0].left().imageSize(),
5413 _feature2D->getSSC());
5417 Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures());
5420 for(
size_t i=0;
i<inliers.size(); ++
i)
5426 descriptorsForQuantization = cv::Mat(inliersCount, descriptors.cols, descriptors.type());
5427 quantizedToRawIndices.resize(inliersCount);
5429 UASSERT((
int)inliers.size() == descriptors.rows);
5430 for(
int k=0; k < descriptors.rows; ++k)
5434 UASSERT(oi < quantizedToRawIndices.size());
5435 if(descriptors.type() == CV_32FC1)
5437 memcpy(descriptorsForQuantization.ptr<
float>(oi), descriptors.ptr<
float>(k), descriptors.cols*
sizeof(
float));
5441 memcpy(descriptorsForQuantization.ptr<
char>(oi), descriptors.ptr<
char>(k), descriptors.cols*
sizeof(
char));
5443 quantizedToRawIndices[oi] = k;
5448 uFormat(
"oi=%d inliersCount=%d (maxFeatures=%d, grid=%dx%d)",
5449 oi, inliersCount, _feature2D->getMaxFeatures(), _feature2D->getGridCols(), _feature2D->getGridRows()).c_str());
5453 wordIds = _vwd->addNewWords(descriptorsForQuantization,
id);
5456 if(wordIds.size() < keypoints.size())
5458 std::vector<int> allWordIds;
5459 allWordIds.resize(keypoints.size(),-1);
5461 for(std::list<int>::iterator
iter=wordIds.begin();
iter!=wordIds.end(); ++
iter)
5463 allWordIds[quantizedToRawIndices[
i]] = *
iter;
5467 for(i=0;
i<(
int)allWordIds.size(); ++
i)
5469 if(allWordIds[i] < 0)
5471 allWordIds[
i] = negIndex--;
5478 if(stats)
stats->addStatistic(Statistics::kTimingMemAdd_new_words(), t*1000.0f);
5479 UDEBUG(
"time addNewWords %fs indexed=%d not=%d", t, _vwd->getIndexedWordsCount(), _vwd->getNotIndexedWordsCount());
5483 UDEBUG(
"id %d is a bad signature",
id);
5486 std::multimap<int, int> words;
5487 std::vector<cv::KeyPoint> wordsKpts;
5488 std::vector<cv::Point3f> words3D;
5489 cv::Mat wordsDescriptors;
5490 int words3DValid = 0;
5491 if(wordIds.size() > 0)
5493 UASSERT(wordIds.size() == keypoints.size());
5494 UASSERT(keypoints3D.size() == 0 || keypoints3D.size() == wordIds.size());
5496 float decimationRatio =
float(preDecimation) /
float(_imagePostDecimation);
5497 double log2value =
log(
double(preDecimation))/
log(2.0);
5498 for(std::list<int>::iterator
iter=wordIds.begin();
iter!=wordIds.end() && i < keypoints.size(); ++
iter, ++i)
5500 cv::KeyPoint kpt = keypoints[
i];
5501 if(preDecimation != _imagePostDecimation)
5504 kpt.pt.x *= decimationRatio;
5505 kpt.pt.y *= decimationRatio;
5506 kpt.size *= decimationRatio;
5507 kpt.octave += log2value;
5509 words.insert(std::make_pair(*
iter, words.size()));
5510 wordsKpts.push_back(kpt);
5512 if(keypoints3D.size())
5514 words3D.push_back(keypoints3D.at(i));
5515 if(util3d::isFinite(keypoints3D.at(i)))
5520 if(_rawDescriptorsKept)
5522 wordsDescriptors.push_back(descriptors.row(i));
5528 if(!landmarks.empty() && isIntermediateNode)
5530 UDEBUG(
"Landmarks provided (size=%ld) are ignored because this signature is set as intermediate.", landmarks.size());
5533 else if(_detectMarkers && !isIntermediateNode && !
data.imageRaw().empty())
5535 UDEBUG(
"Detecting markers...");
5536 if(landmarks.empty())
5538 std::vector<CameraModel> models =
data.cameraModels();
5541 for(
size_t i=0;
i<
data.stereoCameraModels().
size(); ++
i)
5543 models.push_back(
data.stereoCameraModels()[i].left());
5547 if(!models.empty() && models[0].isValidForProjection())
5549 std::map<int, MarkerInfo> markers = _markerDetector->detect(
data.imageRaw(), models,
data.depthRaw(), _landmarksSize);
5551 for(std::map<int, MarkerInfo>::iterator
iter=markers.begin();
iter!=markers.end(); ++
iter)
5553 if(
iter->first <= 0)
5555 UERROR(
"Invalid marker received! IDs should be > 0 (it is %d). Ignoring this marker.",
iter->first);
5558 cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1);
5559 covariance(cv::Range(0,3), cv::Range(0,3)) *= _markerLinVariance;
5560 covariance(cv::Range(3,6), cv::Range(3,6)) *= _markerAngVariance;
5561 landmarks.insert(std::make_pair(
iter->first, Landmark(
iter->first,
iter->second.length(),
iter->second.pose(), covariance)));
5563 UDEBUG(
"Markers detected = %d", (
int)markers.size());
5567 UWARN(
"No valid camera calibration for marker detection");
5572 UWARN(
"Input data has already landmarks, cannot do marker detection.");
5575 if(stats)
stats->addStatistic(Statistics::kTimingMemMarkers_detection(), t*1000.0f);
5576 UDEBUG(
"time markers detection = %fs", t);
5579 cv::Mat image =
data.imageRaw();
5580 cv::Mat depthOrRightImage =
data.depthOrRightRaw();
5581 std::vector<CameraModel> cameraModels =
data.cameraModels();
5582 std::vector<StereoCameraModel> stereoCameraModels =
data.stereoCameraModels();
5585 if(_imagePostDecimation > 1 && !isIntermediateNode)
5587 if(_imagePostDecimation == preDecimation && decimatedData.isValid())
5589 image = decimatedData.imageRaw();
5590 depthOrRightImage = decimatedData.depthOrRightRaw();
5591 cameraModels = decimatedData.cameraModels();
5592 stereoCameraModels = decimatedData.stereoCameraModels();
5596 int decimationDepth = _imagePreDecimation;
5597 if( !
data.cameraModels().empty() &&
5598 data.cameraModels()[0].imageHeight()>0 &&
5599 data.cameraModels()[0].imageWidth()>0)
5602 int targetSize =
data.cameraModels()[0].imageHeight() / _imagePreDecimation;
5603 if(targetSize >=
data.depthRaw().rows)
5605 decimationDepth = 1;
5609 decimationDepth = (
int)
ceil(
float(
data.depthRaw().rows) /
float(targetSize));
5612 UDEBUG(
"decimation rgbOrLeft(rows=%d)=%d, depthOrRight(rows=%d)=%d",
data.imageRaw().rows, _imagePostDecimation,
data.depthOrRightRaw().rows, decimationDepth);
5616 for(
unsigned int i=0;
i<cameraModels.size(); ++
i)
5618 cameraModels[
i] = cameraModels[
i].scaled(1.0/
double(_imagePostDecimation));
5620 for(
unsigned int i=0;
i<stereoCameraModels.size(); ++
i)
5622 stereoCameraModels[
i].scale(1.0/
double(_imagePostDecimation));
5626 if(!image.empty() && (depthOrRightImage.cols > image.cols || depthOrRightImage.rows > image.rows))
5628 UWARN(
"Depth image is bigger than RGB image after post decimation, %s=%d is too high! RGB=%dx%d, depth=%dx%d",
5629 Parameters::kMemImagePostDecimation().
c_str(), _imagePostDecimation,
5630 image.cols, image.rows, depthOrRightImage.cols, depthOrRightImage.rows);
5634 if(stats)
stats->addStatistic(Statistics::kTimingMemPost_decimation(), t*1000.0f);
5635 UDEBUG(
"time post-decimation = %fs", t);
5638 if(_stereoFromMotion &&
5640 cameraModels.size() == 1 &&
5642 (words3D.size() == 0 || (words.size() == words3D.size() && words3DValid!=(
int)words3D.size())) &&
5643 _registrationPipeline->isImageRequired() &&
5644 _signatures.size() &&
5645 _signatures.rbegin()->second->mapId() == _idMapCount)
5647 UDEBUG(
"Generate 3D words using odometry (%s=true and words3DValid=%d/%d)",
5648 Parameters::kMemStereoFromMotion().
c_str(), words3DValid, (
int)words3D.size());
5649 Signature * previousS = _signatures.rbegin()->second;
5650 if(previousS->getWords().size() > 8 && words.size() > 8 && !previousS->getPose().isNull())
5652 UDEBUG(
"Previous pose(%d) = %s", previousS->id(), previousS->getPose().prettyPrint().c_str());
5653 UDEBUG(
"Current pose(%d) = %s",
id, pose.prettyPrint().c_str());
5654 Transform cameraTransform = pose.inverse() * previousS->getPose();
5656 Signature cpPrevious(2);
5659 std::vector<cv::KeyPoint> uniqueWordsKpts;
5660 cv::Mat uniqueWordsDescriptors;
5661 std::multimap<int, int> uniqueWords;
5662 for(std::map<int, int>::iterator
iter=uniqueWordsOld.begin();
iter!=uniqueWordsOld.end(); ++
iter)
5664 uniqueWords.insert(std::make_pair(
iter->first, uniqueWords.size()));
5665 uniqueWordsKpts.push_back(previousS->getWordsKpts()[
iter->second]);
5666 uniqueWordsDescriptors.push_back(previousS->getWordsDescriptors().row(
iter->second));
5668 cpPrevious.sensorData().setCameraModels(previousS->sensorData().cameraModels());
5669 cpPrevious.setWords(uniqueWords, uniqueWordsKpts, std::vector<cv::Point3f>(), uniqueWordsDescriptors);
5670 Signature cpCurrent(1);
5672 uniqueWordsKpts.clear();
5673 uniqueWordsDescriptors = cv::Mat();
5674 uniqueWords.clear();
5675 for(std::map<int, int>::iterator
iter=uniqueWordsOld.begin();
iter!=uniqueWordsOld.end(); ++
iter)
5677 uniqueWords.insert(std::make_pair(
iter->first, uniqueWords.size()));
5678 uniqueWordsKpts.push_back(wordsKpts[
iter->second]);
5679 uniqueWordsDescriptors.push_back(wordsDescriptors.row(
iter->second));
5681 cpCurrent.sensorData().setCameraModels(cameraModels);
5683 cpCurrent.setWords(uniqueWords, uniqueWordsKpts, std::vector<cv::Point3f>(), uniqueWordsDescriptors);
5687 RegistrationVis reg(parameters_);
5688 if(_registrationPipeline->isScanRequired())
5691 RegistrationVis vis(parameters_);
5692 tmpt = vis.computeTransformationMod(cpCurrent, cpPrevious, cameraTransform);
5696 tmpt = _registrationPipeline->computeTransformationMod(cpCurrent, cpPrevious, cameraTransform);
5698 UDEBUG(
"t=%s", tmpt.prettyPrint().c_str());
5703 std::map<int, cv::KeyPoint> currentWords;
5704 std::map<int, cv::KeyPoint> previousWords;
5705 for(std::map<int, int>::iterator
iter=currentUniqueWords.begin();
iter!=currentUniqueWords.end(); ++
iter)
5707 currentWords.insert(std::make_pair(
iter->first, cpCurrent.getWordsKpts()[
iter->second]));
5709 for(std::map<int, int>::iterator
iter=previousUniqueWords.begin();
iter!=previousUniqueWords.end(); ++
iter)
5711 previousWords.insert(std::make_pair(
iter->first, cpPrevious.getWordsKpts()[
iter->second]));
5719 UDEBUG(
"inliers=%d", (
int)inliers.size());
5722 float bad_point = std::numeric_limits<float>::quiet_NaN ();
5723 UASSERT(words3D.size() == 0 || words.size() == words3D.size());
5724 bool words3DWasEmpty = words3D.empty();
5725 int added3DPointsWithoutDepth = 0;
5726 for(std::multimap<int, int>::const_iterator
iter=words.begin();
iter!=words.end(); ++
iter)
5728 std::map<int, cv::Point3f>::iterator jter=inliers.find(
iter->first);
5731 if(jter != inliers.end())
5733 words3D.push_back(jter->second);
5734 ++added3DPointsWithoutDepth;
5738 words3D.push_back(cv::Point3f(bad_point,bad_point,bad_point));
5741 else if(!util3d::isFinite(words3D[
iter->second]) && jter != inliers.end())
5743 words3D[
iter->second] = jter->second;
5744 ++added3DPointsWithoutDepth;
5747 UDEBUG(
"added3DPointsWithoutDepth=%d", added3DPointsWithoutDepth);
5748 if(stats)
stats->addStatistic(Statistics::kMemoryTriangulated_points(), (
float)added3DPointsWithoutDepth);
5751 UASSERT(words3D.size() == words.size());
5752 if(stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_3D_motion(), t*1000.0f);
5753 UDEBUG(
"time keypoints 3D by motion (%d) = %fs", (
int)words3D.size(), t);
5758 LaserScan laserScan =
data.laserScanRaw();
5759 if(!isIntermediateNode && laserScan.size())
5761 if(laserScan.rangeMax() == 0.0f)
5763 bool id2d = laserScan.is2d();
5764 float maxRange = 0.0f;
5765 for(
int i=0;
i<laserScan.size(); ++
i)
5767 const float * ptr = laserScan.data().ptr<
float>(0,
i);
5771 r = ptr[0]*ptr[0] + ptr[1]*ptr[1];
5775 r = ptr[0]*ptr[0] + ptr[1]*ptr[1] + ptr[2]*ptr[2];
5784 laserScan=LaserScan(laserScan.data(), laserScan.maxPoints(),
sqrt(maxRange), laserScan.format(), laserScan.localTransform());
5789 _laserScanDownsampleStepSize,
5792 _laserScanVoxelSize,
5794 _laserScanNormalRadius,
5795 _laserScanGroundNormalsUp);
5797 if(stats)
stats->addStatistic(Statistics::kTimingMemScan_filtering(), t*1000.0f);
5798 UDEBUG(
"time normals scan = %fs", t);
5802 if(this->isBinDataKept() && (!isIntermediateNode || _saveIntermediateNodeData))
5804 UDEBUG(
"Bin data kept: rgb=%d, depth=%d, scan=%d, userData=%d",
5806 depthOrRightImage.empty()?0:1,
5807 laserScan.isEmpty()?0:1,
5808 data.userDataRaw().empty()?0:1);
5810 std::vector<unsigned char> imageBytes;
5811 std::vector<unsigned char> depthBytes;
5813 if(!depthOrRightImage.empty() && depthOrRightImage.type() == CV_32FC1)
5815 if(_saveDepth16Format)
5817 static bool warned =
false;
5820 UWARN(
"Converting depth data to 16 bits format because depth type detected is 32FC1, "
5821 "feed 16UC1 depth format directly to avoid this conversion (or set parameter %s=false "
5822 "to save 32bits format). This warning is only printed once.",
5823 Parameters::kMemSaveDepth16Format().
c_str());
5828 else if(_depthCompressionFormat ==
".rvl")
5830 static bool warned =
false;
5833 UWARN(
"%s is set to false to use 32bits format but this is not "
5834 "compatible with the compressed depth format chosen (%s=\"%s\"), depth "
5835 "images will be compressed in \".png\" format instead. Explicitly "
5836 "set %s to true to keep using \"%s\" format and images will be "
5837 "converted to 16bits for convenience (warning: that would "
5838 "remove all depth values over 65 meters). Explicitly set %s=\".png\" "
5839 "to suppress this warning. This warning is only printed once.",
5840 Parameters::kMemSaveDepth16Format().
c_str(),
5841 Parameters::kMemDepthCompressionFormat().
c_str(),
5842 _depthCompressionFormat.c_str(),
5843 Parameters::kMemSaveDepth16Format().c_str(),
5844 _depthCompressionFormat.c_str(),
5845 Parameters::kMemDepthCompressionFormat().c_str());
5851 cv::Mat compressedImage;
5852 cv::Mat compressedDepth;
5853 cv::Mat compressedScan;
5854 cv::Mat compressedUserData;
5855 if(_compressionParallelized)
5858 rtabmap::CompressionThread ctDepth(depthOrRightImage, depthOrRightImage.type() == CV_32FC1 || depthOrRightImage.type() == CV_16UC1?_depthCompressionFormat:_rgbCompressionFormat);
5865 if(!depthOrRightImage.empty())
5869 if(!laserScan.isEmpty())
5871 ctLaserScan.start();
5873 if(!
data.userDataRaw().empty())
5882 compressedImage = ctImage.getCompressedData();
5883 compressedDepth = ctDepth.getCompressedData();
5884 compressedScan = ctLaserScan.getCompressedData();
5885 compressedUserData = ctUserData.getCompressedData();
5890 compressedDepth =
compressImage2(depthOrRightImage, depthOrRightImage.type() == CV_32FC1 || depthOrRightImage.type() == CV_16UC1?_depthCompressionFormat:_rgbCompressionFormat);
5895 s =
new Signature(
id,
5897 isIntermediateNode?-1:0,
5902 !stereoCameraModels.empty()?
5904 laserScan.angleIncrement() == 0.0f?
5905 LaserScan(compressedScan,
5906 laserScan.maxPoints(),
5907 laserScan.rangeMax(),
5909 laserScan.localTransform()):
5910 LaserScan(compressedScan,
5912 laserScan.rangeMin(),
5913 laserScan.rangeMax(),
5914 laserScan.angleMin(),
5915 laserScan.angleMax(),
5916 laserScan.angleIncrement(),
5917 laserScan.localTransform()),
5923 compressedUserData):
5925 laserScan.angleIncrement() == 0.0f?
5926 LaserScan(compressedScan,
5927 laserScan.maxPoints(),
5928 laserScan.rangeMax(),
5930 laserScan.localTransform()):
5931 LaserScan(compressedScan,
5933 laserScan.rangeMin(),
5934 laserScan.rangeMax(),
5935 laserScan.angleMin(),
5936 laserScan.angleMax(),
5937 laserScan.angleIncrement(),
5938 laserScan.localTransform()),
5944 compressedUserData));
5948 UDEBUG(
"Bin data kept: scan=%d, userData=%d",
5949 laserScan.isEmpty()?0:1,
5950 data.userDataRaw().empty()?0:1);
5953 cv::Mat compressedScan;
5954 cv::Mat compressedUserData;
5955 if(_compressionParallelized)
5959 if(!
data.userDataRaw().empty() && !isIntermediateNode)
5963 if(!laserScan.isEmpty() && !isIntermediateNode)
5965 ctLaserScan.start();
5970 compressedScan = ctLaserScan.getCompressedData();
5971 compressedUserData = ctUserData.getCompressedData();
5979 s =
new Signature(
id,
5981 isIntermediateNode?-1:0,
5986 !stereoCameraModels.empty()?
5988 laserScan.angleIncrement() == 0.0f?
5989 LaserScan(compressedScan,
5990 laserScan.maxPoints(),
5991 laserScan.rangeMax(),
5993 laserScan.localTransform()):
5994 LaserScan(compressedScan,
5996 laserScan.rangeMin(),
5997 laserScan.rangeMax(),
5998 laserScan.angleMin(),
5999 laserScan.angleMax(),
6000 laserScan.angleIncrement(),
6001 laserScan.localTransform()),
6007 compressedUserData):
6009 laserScan.angleIncrement() == 0.0f?
6010 LaserScan(compressedScan,
6011 laserScan.maxPoints(),
6012 laserScan.rangeMax(),
6014 laserScan.localTransform()):
6015 LaserScan(compressedScan,
6017 laserScan.rangeMin(),
6018 laserScan.rangeMax(),
6019 laserScan.angleMin(),
6020 laserScan.angleMax(),
6021 laserScan.angleIncrement(),
6022 laserScan.localTransform()),
6028 compressedUserData));
6031 s->setWords(words, wordsKpts,
6032 _reextractLoopClosureFeatures?std::vector<cv::Point3f>():words3D,
6033 _reextractLoopClosureFeatures?cv::Mat():wordsDescriptors);
6036 if(!cameraModels.empty())
6038 s->sensorData().setRGBDImage(image, depthOrRightImage, cameraModels,
false);
6042 s->sensorData().setStereoImage(image, depthOrRightImage, stereoCameraModels,
false);
6044 s->sensorData().setLaserScan(laserScan,
false);
6045 s->sensorData().setUserData(
data.userDataRaw(),
false);
6047 UDEBUG(
"data.groundTruth() =%s",
data.groundTruth().prettyPrint().c_str());
6048 UDEBUG(
"data.gps() =%s",
data.gps().stamp()?
"true":
"false");
6049 UDEBUG(
"data.envSensors() =%d", (
int)
data.envSensors().size());
6050 UDEBUG(
"data.globalDescriptors()=%d", (
int)
data.globalDescriptors().size());
6051 s->sensorData().setGroundTruth(
data.groundTruth());
6052 s->sensorData().setGPS(
data.gps());
6053 s->sensorData().setEnvSensors(
data.envSensors());
6055 if(!isIntermediateNode)
6057 std::vector<GlobalDescriptor> globalDescriptors =
data.globalDescriptors();
6058 if(_globalDescriptorExtractor)
6060 GlobalDescriptor gdescriptor = _globalDescriptorExtractor->extract(inputData);
6061 if(!gdescriptor.data().empty())
6063 globalDescriptors.push_back(gdescriptor);
6066 s->sensorData().setGlobalDescriptors(globalDescriptors);
6068 else if(!
data.globalDescriptors().empty())
6070 UDEBUG(
"Global descriptors provided (size=%ld) are ignored because this signature is set as intermediate.",
data.globalDescriptors().size());
6074 if(stats)
stats->addStatistic(Statistics::kTimingMemCompressing_data(), t*1000.0f);
6075 UDEBUG(
"time compressing data (id=%d) %fs",
id, t);
6078 s->setEnabled(
true);
6082 if(_createOccupancyGrid && !isIntermediateNode)
6084 if( (_localMapMaker->isGridFromDepth() && !
data.depthOrRightRaw().empty()) ||
6085 (!_localMapMaker->isGridFromDepth() && !
data.laserScanRaw().empty()))
6087 cv::Mat ground, obstacles,
empty;
6088 float cellSize = 0.0f;
6089 cv::Point3f viewPoint(0,0,0);
6090 _localMapMaker->createLocalMap(*s, ground, obstacles,
empty, viewPoint);
6091 cellSize = _localMapMaker->getCellSize();
6092 s->sensorData().setOccupancyGrid(ground, obstacles,
empty, cellSize, viewPoint);
6095 if(stats)
stats->addStatistic(Statistics::kTimingMemOccupancy_grid(), t*1000.0f);
6096 UDEBUG(
"time grid map = %fs", t);
6098 else if(
data.gridCellSize() != 0.0f)
6100 s->sensorData().setOccupancyGrid(
6101 data.gridGroundCellsRaw(),
6102 data.gridObstacleCellsRaw(),
6103 data.gridEmptyCellsRaw(),
6104 data.gridCellSize(),
6105 data.gridViewPoint());
6110 if(!
data.globalPose().isNull() &&
data.globalPoseCovariance().cols==6 &&
data.globalPoseCovariance().rows==6 &&
data.globalPoseCovariance().cols==CV_64FC1)
6112 s->addLink(Link(
s->id(),
s->id(), Link::kPosePrior,
data.globalPose(),
data.globalPoseCovariance().inv()));
6113 UDEBUG(
"Added global pose prior: %s",
data.globalPose().prettyPrint().c_str());
6115 if(
data.gps().stamp() > 0.0)
6117 UWARN(
"GPS constraint ignored as global pose is also set.");
6120 else if(
data.gps().stamp() > 0.0)
6127 data.gps().error() > 0.0)
6129 if(_gpsOrigin.stamp() <= 0.0)
6131 _gpsOrigin =
data.gps();
6132 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());
6134 cv::Point3f pt =
data.gps().toGeodeticCoords().toENU_WGS84(_gpsOrigin.toGeodeticCoords());
6135 Transform gpsPose(pt.x, pt.y, pose.z(), 0, 0, -(
data.gps().bearing()-90.0)*
M_PI/180.0);
6136 cv::Mat gpsInfMatrix = cv::Mat::eye(6,6,CV_64FC1)/9999.0;
6138 UDEBUG(
"Added GPS prior: x=%f y=%f z=%f yaw=%f", gpsPose.x(), gpsPose.y(), gpsPose.z(), gpsPose.theta());
6140 gpsInfMatrix.at<
double>(0,0) = gpsInfMatrix.at<
double>(1,1) = 1.0/
data.gps().error();
6141 gpsInfMatrix.at<
double>(2,2) = 1;
6142 s->addLink(Link(
s->id(),
s->id(), Link::kPosePrior, gpsPose, gpsInfMatrix));
6146 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());
6151 if(_useOdometryGravity && !pose.isNull())
6153 s->addLink(Link(
s->id(),
s->id(), Link::kGravity, pose.rotation()));
6154 UDEBUG(
"Added gravity constraint from odom pose: %s", pose.rotation().prettyPrint().c_str());
6156 else if(!
data.imu().localTransform().isNull() &&
6157 (
data.imu().orientation()[0] != 0 ||
6158 data.imu().orientation()[1] != 0 ||
6159 data.imu().orientation()[2] != 0 ||
6160 data.imu().orientation()[3] != 0))
6163 Transform
orientation(0,0,0,
data.imu().orientation()[0],
data.imu().orientation()[1],
data.imu().orientation()[2],
data.imu().orientation()[3]);
6172 for(Landmarks::const_iterator
iter = landmarks.begin();
iter!=landmarks.end(); ++
iter)
6174 if(
iter->second.id() > 0)
6176 int landmarkId = -
iter->first;
6177 cv::Mat landmarkSize;
6178 if(
iter->second.size() > 0.0f)
6180 landmarkSize = cv::Mat(1,1,CV_32FC1);
6181 landmarkSize.at<
float>(0,0) =
iter->second.size();
6183 std::pair<std::map<int, float>::iterator,
bool> inserted=_landmarksSize.insert(std::make_pair(
iter->first,
iter->second.size()));
6184 if(!inserted.second)
6186 if(inserted.first->second != landmarkSize.at<
float>(0,0))
6188 UWARN(
"Trying to update landmark size buffer for landmark %d with size=%f but "
6189 "it has already a different size set. Keeping old size (%f).",
6190 -landmarkId, inserted.first->second, landmarkSize.at<
float>(0,0));
6196 Transform landmarkPose =
iter->second.pose();
6197 if(_registrationPipeline->force3DoF())
6202 if(
fabs(tx.
z()) > 0.9)
6206 else if(
fabs(ty.
z()) > 0.9)
6212 Link landmark(
s->id(), landmarkId, Link::kLandmark, landmarkPose,
iter->second.covariance().inv(), landmarkSize);
6213 s->addLandmark(landmark);
6216 std::map<int, std::set<int> >
::iterator nter = _landmarksIndex.find(landmarkId);
6217 if(nter!=_landmarksIndex.end())
6219 nter->second.insert(
s->id());
6224 tmp.insert(
s->id());
6225 _landmarksIndex.insert(std::make_pair(landmarkId, tmp));
6230 UERROR(
"Invalid landmark received! IDs should be > 0 (it is %d). Ignoring this landmark.",
iter->second.id());
6237 void Memory::disableWordsRef(
int signatureId)
6239 UDEBUG(
"id=%d", signatureId);
6241 Signature * ss = this->_getSignature(signatureId);
6244 const std::multimap<int, int> & words = ss->
getWords();
6246 int count = _vwd->getTotalActiveReferences();
6248 for(std::list<int>::const_iterator
i=
keys.begin();
i!=
keys.end(); ++
i)
6250 _vwd->removeAllWordRef(*
i, signatureId);
6253 count -= _vwd->getTotalActiveReferences();
6255 UDEBUG(
"%d words total ref removed from signature %d... (total active ref = %d)",
count, ss->
id(), _vwd->getTotalActiveReferences());
6259 void Memory::cleanUnusedWords()
6261 std::vector<VisualWord*> removedWords = _vwd->getUnusedWords();
6262 UDEBUG(
"Removing %d words (dictionary size=%d)...", removedWords.size(), _vwd->getVisualWords().size());
6263 if(removedWords.size())
6266 _vwd->removeWords(removedWords);
6268 for(
unsigned int i=0;
i<removedWords.size(); ++
i)
6272 _dbDriver->asyncSave(removedWords[
i]);
6276 delete removedWords[
i];
6282 void Memory::enableWordsRef(
const std::list<int> & signatureIds)
6284 UDEBUG(
"size=%d", signatureIds.size());
6288 std::map<int, int> refsToChange;
6290 std::set<int> oldWordIds;
6291 std::list<Signature *> surfSigns;
6292 for(std::list<int>::const_iterator
i=signatureIds.begin();
i!=signatureIds.end(); ++
i)
6297 surfSigns.push_back(ss);
6301 for(std::list<int>::const_iterator k=uniqueKeys.begin(); k!=uniqueKeys.end(); ++k)
6303 if(*k>0 && _vwd->getWord(*k) == 0 && _vwd->getUnusedWord(*k) == 0)
6305 oldWordIds.insert(oldWordIds.end(), *k);
6311 if(!_vwd->isIncremental() && oldWordIds.size())
6313 UWARN(
"Dictionary is fixed, but some words retrieved have not been found!?");
6316 UDEBUG(
"oldWordIds.size()=%d, getOldIds time=%fs", oldWordIds.size(),
timer.ticks());
6319 std::list<VisualWord *> vws;
6320 if(oldWordIds.size() && _dbDriver)
6323 _dbDriver->loadWords(oldWordIds, vws);
6325 UDEBUG(
"loading words(%d) time=%fs", oldWordIds.size(),
timer.ticks());
6331 std::vector<int> vwActiveIds = _vwd->findNN(vws);
6332 UDEBUG(
"find active ids (number=%d) time=%fs", vws.size(),
timer.ticks());
6334 for(std::list<VisualWord *>::iterator iterVws=vws.begin(); iterVws!=vws.end(); ++iterVws)
6336 if(vwActiveIds[
i] > 0)
6339 refsToChange.insert(refsToChange.end(), std::pair<int, int>((*iterVws)->id(), vwActiveIds[
i]));
6340 if((*iterVws)->isSaved())
6346 _dbDriver->asyncSave(*iterVws);
6352 _vwd->addWord(*iterVws);
6356 UDEBUG(
"Added %d to dictionary, time=%fs", vws.size()-refsToChange.size(),
timer.ticks());
6359 for(std::map<int, int>::const_iterator
iter=refsToChange.begin();
iter != refsToChange.end(); ++
iter)
6362 for(std::list<Signature *>::iterator
j=surfSigns.begin();
j!=surfSigns.end(); ++
j)
6364 (*j)->changeWordsRef(
iter->first,
iter->second);
6367 UDEBUG(
"changing ref, total=%d, time=%fs", refsToChange.size(),
timer.ticks());
6370 int count = _vwd->getTotalActiveReferences();
6373 for(std::list<Signature *>::iterator
j=surfSigns.begin();
j!=surfSigns.end(); ++
j)
6375 const std::vector<int> &
keys =
uKeys((*j)->getWords());
6379 for(
unsigned int i=0;
i<
keys.size(); ++
i)
6383 _vwd->addWordRef(
keys.at(
i), (*j)->id());
6386 (*j)->setEnabled(
true);
6390 count = _vwd->getTotalActiveReferences() -
count;
6391 UDEBUG(
"%d words total ref added from %d signatures, time=%fs...",
count, surfSigns.size(),
timer.ticks());
6394 std::set<int> Memory::reactivateSignatures(
const std::list<int> & ids,
unsigned int maxLoaded,
double & timeDbAccess)
6402 std::list<int> idsToLoad;
6403 std::map<int, int>::iterator wmIter;
6404 for(std::list<int>::const_iterator
i=ids.begin();
i!=ids.end(); ++
i)
6406 if(!this->getSignature(*
i) && !
uContains(idsToLoad, *
i))
6408 if(!maxLoaded || idsToLoad.size() < maxLoaded)
6410 idsToLoad.push_back(*
i);
6411 UINFO(
"Loading location %d from database...", *
i);
6416 UDEBUG(
"idsToLoad = %d", idsToLoad.size());
6418 std::list<Signature *> reactivatedSigns;
6421 _dbDriver->loadSignatures(idsToLoad, reactivatedSigns);
6423 timeDbAccess =
timer.getElapsedTime();
6424 std::list<int> idsLoaded;
6425 for(std::list<Signature *>::iterator
i=reactivatedSigns.begin();
i!=reactivatedSigns.end(); ++
i)
6427 if(!(*i)->getLandmarks().empty())
6430 for(std::map<int, Link>::const_iterator
iter = (*i)->getLandmarks().begin();
iter!=(*i)->getLandmarks().end(); ++
iter)
6432 int landmarkId =
iter->first;
6435 cv::Mat landmarkSize =
iter->second.uncompressUserDataConst();
6436 if(!landmarkSize.empty() && landmarkSize.type() == CV_32FC1 && landmarkSize.total()==1)
6438 std::pair<std::map<int, float>::iterator,
bool> inserted=_landmarksSize.insert(std::make_pair(-landmarkId, landmarkSize.at<
float>(0,0)));
6439 if(!inserted.second)
6441 if(inserted.first->second != landmarkSize.at<
float>(0,0))
6443 UWARN(
"Trying to update landmark size buffer for landmark %d with size=%f but "
6444 "it has already a different size set. Keeping old size (%f).",
6445 -landmarkId, inserted.first->second, landmarkSize.at<
float>(0,0));
6450 std::map<int, std::set<int> >
::iterator nter = _landmarksIndex.find(landmarkId);
6451 if(nter!=_landmarksIndex.end())
6453 nter->second.insert((*i)->id());
6458 tmp.insert((*i)->id());
6459 _landmarksIndex.insert(std::make_pair(landmarkId, tmp));
6464 idsLoaded.push_back((*i)->id());
6466 this->addSignatureToWmFromLTM(*
i);
6468 this->enableWordsRef(idsLoaded);
6470 return std::set<int>(idsToLoad.begin(), idsToLoad.end());
6475 void Memory::getMetricConstraints(
6476 const std::set<int> & ids,
6477 std::map<int, Transform> & poses,
6478 std::multimap<int, Link> & links,
6479 bool lookInDatabase,
6480 bool landmarksAdded)
6483 for(std::set<int>::const_iterator
iter=ids.begin();
iter!=ids.end(); ++
iter)
6488 poses.insert(std::make_pair(*
iter, pose));
6492 for(std::set<int>::const_iterator
iter=ids.begin();
iter!=ids.end(); ++
iter)
6496 std::multimap<int, Link> tmpLinks = getLinks(*
iter, lookInDatabase,
true);
6497 for(std::multimap<int, Link>::iterator jter=tmpLinks.begin(); jter!=tmpLinks.end(); ++jter)
6499 std::multimap<int, Link>::iterator addedLinksIterator =
graph::findLink(links, *
iter, jter->first);
6500 if( jter->second.isValid() &&
6501 (addedLinksIterator == links.end() || addedLinksIterator->second.from()==addedLinksIterator->second.to()) &&
6502 (
uContains(poses, jter->first) || (landmarksAdded && jter->second.type() == Link::kLandmark)))
6504 if(!lookInDatabase &&
6505 (jter->second.type() == Link::kNeighbor ||
6506 jter->second.type() == Link::kNeighborMerged))
6508 const Signature *
s = this->getSignature(jter->first);
6510 if(
s->getWeight() == -1)
6512 Link link = jter->second;
6513 while(
s &&
s->getWeight() == -1)
6517 std::multimap<int, Link>
n = this->getNeighborLinks(
s->id(),
false);
6519 std::multimap<int, Link>::iterator uter =
n.upper_bound(
s->id());
6522 const Signature * s2 = this->getSignature(uter->first);
6525 link = link.
merge(uter->second, uter->second.type());
6526 poses.erase(
s->id());
6536 links.insert(std::make_pair(*
iter, link));
6540 links.insert(std::make_pair(*
iter, jter->second));
6543 else if(jter->second.type() != Link::kLandmark)
6545 links.insert(std::make_pair(*
iter, jter->second));
6547 else if(landmarksAdded)
6551 poses.insert(std::make_pair(jter->first, poses.at(*
iter) * jter->second.transform()));
6553 links.insert(std::make_pair(jter->first, jter->second.inverse()));