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 _incrementalMemory(
Parameters::defaultMemIncrementalMemory()),
84 _localizationDataSaved(
Parameters::defaultMemLocalizationDataSaved()),
85 _reduceGraph(
Parameters::defaultMemReduceGraph()),
86 _maxStMemSize(
Parameters::defaultMemSTMSize()),
87 _recentWmRatio(
Parameters::defaultMemRecentWmRatio()),
88 _transferSortingByWeightId(
Parameters::defaultMemTransferSortingByWeightId()),
89 _idUpdatedToNewOneRehearsal(
Parameters::defaultMemRehearsalIdUpdatedToNewOne()),
90 _generateIds(
Parameters::defaultMemGenerateIds()),
91 _badSignaturesIgnored(
Parameters::defaultMemBadSignaturesIgnored()),
92 _mapLabelsAdded(
Parameters::defaultMemMapLabelsAdded()),
93 _depthAsMask(
Parameters::defaultMemDepthAsMask()),
94 _stereoFromMotion(
Parameters::defaultMemStereoFromMotion()),
95 _imagePreDecimation(
Parameters::defaultMemImagePreDecimation()),
96 _imagePostDecimation(
Parameters::defaultMemImagePostDecimation()),
97 _compressionParallelized(
Parameters::defaultMemCompressionParallelized()),
98 _laserScanDownsampleStepSize(
Parameters::defaultMemLaserScanDownsampleStepSize()),
99 _laserScanVoxelSize(
Parameters::defaultMemLaserScanVoxelSize()),
100 _laserScanNormalK(
Parameters::defaultMemLaserScanNormalK()),
101 _laserScanNormalRadius(
Parameters::defaultMemLaserScanNormalRadius()),
102 _laserScanGroundNormalsUp(
Parameters::defaultIcpPointToPlaneGroundNormalsUp()),
103 _reextractLoopClosureFeatures(
Parameters::defaultRGBDLoopClosureReextractFeatures()),
104 _localBundleOnLoopClosure(
Parameters::defaultRGBDLocalBundleOnLoopClosure()),
105 _invertedReg(
Parameters::defaultRGBDInvertedReg()),
106 _rehearsalMaxDistance(
Parameters::defaultRGBDLinearUpdate()),
107 _rehearsalMaxAngle(
Parameters::defaultRGBDAngularUpdate()),
108 _rehearsalWeightIgnoredWhileMoving(
Parameters::defaultMemRehearsalWeightIgnoredWhileMoving()),
109 _useOdometryFeatures(
Parameters::defaultMemUseOdomFeatures()),
110 _useOdometryGravity(
Parameters::defaultMemUseOdomGravity()),
111 _rotateImagesUpsideUp(
Parameters::defaultMemRotateImagesUpsideUp()),
112 _createOccupancyGrid(
Parameters::defaultRGBDCreateOccupancyGrid()),
113 _visMaxFeatures(
Parameters::defaultVisMaxFeatures()),
115 _imagesAlreadyRectified(
Parameters::defaultRtabmapImagesAlreadyRectified()),
116 _rectifyOnlyFeatures(
Parameters::defaultRtabmapRectifyOnlyFeatures()),
117 _covOffDiagonalIgnored(
Parameters::defaultMemCovOffDiagIgnored()),
118 _detectMarkers(
Parameters::defaultRGBDMarkerDetection()),
119 _markerLinVariance(
Parameters::defaultMarkerVarianceLinear()),
120 _markerAngVariance(
Parameters::defaultMarkerVarianceAngular()),
122 _idMapCount(kIdStart),
124 _lastGlobalLoopClosureId(0),
125 _memoryChanged(
false),
126 _linksChanged(
false),
129 _badSignRatio(
Parameters::defaultKpBadSignRatio()),
130 _tfIdfLikelihoodUsed(
Parameters::defaultKpTfIdfLikelihoodUsed()),
131 _parallelized(
Parameters::defaultKpParallelized()),
148 float corRatio = Parameters::defaultIcpCorrespondenceRatio();
154 UWARN(
"%s is >=0.5, which sets correspondence ratio for proximity detection using "
155 "laser scans to 100% (2 x Ratio). You may lower the ratio to accept proximity "
156 "detection with not full scans overlapping.", Parameters::kIcpCorrespondenceRatio().
c_str());
234 bool loadAllNodesInWM = Parameters::defaultMemInitWMWithAllNodes();
238 std::list<Signature*> dbSignatures;
253 for(std::list<Signature*>::reverse_iterator
iter=dbSignatures.rbegin();
iter!=dbSignatures.rend(); ++
iter)
265 if(!(*iter)->getGroundTruthPose().isNull()) {
266 _groundTruths.insert(std::make_pair((*iter)->id(), (*iter)->getGroundTruthPose()));
269 if(!(*iter)->getLandmarks().empty())
272 for(std::map<int, Link>::const_iterator jter = (*iter)->getLandmarks().begin(); jter!=(*iter)->getLandmarks().end(); ++jter)
274 int landmarkId = jter->first;
277 cv::Mat landmarkSize = jter->second.uncompressUserDataConst();
278 if(!landmarkSize.empty() && landmarkSize.type() == CV_32FC1 && landmarkSize.total()==1)
280 std::pair<std::map<int, float>::iterator,
bool> inserted=
_landmarksSize.insert(std::make_pair(-landmarkId, landmarkSize.at<
float>(0,0)));
283 if(inserted.first->second != landmarkSize.at<
float>(0,0))
285 UWARN(
"Trying to update landmark size buffer for landmark %d with size=%f but "
286 "it has already a different size set. Keeping old size (%f).",
287 -landmarkId, inserted.first->second, landmarkSize.at<
float>(0,0));
292 UDEBUG(
"Caching landmark size %f for %d", landmarkSize.at<
float>(0,0), -landmarkId);
299 nter->second.insert((*iter)->id());
304 tmp.insert((*iter)->id());
320 UDEBUG(
"Check if all nodes are in Working Memory");
323 for(std::map<int, Link>::const_iterator jter =
iter->second->getLinks().begin(); jter!=
iter->second->getLinks().end(); ++jter)
334 UDEBUG(
"update odomMaxInf vector");
335 std::multimap<int, Link> links = this->
getAllLinks(
true,
true);
336 for(std::multimap<int, Link>::iterator
iter=links.begin();
iter!=links.end(); ++
iter)
339 iter->second.infMatrix().cols == 6 &&
340 iter->second.infMatrix().rows == 6)
346 for(
int i=0;
i<6; ++
i)
348 const double &
v =
iter->second.infMatrix().at<
double>(
i,
i);
356 UDEBUG(
"update odomMaxInf vector, done!");
378 UDEBUG(
"Loading dictionary...");
381 UDEBUG(
"load all referenced words in working memory");
383 std::set<int> wordIds;
384 const std::map<int, Signature *> & signatures = this->
getSignatures();
385 for(std::map<int, Signature *>::const_iterator
i=signatures.begin();
i!=signatures.end(); ++
i)
387 const std::multimap<int, int> & words =
i->second->getWords();
393 wordIds.insert(*
iter);
398 UDEBUG(
"load words %d", (
int)wordIds.size());
403 std::list<VisualWord*> words;
405 for(std::list<VisualWord*>::iterator
iter = words.begin();
iter!=words.end(); ++
iter)
432 const std::map<int, Signature *> & signatures = this->
getSignatures();
433 for(std::map<int, Signature *>::const_iterator
i=signatures.begin();
i!=signatures.end(); ++
i)
438 const std::multimap<int, int> & words =
s->getWords();
441 UDEBUG(
"node=%d, word references=%d",
s->id(), words.size());
442 for(std::multimap<int, int>::const_iterator
iter = words.begin();
iter!=words.end(); ++
iter)
465 parameters.erase(Parameters::kRtabmapWorkingDirectory());
482 void Memory::close(
bool databaseSaved,
bool postInitClosingEvents,
const std::string & ouputDatabasePath)
484 UINFO(
"databaseSaved=%d, postInitClosingEvents=%d", databaseSaved?1:0, postInitClosingEvents?1:0);
487 bool databaseNameChanged =
false;
497 UINFO(
"No changes added to database.");
512 UINFO(
"Saving memory...");
545 UWARN(
"Please call Memory::close() before");
561 ParametersMap::const_iterator
iter;
593 UWARN(
"%s and %s cannot be used at the same time, disabling %s...",
594 Parameters::kRGBDLocalBundleOnLoopClosure().
c_str(),
595 Parameters::kRGBDInvertedReg().
c_str(),
596 Parameters::kRGBDLocalBundleOnLoopClosure().
c_str());
656 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));
660 UINFO(
"new detector strategy %d.",
int(detectorStrategy));
702 UDEBUG(
"new registration strategy %d",
int(regStrategy));
740 float corRatio = Parameters::defaultIcpCorrespondenceRatio();
746 UWARN(
"%s is >=0.5, which sets correspondence ratio for proximity detection using "
747 "laser scans to 100% (2 x Ratio). You may lower the ratio to accept proximity "
748 "detection with not full scans overlapping.", Parameters::kIcpCorrespondenceRatio().
c_str());
768 int globalDescriptorStrategy = -1;
770 if(globalDescriptorStrategy != -1 &&
786 iter =
params.find(Parameters::kMemIncrementalMemory());
799 UWARN(
"Switching from Mapping to Localization mode, the database will be saved and reloaded.");
806 UWARN(
"Switching from Mapping to Localization mode, the database is reloaded!");
814 int visFeatureType = Parameters::defaultVisFeatureType();
815 int kpDetectorStrategy = Parameters::defaultKpDetectorStrategy();
818 if(visFeatureType != kpDetectorStrategy)
820 UWARN(
"%s is enabled, but %s and %s parameters are not the same! Disabling %s...",
821 Parameters::kMemUseOdomFeatures().
c_str(),
822 Parameters::kVisFeatureType().
c_str(),
823 Parameters::kKpDetectorStrategy().
c_str(),
824 Parameters::kMemUseOdomFeatures().
c_str());
855 const cv::Mat & covariance,
856 const std::vector<float> & velocity,
868 UDEBUG(
"pre-updating...");
870 t=
timer.ticks()*1000;
871 if(
stats)
stats->addStatistic(Statistics::kTimingMemPre_update(),
t);
872 UDEBUG(
"time preUpdate=%f ms",
t);
880 UERROR(
"Failed to create a signature...");
889 if(
stats)
stats->addStatistic(Statistics::kTimingMemSignature_creation(),
t);
890 UDEBUG(
"time creating signature=%f ms",
t);
910 if(
stats)
stats->addStatistic(Statistics::kTimingMemRehearsal(),
t);
911 UDEBUG(
"time rehearsal=%f ms",
t);
917 UWARN(
"The working memory is empty and the memory is not "
918 "incremental (Mem/IncrementalMemory=False), no loop closure "
919 "can be detected! Please set Mem/IncrementalMemory=true to increase "
920 "the memory with new images or decrease the STM size (which is %d "
921 "including the new one added).", (
int)
_stMem.size());
928 int notIntermediateNodesCount = 0;
933 if(
s->getWeight() >= 0)
935 ++notIntermediateNodesCount;
938 std::map<int, int> reducedIds;
944 if(
s->getWeight() >= 0)
946 --notIntermediateNodesCount;
954 reducedIds.insert(std::make_pair(
id, reducedTo));
985 UASSERT(covariance.cols == 6 && covariance.rows == 6 && covariance.type() == CV_64FC1);
986 double maxAngVar = 0.0;
989 maxAngVar = covariance.at<
double>(5,5);
993 maxAngVar =
uMax3(covariance.at<
double>(3,3), covariance.at<
double>(4,4), covariance.at<
double>(5,5));
996 if(maxAngVar != 1.0 && maxAngVar > 0.1)
998 static bool warned =
false;
1001 UWARN(
"Very large angular variance (%f) detected! Please fix odometry "
1002 "covariance, otherwise poor graph optimizations are "
1003 "expected and wrong loop closure detections creating a lot "
1004 "of errors in the map could be accepted. This message is only "
1005 "printed once.", maxAngVar);
1013 infMatrix = cv::Mat::zeros(6,6,CV_64FC1);
1014 infMatrix.at<
double>(0,0) = 1.0 / covariance.at<
double>(0,0);
1015 infMatrix.at<
double>(1,1) = 1.0 / covariance.at<
double>(1,1);
1016 infMatrix.at<
double>(2,2) = 1.0 / covariance.at<
double>(2,2);
1017 infMatrix.at<
double>(3,3) = 1.0 / covariance.at<
double>(3,3);
1018 infMatrix.at<
double>(4,4) = 1.0 / covariance.at<
double>(4,4);
1019 infMatrix.at<
double>(5,5) = 1.0 / covariance.at<
double>(5,5);
1023 infMatrix = covariance.inv();
1025 if((
uIsFinite(covariance.at<
double>(0,0)) && covariance.at<
double>(0,0)>0.0) &&
1026 !(
uIsFinite(infMatrix.at<
double>(0,0)) && infMatrix.at<
double>(0,0)>0.0))
1028 UERROR(
"Failed to invert the covariance matrix! Covariance matrix should be invertible!");
1029 std::cout <<
"Covariance: " << covariance << std::endl;
1030 infMatrix = cv::Mat::eye(6,6,CV_64FC1);
1033 UASSERT(infMatrix.rows == 6 && infMatrix.cols == 6);
1038 for(
int i=0;
i<6; ++
i)
1040 const double &
v = infMatrix.at<
double>(
i,
i);
1060 UDEBUG(
"Ignoring neighbor link between %d and %d because they are not in the same map! (%d vs %d)",
1067 std::string tag =
uFormat(
"map%d", signature->
mapId());
1070 UINFO(
"Tagging node %d with label \"%s\"", signature->
id(), tag.c_str());
1072 _labels.insert(std::make_pair(signature->
id(), tag));
1080 std::string tag =
uFormat(
"map%d", signature->
mapId());
1083 UINFO(
"Tagging node %d with label \"%s\"", signature->
id(), tag.c_str());
1085 _labels.insert(std::make_pair(signature->
id(), tag));
1098 UDEBUG(
"%d words ref for the signature %d (weight=%d)", signature->
getWords().size(), signature->
id(), signature->
getWeight());
1113 UDEBUG(
"Inserting node %d in WM...", signature->
id());
1115 _signatures.insert(std::pair<int, Signature*>(signature->
id(), signature));
1123 UERROR(
"Signature is null ?!?");
1129 UDEBUG(
"Inserting node %d from STM in WM...",
id);
1137 const std::multimap<int, Link> & links =
s->getLinks();
1138 std::map<int, Link> neighbors;
1139 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
1143 merge =
iter->second.to() <
s->id() &&
1144 iter->second.to() !=
iter->second.from() &&
1147 iter->second.userDataCompressed().empty() &&
1152 UDEBUG(
"Reduce %d to %d",
s->id(),
iter->second.to());
1155 *reducedTo =
iter->second.to();
1162 neighbors.insert(*
iter);
1167 if(
s->getLabel().empty())
1169 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
1172 if(sTo->
id()!=
s->id())
1181 for(std::map<int, Link>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
1183 if(!sTo->
hasLink(jter->second.to()))
1185 UDEBUG(
"Merging link %d->%d (type=%d) to link %d->%d (type %d)",
1186 iter->second.from(),
iter->second.to(),
iter->second.type(),
1187 jter->second.from(), jter->second.to(), jter->second.type());
1188 Link l =
iter->second.inverse().merge(
1203 std::multimap<int, Link> linksCopy = links;
1204 for(std::multimap<int, Link>::iterator
iter=linksCopy.begin();
iter!=linksCopy.end(); ++
iter)
1209 s->removeLink(
iter->first);
1253 bool lookInDatabase)
const
1255 std::multimap<int, Link> links;
1259 const std::multimap<int, Link> & allLinks =
s->getLinks();
1260 for(std::multimap<int, Link>::const_iterator
iter = allLinks.begin();
iter!=allLinks.end(); ++
iter)
1265 links.insert(*
iter);
1272 for(std::multimap<int, Link>::iterator
iter=links.begin();
iter!=links.end();)
1277 links.erase(
iter++);
1287 UWARN(
"Cannot find signature %d in memory", signatureId);
1294 bool lookInDatabase)
const
1297 std::multimap<int, Link> loopClosures;
1300 const std::multimap<int, Link> & allLinks =
s->getLinks();
1301 for(std::multimap<int, Link>::const_iterator
iter = allLinks.begin();
iter!=allLinks.end(); ++
iter)
1305 iter->second.from() !=
iter->second.to() &&
1308 loopClosures.insert(*
iter);
1315 for(std::multimap<int, Link>::iterator
iter=loopClosures.begin();
iter!=loopClosures.end();)
1321 loopClosures.erase(
iter++);
1329 return loopClosures;
1334 bool lookInDatabase,
1335 bool withLandmarks)
const
1337 std::multimap<int, Link> links;
1343 links =
s->getLinks();
1346 links.insert(
s->getLandmarks().begin(),
s->getLandmarks().end());
1355 UWARN(
"Cannot find signature %d in memory", signatureId);
1358 else if(signatureId < 0)
1360 int landmarkId = signatureId;
1364 for(std::set<int>::const_iterator jter=
iter->second.begin(); jter!=
iter->second.end(); ++jter)
1369 std::map<int, Link>::const_iterator kter =
s->getLandmarks().find(landmarkId);
1370 if(kter !=
s->getLandmarks().end())
1373 links.insert(std::make_pair(
s->id(), kter->second.inverse()));
1380 std::map<int, Link>
nodes;
1382 for(std::map<int, Link>::iterator kter=
nodes.begin(); kter!=
nodes.end(); ++kter)
1384 links.insert(std::make_pair(kter->first, kter->second.inverse()));
1391 std::multimap<int, Link>
Memory::getAllLinks(
bool lookInDatabase,
bool ignoreNullLinks,
bool withLandmarks)
const
1393 std::multimap<int, Link> links;
1402 links.erase(
iter->first);
1403 for(std::map<int, Link>::const_iterator jter=
iter->second->getLinks().begin();
1404 jter!=
iter->second->getLinks().end();
1407 if(!ignoreNullLinks || jter->second.isValid())
1409 links.insert(std::make_pair(
iter->first, jter->second));
1414 for(std::map<int, Link>::const_iterator jter=
iter->second->getLandmarks().begin();
1415 jter!=
iter->second->getLandmarks().end();
1418 if(!ignoreNullLinks || jter->second.isValid())
1420 links.insert(std::make_pair(
iter->first, jter->second));
1436 int maxCheckedInDatabase,
1437 bool incrementMarginOnLoop,
1439 bool ignoreIntermediateNodes,
1440 bool ignoreLocalSpaceLoopIds,
1441 const std::set<int> & nodesSet,
1442 double * dbAccessTime
1454 std::map<int, int> ids;
1459 int nbLoadedFromDb = 0;
1460 std::list<int> curentMarginList;
1461 std::set<int> currentMargin;
1462 std::set<int> nextMargin;
1463 nextMargin.insert(signatureId);
1465 std::set<int> ignoredIds;
1466 while((maxGraphDepth == 0 ||
m < maxGraphDepth) && nextMargin.size())
1469 curentMarginList = std::list<int>(nextMargin.rbegin(), nextMargin.rend());
1472 for(std::list<int>::iterator jter = curentMarginList.begin(); jter!=curentMarginList.end(); ++jter)
1474 if(ids.find(*jter) == ids.end() && (nodesSet.empty() || nodesSet.find(*jter) != nodesSet.end()))
1479 std::multimap<int, Link> tmpLinks;
1480 std::map<int, Link> tmpLandmarks;
1481 const std::multimap<int, Link> * links = &tmpLinks;
1482 const std::map<int, Link> * landmarks = &tmpLandmarks;
1485 if(!ignoreIntermediateNodes ||
s->getWeight() != -1)
1487 ids.insert(std::pair<int, int>(*jter,
m));
1491 ignoredIds.insert(*jter);
1494 links = &
s->getLinks();
1497 landmarks = &
s->getLandmarks();
1500 else if(maxCheckedInDatabase == -1 || (maxCheckedInDatabase > 0 &&
_dbDriver && nbLoadedFromDb < maxCheckedInDatabase))
1503 ids.insert(std::pair<int, int>(*jter,
m));
1507 if(tmpLinks.empty())
1509 UWARN(
"No links loaded for %d?!", *jter);
1513 for(std::multimap<int, Link>::iterator kter=tmpLinks.begin(); kter!=tmpLinks.end();)
1517 tmpLandmarks.insert(*kter);
1518 tmpLinks.erase(kter++);
1520 else if(kter->second.from() == kter->second.to())
1523 tmpLinks.erase(kter++);
1533 *dbAccessTime +=
timer.getElapsedTime();
1538 for(std::multimap<int, Link>::const_iterator
iter=links->begin();
iter!=links->end(); ++
iter)
1541 ignoredIds.find(
iter->first) == ignoredIds.end())
1547 if(ignoreIntermediateNodes &&
s->getWeight()==-1)
1550 if(currentMargin.insert(
iter->first).second)
1552 curentMarginList.push_back(
iter->first);
1557 nextMargin.insert(
iter->first);
1562 if(incrementMarginOnLoop)
1564 nextMargin.insert(
iter->first);
1568 if(currentMargin.insert(
iter->first).second)
1570 curentMarginList.push_back(
iter->first);
1578 for(std::map<int, Link>::const_iterator
iter=landmarks->begin();
iter!=landmarks->end(); ++
iter)
1580 const std::map<int, std::set<int> >::const_iterator kter =
_landmarksIndex.find(
iter->first);
1583 for(std::set<int>::const_iterator nter=kter->second.begin(); nter!=kter->second.end(); ++nter)
1585 if( !
uContains(ids, *nter) && ignoredIds.find(*nter) == ignoredIds.end())
1587 if(incrementMarginOnLoop)
1589 nextMargin.insert(*nter);
1593 if(currentMargin.insert(*nter).second)
1595 curentMarginList.push_back(*nter);
1613 const std::map<int, Transform> & optimizedPoses,
1620 std::map<int, float> ids;
1621 std::map<int, float> checkedIds;
1622 std::list<int> curentMarginList;
1623 std::set<int> currentMargin;
1624 std::set<int> nextMargin;
1625 nextMargin.insert(signatureId);
1627 Transform referential = optimizedPoses.at(signatureId);
1629 float radiusSqrd = radius*radius;
1630 while((maxGraphDepth == 0 ||
m < maxGraphDepth) && nextMargin.size())
1632 curentMarginList = std::list<int>(nextMargin.begin(), nextMargin.end());
1635 for(std::list<int>::iterator jter = curentMarginList.begin(); jter!=curentMarginList.end(); ++jter)
1637 if(checkedIds.find(*jter) == checkedIds.end())
1644 const Transform &
t = optimizedPoses.at(*jter);
1647 if(radiusSqrd == 0 || distanceSqrd<radiusSqrd)
1649 ids.insert(std::pair<int, float>(*jter,distanceSqrd));
1653 for(std::multimap<int, Link>::const_iterator
iter=
s->getLinks().begin();
iter!=
s->getLinks().end(); ++
iter)
1659 nextMargin.insert(
iter->first);
1685 int id = *
_stMem.begin();
1687 if(reducedIds && reducedId > 0)
1689 reducedIds->insert(std::make_pair(
id, reducedId));
1720 std::string
version =
"0.0.0";
1730 std::string
url =
"";
1752 ids.insert(
iter->first);
1797 uFormat(
"The number of signatures don't match! _workingMem=%d, _stMem=%d, _signatures=%d",
1800 UDEBUG(
"Adding statistics after run...");
1805 parameters.erase(Parameters::kRtabmapWorkingDirectory());
1819 for(std::map<int, Signature *>::iterator
i=mem.begin();
i!=mem.end(); ++
i)
1823 UDEBUG(
"deleting from the working and the short-term memory: %d",
i->first);
1890 std::map<int, float> likelihood;
1897 else if(ids.empty())
1899 UWARN(
"ids list is empty");
1903 for(std::list<int>::const_iterator
iter = ids.begin();
iter!=ids.end(); ++
iter)
1911 UFATAL(
"Signature %d not found in WM ?!?", *
iter);
1916 likelihood.insert(likelihood.end(), std::pair<int, float>(*
iter, sim));
1919 UDEBUG(
"compute likelihood (similarity)... %f s",
timer.ticks());
1926 std::map<int, float> likelihood;
1927 std::map<int, float> calculatedWordsRatio;
1934 else if(ids.empty())
1936 UWARN(
"ids list is empty");
1940 for(std::list<int>::const_iterator
iter = ids.begin();
iter!=ids.end(); ++
iter)
1942 likelihood.insert(likelihood.end(), std::pair<int, float>(*
iter, 0.0f));
1959 UDEBUG(
"processing... ");
1961 for(std::list<int>::const_iterator
i=wordIds.begin();
i!=wordIds.end(); ++
i)
1976 for(std::map<int, int>::const_iterator
j=refs.begin();
j!=refs.end(); ++
j)
1978 std::map<int, float>::iterator
iter = likelihood.find(
j->first);
1979 if(
iter != likelihood.end())
1982 ni = this->
getNi(
j->first);
1986 iter->second += ( nwi * logNnw ) / ni;
1996 UDEBUG(
"compute likelihood (tf-idf) %f s",
timer.ticks());
2004 std::map<int, int> weights;
2012 UFATAL(
"Location %d must exist in memory",
iter->first);
2014 weights.insert(weights.end(), std::make_pair(
iter->first,
s->getWeight()));
2018 weights.insert(weights.end(), std::make_pair(
iter->first, -1));
2027 std::list<int> signaturesRemoved;
2038 int wordsRemoved = 0;
2045 while(wordsRemoved < newWords)
2048 if(signatures.size())
2053 signaturesRemoved.push_back(
s->id());
2067 UDEBUG(
"newWords=%d, wordsRemoved=%d", newWords, wordsRemoved);
2075 for(std::list<Signature *>::iterator
iter=signatures.begin();
iter!=signatures.end(); ++
iter)
2077 signaturesRemoved.push_back((*iter)->id());
2082 if((
int)signatures.size() < signaturesAdded)
2084 UWARN(
"Less signatures transferred (%d) than added (%d)! The working memory cannot decrease in size.",
2085 (
int)signatures.size(), signaturesAdded);
2089 UDEBUG(
"signaturesRemoved=%d, _signaturesAdded=%d", (
int)signatures.size(), signaturesAdded);
2092 return signaturesRemoved;
2099 int signatureRemoved = 0;
2112 return signatureRemoved;
2154 for(std::map<int, Transform>::iterator
iter=poses.lower_bound(1);
iter!=poses.end() && ok; ++
iter)
2158 UWARN(
"Node %d not found in working memory",
iter->first);
2164 UWARN(
"Optimized poses (%d) and working memory "
2165 "size (%d) don't match. Returning empty optimized "
2166 "poses to force re-update. If you want to use the "
2167 "saved optimized poses, set %s to true",
2170 Parameters::kMemInitWMWithAllNodes().c_str());
2171 return std::map<int, Transform>();
2176 return std::map<int, Transform>();
2197 const cv::Mat & cloud,
2198 const std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > & polygons,
2199 #
if PCL_VERSION_COMPARE(>=, 1, 8, 0)
2202 const std::vector<std::vector<Eigen::Vector2f> > & texCoords,
2204 const cv::Mat & textures)
const
2213 std::vector<std::vector<std::vector<RTABMAP_PCL_INDEX> > > * polygons,
2214 #
if PCL_VERSION_COMPARE(>=, 1, 8, 0)
2217 std::vector<std::vector<Eigen::Vector2f> > * texCoords,
2219 cv::Mat * textures)
const
2280 std::list<Signature *> removableSignatures;
2281 std::map<WeightAgeIdKey, Signature *> weightAgeIdMap;
2284 UDEBUG(
"mem.size()=%d, ignoredIds.size()=%d", (
int)
_workingMem.size(), (
int)ignoredIds.size());
2289 bool recentWmImmunized =
false;
2291 int currentRecentWmSize = 0;
2298 ++currentRecentWmSize;
2301 if(currentRecentWmSize>1 && currentRecentWmSize < recentWmMaxSize)
2303 recentWmImmunized =
true;
2305 else if(currentRecentWmSize == 0 &&
_workingMem.size() > 1)
2319 for(std::map<int, double>::const_iterator memIter =
_workingMem.begin(); memIter !=
_workingMem.end(); ++memIter)
2326 else if(memIter->first > 0 && ignoredIds.find(memIter->first) == ignoredIds.end() && (!lastInSTM || !lastInSTM->
hasLink(memIter->first)))
2332 bool foundInSTM =
false;
2333 for(std::map<int, Link>::const_iterator
iter =
s->getLinks().begin();
iter!=
s->getLinks().end(); ++
iter)
2337 UDEBUG(
"Ignored %d because it has a link (%d) to STM",
s->id(),
iter->first);
2359 int recentWmCount = 0;
2362 UDEBUG(
"signatureMap.size()=%d _lastGlobalLoopClosureId=%d currentRecentWmSize=%d recentWmMaxSize=%d",
2364 for(std::map<WeightAgeIdKey, Signature*>::iterator
iter=weightAgeIdMap.begin();
2365 iter!=weightAgeIdMap.end();
2368 if(!recentWmImmunized)
2370 UDEBUG(
"weight=%d, id=%d",
2371 iter->second->getWeight(),
2372 iter->second->id());
2373 removableSignatures.push_back(
iter->second);
2378 if(currentRecentWmSize - recentWmCount < recentWmMaxSize)
2380 UDEBUG(
"switched recentWmImmunized");
2381 recentWmImmunized =
true;
2387 UDEBUG(
"weight=%d, id=%d",
2388 iter->second->getWeight(),
2389 iter->second->id());
2390 removableSignatures.push_back(
iter->second);
2392 if(removableSignatures.size() >= (
unsigned int)
count)
2400 ULOGGER_WARN(
"not enough signatures to get an old one...");
2402 return removableSignatures;
2414 if(!
s->getLandmarks().empty())
2416 for(std::map<int, Link>::const_iterator
iter=
s->getLandmarks().begin();
iter!=
s->getLandmarks().end(); ++
iter)
2418 int landmarkId =
iter->first;
2422 nter->second.erase(
s->id());
2423 if(nter->second.empty())
2434 keepLinkedToGraph =
false;
2438 if(!keepLinkedToGraph)
2441 uFormat(
"Deleting location (%d) outside the "
2442 "STM is not implemented!",
s->id()).c_str());
2443 const std::multimap<int, Link> & links =
s->getLinks();
2444 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
2446 if(
iter->second.from() !=
iter->second.to() &&
iter->first > 0)
2451 uFormat(
"A neighbor (%d) of the deleted location %d is "
2452 "not found in WM/STM! Are you deleting a location "
2453 "outside the STM?",
iter->first,
s->id()).c_str());
2455 if(
iter->first >
s->id() && links.size()>1 && sTo->
hasLink(
s->id()))
2457 UWARN(
"Link %d of %d is newer, removing neighbor link "
2458 "may split the map!",
2459 iter->first,
s->id());
2472 s->removeLinks(
true);
2473 s->removeLandmarks();
2489 for(std::list<int>::const_iterator
i=
keys.begin();
i!=
keys.end(); ++
i)
2495 std::vector<VisualWord*> wordToDelete;
2496 wordToDelete.push_back(
w);
2500 deletedWords->push_back(
w->id());
2539 if(keepLinkedToGraph)
2565 UDEBUG(
"landmarkId=%d", landmarkId);
2566 std::map<int, Link>
nodes;
2572 for(std::set<int>::const_iterator jter=
iter->second.begin(); jter!=
iter->second.end(); ++jter)
2577 std::map<int, Link>::const_iterator kter =
s->getLandmarks().find(landmarkId);
2578 if(kter !=
s->getLandmarks().end())
2580 nodes.insert(std::make_pair(
s->id(), kter->second));
2595 UDEBUG(
"label=%s", label.c_str());
2602 if(
iter->second->getLabel().compare(label) == 0)
2604 id =
iter->second->id();
2608 if(
id == 0 &&
_dbDriver && lookInDatabase)
2628 if(idFound == 0 && label.empty() &&
_labels.find(
id)==
_labels.end())
2630 UWARN(
"Trying to remove label from node %d but it has already no label",
id);
2633 if(idFound == 0 || idFound ==
id)
2640 UWARN(
"Label \"%s\" removed from node %d",
_labels.at(
id).c_str(),
id);
2647 UWARN(
"Label \"%s\" set to node %d (previously labeled \"%s\")", label.c_str(),
id,
_labels.at(
id).c_str());
2651 UWARN(
"Label \"%s\" set to node %d", label.c_str(),
id);
2663 std::list<Signature *> signatures;
2665 if(signatures.size())
2669 UWARN(
"Label \"%s\" removed from node %d",
_labels.at(
id).c_str(),
id);
2676 UWARN(
"Label \"%s\" set to node %d (previously labeled \"%s\")", label.c_str(),
id,
_labels.at(
id).c_str());
2680 UWARN(
"Label \"%s\" set to node %d", label.c_str(),
id);
2685 signatures.front()->setLabel(label);
2692 UERROR(
"Node %d not found, failed to set label \"%s\"!",
id, label.c_str());
2697 UWARN(
"Another node %d has already label \"%s\", cannot set it to node %d", idFound, label.c_str(),
id);
2707 s->sensorData().setUserData(
data);
2712 UERROR(
"Node %d not found in RAM, failed to set user data (size=%d)!",
id,
data.total());
2719 UDEBUG(
"Deleting location %d", locationId);
2729 UDEBUG(
"Saving location data %d", locationId);
2753 UINFO(
"removing link between location %d and %d", oldS->
id(), newS->
id());
2774 bool noChildrenAnymore =
true;
2779 iter->second.from() !=
iter->second.to() &&
2780 iter->first < newS->
id())
2782 noChildrenAnymore =
false;
2793 UERROR(
"Signatures %d and %d don't have bidirectional link!", oldS->
id(), newS->
id());
2798 int landmarkId = newId<0?newId:oldId;
2800 s->removeLandmark(newId<0?newId:oldId);
2806 nter->second.erase(
s->id());
2813 UERROR(
"Signature %d is not in working memory... cannot remove link.", newS->
id());
2817 UERROR(
"Signature %d is not in working memory... cannot remove link.", oldS->
id());
2824 UDEBUG(
"id=%d image=%d scan=%d userData=%d",
id, image?1:0, scan?1:0, userData?1:0);
2828 s->sensorData().clearRawData(
2841 bool useKnownCorrespondencesIfPossible)
2854 std::string
msg =
uFormat(
"Did not find nodes %d and/or %d", fromId, toId);
2870 bool useKnownCorrespondencesIfPossible)
const
2890 cv::Mat imgBuf, depthBuf, userBuf;
2905 std::vector<int> inliersV;
2930 tmpFrom.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
2934 else if(useKnownCorrespondencesIfPossible)
2954 else if(!isNeighborRefining &&
2967 std::multimap<int, int> words;
2968 std::vector<cv::Point3f> words3DMap;
2969 std::vector<cv::KeyPoint> wordsMap;
2970 cv::Mat wordsDescriptorsMap;
2972 const std::multimap<int, Link> & links = fromS.
getLinks();
2976 UDEBUG(
"fromS.getWords()=%d uniques=%d", (
int)fromS.
getWords().size(), (
int)wordsFrom.size());
2977 for(std::map<int, int>::const_iterator jter=wordsFrom.begin(); jter!=wordsFrom.end(); ++jter)
2979 const cv::Point3f & pt = fromS.
getWords3()[jter->second];
2982 words.insert(std::make_pair(jter->first, words.size()));
2983 words3DMap.push_back(pt);
2984 wordsMap.push_back(fromS.
getWordsKpts()[jter->second]);
2989 UDEBUG(
"words3DMap=%d", (
int)words3DMap.size());
2991 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
2993 int id =
iter->first;
2997 if(s && !
s->getWords3().empty())
3000 for(std::map<int, int>::const_iterator jter=wordsTo.begin(); jter!=wordsTo.end(); ++jter)
3002 const cv::Point3f & pt =
s->getWords3()[jter->second];
3003 if( jter->first > 0 &&
3005 words.find(jter->first) == words.end())
3007 words.insert(words.end(), std::make_pair(jter->first, words.size()));
3009 wordsMap.push_back(
s->getWordsKpts()[jter->second]);
3010 wordsDescriptorsMap.push_back(
s->getWordsDescriptors().row(jter->second));
3016 UDEBUG(
"words3DMap=%d", (
int)words3DMap.size());
3018 tmpFrom2.
setWords(words, wordsMap, words3DMap, wordsDescriptorsMap);
3024 std::map<int, cv::Point3f> points3DMap;
3026 for(std::map<int, int>::iterator
iter=wordsMap.begin();
iter!=wordsMap.end(); ++
iter)
3028 points3DMap.insert(std::make_pair(
iter->first, tmpFrom2.
getWords3()[
iter->second]));
3030 std::map<int, Transform> bundlePoses;
3031 std::multimap<int, Link> bundleLinks;
3032 std::map<int, std::vector<CameraModel> > bundleModels;
3033 std::map<int, std::map<int, FeatureBA> > wordReferences;
3035 std::multimap<int, Link> links = fromS.
getLinks();
3038 links.insert(std::make_pair(fromS.
id(),
Link()));
3040 int totalWordReferences = 0;
3041 for(std::multimap<int, Link>::iterator
iter=links.begin();
iter!=links.end(); ++
iter)
3043 int id =
iter->first;
3044 if(
id != fromS.
id() ||
iter->second.transform().isNull())
3048 if(
id == tmpTo.
id())
3058 std::vector<CameraModel> models;
3059 if(
s->sensorData().cameraModels().size() >= 1 &&
s->sensorData().cameraModels().at(0).isValidForProjection())
3061 models =
s->sensorData().cameraModels();
3063 else if(
s->sensorData().stereoCameraModels().size() >= 1 &&
s->sensorData().stereoCameraModels().at(0).isValidForProjection())
3065 for(
size_t i=0;
i<
s->sensorData().stereoCameraModels().
size(); ++
i)
3073 model.localTransform(),
3074 -
s->sensorData().stereoCameraModels()[
i].baseline()*
model.fx(),
3076 models.push_back(
model);
3081 UFATAL(
"no valid camera model to use local bundle adjustment on loop closure!");
3083 bundleModels.insert(std::make_pair(
id, models));
3086 if(
iter->second.transform().isNull())
3093 bundleLinks.insert(std::make_pair(
iter->second.from(),
iter->second));
3094 bundlePoses.insert(std::make_pair(
id,
iter->second.transform()));
3098 for(std::map<int, int>::const_iterator jter=words.begin(); jter!=words.end(); ++jter)
3100 if(points3DMap.find(jter->first)!=points3DMap.end() &&
3101 (
id == tmpTo.
id() || jter->first > 0))
3103 cv::KeyPoint kpts =
s->getWordsKpts()[jter->second];
3104 int cameraIndex = 0;
3107 UASSERT(models[0].imageWidth()>0);
3108 float subImageWidth = models[0].imageWidth();
3109 cameraIndex =
int(kpts.pt.x / subImageWidth);
3110 kpts.pt.x = kpts.pt.x - (subImageWidth*
float(cameraIndex));
3115 if( !
s->getWords3().empty() &&
3119 Transform invLocalTransform = models[cameraIndex].localTransform().
inverse();
3122 wordReferences.insert(std::make_pair(jter->first, std::map<int, FeatureBA>()));
3123 wordReferences.at(jter->first).insert(std::make_pair(
id,
FeatureBA(kpts,
d, cv::Mat(), cameraIndex)));
3124 ++totalWordReferences;
3134 std::set<int> sbaOutliers;
3139 bundlePoses = sba.
optimizeBA(-toS.
id(), bundlePoses, bundleLinks, bundleModels, points3DMap, wordReferences, &sbaOutliers);
3142 UDEBUG(
"bundleTime=%fs (poses=%d wordRef=%d outliers=%d)", bundleTime.
ticks(), (
int)bundlePoses.size(), totalWordReferences, (
int)sbaOutliers.size());
3144 UDEBUG(
"Local Bundle Adjustment Before: %s",
transform.prettyPrint().c_str());
3145 if(!bundlePoses.rbegin()->second.isNull())
3147 if(sbaOutliers.size())
3149 std::vector<int> newInliers(
info->inliersIDs.size());
3151 for(
unsigned int i=0;
i<
info->inliersIDs.size(); ++
i)
3153 if(sbaOutliers.find(
info->inliersIDs[
i]) == sbaOutliers.end())
3155 newInliers[oi++] =
info->inliersIDs[
i];
3158 newInliers.resize(oi);
3159 UDEBUG(
"BA outliers ratio %f",
float(sbaOutliers.size())/
float(
info->inliersIDs.size()));
3160 info->inliers = (
int)newInliers.size();
3161 info->inliersIDs = newInliers;
3170 transform = bundlePoses.rbegin()->second;
3177 UDEBUG(
"Local Bundle Adjustment After : %s",
transform.prettyPrint().c_str());
3191 std::string
msg =
uFormat(
"Missing visual features or missing raw data to compute them. Transform cannot be estimated.");
3218 const std::map<int, Transform> & poses,
3224 UDEBUG(
"%d -> %d, Guess=%s", fromId, toId, (poses.at(fromId).inverse() * poses.at(toId)).prettyPrint().c_str());
3228 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
3230 if(
iter->first != fromId)
3235 UDEBUG(
"%d vs %s", fromId, ids.c_str());
3239 std::list<Signature*> scansToLoad;
3240 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
3245 if(
s->sensorData().imageCompressed().empty() &&
3246 s->sensorData().laserScanCompressed().isEmpty())
3248 scansToLoad.push_back(
s);
3268 float guessNorm = guess.
getNorm();
3273 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());
3280 int maxPoints = fromScan.
size();
3281 pcl::PointCloud<pcl::PointXYZ>::Ptr assembledToClouds(
new pcl::PointCloud<pcl::PointXYZ>);
3282 pcl::PointCloud<pcl::PointNormal>::Ptr assembledToNormalClouds(
new pcl::PointCloud<pcl::PointNormal>);
3283 pcl::PointCloud<pcl::PointXYZI>::Ptr assembledToIClouds(
new pcl::PointCloud<pcl::PointXYZI>);
3284 pcl::PointCloud<pcl::PointXYZINormal>::Ptr assembledToNormalIClouds(
new pcl::PointCloud<pcl::PointXYZINormal>);
3285 pcl::PointCloud<pcl::PointXYZRGB>::Ptr assembledToRGBClouds(
new pcl::PointCloud<pcl::PointXYZRGB>);
3286 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr assembledToNormalRGBClouds(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3287 UDEBUG(
"maxPoints from(%d) = %d", fromId, maxPoints);
3288 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
3290 if(
iter->first != fromId)
3296 s->sensorData().uncompressData(0, 0, &scan);
3339 if(scan.
size() > maxPoints)
3341 UDEBUG(
"maxPoints scan(%d) = %d",
iter->first, (
int)scan.
size());
3342 maxPoints = scan.
size();
3352 UWARN(
"Depth2D not found for signature %d",
iter->first);
3358 if(assembledToNormalClouds->size())
3362 else if(assembledToClouds->size())
3366 else if(assembledToNormalIClouds->size())
3370 else if(assembledToIClouds->size())
3374 else if(assembledToNormalRGBClouds->size())
3378 UERROR(
"Cannot handle 2d scan with RGB format.");
3385 else if(assembledToRGBClouds->size())
3389 UERROR(
"Cannot handle 2d scan with RGB format.");
3396 UDEBUG(
"assembledScan=%d points", assembledScan.
size());
3428 UINFO(
"already linked! to=%d, from=%d", link.
to(), link.
from());
3432 UDEBUG(
"Add link between %d and %d", toS->
id(), fromS->
id());
3468 else if(!addInDatabase)
3472 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
from());
3476 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
to());
3482 UDEBUG(
"Add link between %d and %d (db)", link.
from(), link.
to());
3488 UDEBUG(
"Add link between %d (db) and %d", link.
from(), link.
to());
3494 UDEBUG(
"Add link between %d (db) and %d (db)", link.
from(), link.
to());
3525 UERROR(
"fromId=%d and toId=%d are not linked!", link.
from(), link.
to());
3528 else if(!updateInDatabase)
3532 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
from());
3536 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
to());
3541 UDEBUG(
"Update link between %d and %d (db)", link.
from(), link.
to());
3548 UDEBUG(
"Update link between %d (db) and %d", link.
from(), link.
to());
3555 UDEBUG(
"Update link between %d (db) and %d (db)", link.
from(), link.
to());
3566 iter->second->removeVirtualLinks();
3576 const std::multimap<int, Link> & links =
s->getLinks();
3577 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
3588 UERROR(
"Link %d of %d not in WM/STM?!?",
iter->first,
s->id());
3592 s->removeVirtualLinks();
3596 UERROR(
"Signature %d not in WM/STM?!?", signatureId);
3602 UINFO(
"Dumping memory to directory \"%s\"", directory.c_str());
3622 fopen_s(&foutSign, fileNameSign,
"w");
3624 foutSign = fopen(fileNameSign,
"w");
3629 fprintf(foutSign,
"SignatureID WordsID...\n");
3630 const std::map<int, Signature *> & signatures = this->
getSignatures();
3631 for(std::map<int, Signature *>::const_iterator
iter=signatures.begin();
iter!=signatures.end(); ++
iter)
3633 fprintf(foutSign,
"%d ",
iter->first);
3641 const std::multimap<int, int> &
ref = ss->
getWords();
3642 for(std::multimap<int, int>::const_iterator jter=
ref.begin(); jter!=
ref.end(); ++jter)
3644 const cv::Point3f & pt = ss->
getWords3()[jter->second];
3646 if(pcl::isFinite(pt) &&
3647 (pt.x != 0 || pt.y != 0 || pt.z != 0))
3649 fprintf(foutSign,
"%d ", (*jter).first);
3656 const std::multimap<int, int> &
ref = ss->
getWords();
3657 for(std::multimap<int, int>::const_iterator jter=
ref.begin(); jter!=
ref.end(); ++jter)
3659 fprintf(foutSign,
"%d ", (*jter).first);
3663 fprintf(foutSign,
"\n");
3674 fopen_s(&foutTree, fileNameTree,
"w");
3676 foutTree = fopen(fileNameTree,
"w");
3681 fprintf(foutTree,
"SignatureID Weight NbLoopClosureIds LoopClosureIds... NbChildLoopClosureIds ChildLoopClosureIds...\n");
3685 fprintf(foutTree,
"%d %d",
i->first,
i->second->getWeight());
3687 std::map<int, Link> loopIds, childIds;
3689 for(std::map<int, Link>::const_iterator
iter =
i->second->getLinks().begin();
3690 iter!=
i->second->getLinks().end();
3696 if(
iter->first <
i->first)
3698 childIds.insert(*
iter);
3700 else if(
iter->second.from() !=
iter->second.to())
3702 loopIds.insert(*
iter);
3707 fprintf(foutTree,
" %d", (
int)loopIds.size());
3708 for(std::map<int, Link>::const_iterator
j=loopIds.begin();
j!=loopIds.end(); ++
j)
3710 fprintf(foutTree,
" %d",
j->first);
3713 fprintf(foutTree,
" %d", (
int)childIds.size());
3714 for(std::map<int, Link>::const_iterator
j=childIds.begin();
j!=childIds.end(); ++
j)
3716 fprintf(foutTree,
" %d",
j->first);
3719 fprintf(foutTree,
"\n");
3729 unsigned long memoryUsage =
sizeof(
Memory);
3730 memoryUsage +=
_signatures.size() * (
sizeof(
int)+
sizeof(std::map<int, Signature *>::iterator)) +
sizeof(std::map<int, Signature *>);
3733 memoryUsage +=
iter->second->getMemoryUsed(
true);
3739 memoryUsage +=
_stMem.size() * (
sizeof(
int)+
sizeof(std::set<int>::iterator)) +
sizeof(std::set<int>);
3740 memoryUsage +=
_workingMem.size() * (
sizeof(
int)+
sizeof(
double)+
sizeof(std::map<int, double>::iterator)) +
sizeof(std::map<int, double>);
3741 memoryUsage +=
_groundTruths.size() * (
sizeof(
int)+
sizeof(
Transform)+12*
sizeof(
float) +
sizeof(std::map<int, Transform>::iterator)) +
sizeof(std::map<int, Transform>);
3742 memoryUsage +=
_labels.size() * (
sizeof(
int)+
sizeof(std::string) +
sizeof(std::map<int, std::string>::iterator)) +
sizeof(std::map<int, std::string>);
3745 memoryUsage+=
iter->second.size();
3747 memoryUsage +=
_landmarksIndex.size() * (
sizeof(
int)+
sizeof(std::set<int>) +
sizeof(std::map<int, std::set<int> >
::iterator)) +
sizeof(std::map<int, std::set<int> >);
3750 memoryUsage+=
iter->second.size()*(
sizeof(
int)+
sizeof(std::set<int>::iterator)) +
sizeof(std::set<int>);
3779 if(
s->getWeight() >= 0 &&
s->id() != signature->
id())
3788 UDEBUG(
"Comparing with signature (%d)...",
id);
3808 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_merged(), merged);
3809 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_sim(), sim);
3811 UDEBUG(
"merged=%d, sim=%f t=%fs", merged, sim,
timer.ticks());
3815 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_merged(), 0);
3816 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_sim(), 0);
3828 std::map<int, Link>::const_iterator
iter = oldS->
getLinks().find(newS->
id());
3832 iter->second.from() !=
iter->second.to())
3835 UWARN(
"already merged, old=%d, new=%d", oldId, newId);
3840 UINFO(
"Rehearsal merging %d (w=%d) and %d (w=%d)",
3845 bool intermediateMerge =
false;
3846 if(!newS->
getLinks().empty() && !newS->
getLinks().begin()->second.transform().isNull())
3861 UINFO(
"Rehearsal ignored because the robot has moved more than %f m or %f rad (\"Mem/RehearsalWeightIgnoredWhileMoving\"=true)",
3865 fullMerge = !isMoving && newS->
hasLink(oldS->
id());
3866 intermediateMerge = !isMoving && !newS->
hasLink(oldS->
id());
3870 fullMerge = newS->
hasLink(oldS->
id()) && newS->
getLinks().begin()->second.transform().isNull();
3872 UDEBUG(
"fullMerge=%s intermediateMerge=%s _idUpdatedToNewOneRehearsal=%s",
3873 fullMerge?
"true":
"false",
3874 intermediateMerge?
"true":
"false",
3887 const std::multimap<int, Link> & links = oldS->
getLinks();
3888 for(std::multimap<int, Link>::const_iterator
iter = links.begin();
iter!=links.end(); ++
iter)
3890 if(
iter->second.from() !=
iter->second.to())
3900 s->removeLink(oldS->
id());
3907 UERROR(
"Didn't find neighbor %d of %d in RAM...", link.
to(), oldS->
id());
3956 oldS->
setWeight(intermediateMerge?-1:0);
3967 newS->
setWeight(intermediateMerge?-1:0);
3975 UERROR(
"newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, newId);
3979 UERROR(
"newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, oldId);
3988 int mapId = -1, weight;
3994 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
4007 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
4020 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
4035 getNodeInfo(
id, odomPose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
4037 if(gps.
stamp() == 0.0)
4041 std::map<int, int> nearestIds;
4042 nearestIds =
getNeighborsId(
id, maxGraphDepth, lookInDatabase?-1:0,
true,
false,
true);
4043 std::multimap<int, int> nearestIdsSorted;
4044 for(std::map<int, int>::iterator
iter=nearestIds.begin();
iter!=nearestIds.end(); ++
iter)
4046 nearestIdsSorted.insert(std::make_pair(
iter->second,
iter->first));
4049 for(std::map<int, int>::iterator
iter=nearestIdsSorted.begin();
iter!=nearestIdsSorted.end(); ++
iter)
4053 if(
s->sensorData().gps().stamp() > 0.0)
4056 if(
path.size() >= 2)
4058 gps =
s->sensorData().gps();
4060 offsetENU = localToENU*(
s->getPose().rotation()*
path.rbegin()->second);
4065 UWARN(
"Failed to find path %d -> %d",
s->id(),
id);
4076 std::string & label,
4079 std::vector<float> & velocity,
4082 bool lookInDatabase)
const
4087 odomPose =
s->getPose().clone();
4089 weight =
s->getWeight();
4090 label = std::string(
s->getLabel());
4091 stamp =
s->getStamp();
4092 groundTruth =
s->getGroundTruthPose().clone();
4093 velocity = std::vector<float>(
s->getVelocity());
4094 gps =
GPS(
s->sensorData().gps());
4095 sensors =
EnvSensors(
s->sensorData().envSensors());
4111 image =
s->sensorData().imageCompressed();
4117 image =
data.imageCompressed();
4127 if(
s && (!
s->isSaved() ||
4128 ((!images || !
s->sensorData().imageCompressed().empty()) &&
4129 (!scan || !
s->sensorData().laserScanCompressed().isEmpty()) &&
4130 (!userData || !
s->sensorData().userDataCompressed().empty()) &&
4131 (!occupancyGrid ||
s->sensorData().gridCellSize() != 0.0f))))
4133 r =
s->sensorData();
4136 r.
setRGBDImage(cv::Mat(), cv::Mat(), std::vector<CameraModel>());
4161 std::multimap<int, int> & words,
4162 std::vector<cv::KeyPoint> & wordsKpts,
4163 std::vector<cv::Point3f> & words3,
4164 cv::Mat & wordsDescriptors,
4165 std::vector<GlobalDescriptor> & globalDescriptors)
const
4171 words =
s->getWords();
4172 wordsKpts =
s->getWordsKpts();
4173 words3 =
s->getWords3();
4174 wordsDescriptors =
s->getWordsDescriptors();
4175 globalDescriptors =
s->sensorData().globalDescriptors();
4180 std::list<Signature*> signatures;
4182 ids.push_back(nodeId);
4183 std::set<int> loadedFromTrash;
4185 if(signatures.size())
4187 words = signatures.front()->getWords();
4188 wordsKpts = signatures.front()->getWordsKpts();
4189 words3 = signatures.front()->getWords3();
4190 wordsDescriptors = signatures.front()->getWordsDescriptors();
4191 globalDescriptors = signatures.front()->sensorData().globalDescriptors();
4192 if(loadedFromTrash.size())
4199 delete signatures.front();
4206 std::vector<CameraModel> & models,
4207 std::vector<StereoCameraModel> & stereoModels)
const
4213 models =
s->sensorData().cameraModels();
4214 stereoModels =
s->sensorData().stereoCameraModels();
4227 UERROR(
"A database must must loaded first...");
4235 const std::map<int, Transform> & poses,
4236 const cv::Mat & map,
4245 UERROR(
"A database must be loaded first...");
4249 if(poses.empty() || poses.lower_bound(1) == poses.end())
4263 for(std::map<int, Transform>::const_iterator
iter=poses.lower_bound(1);
iter!=poses.end(); ++
iter)
4268 UINFO(
"Processing %d grids...", maxPoses);
4269 int processedGrids = 1;
4270 int gridsScansModified = 0;
4271 for(std::map<int, Transform>::const_iterator
iter=poses.lower_bound(1);
iter!=poses.end(); ++
iter, ++processedGrids)
4275 cv::Mat gridObstacles;
4281 data.uncompressData(0,0,&scan,0,&gridGround,&gridObstacles,&gridEmpty);
4283 if(!gridObstacles.empty())
4286 cv::Mat filtered = cv::Mat(1, gridObstacles.cols, gridObstacles.type());
4288 for(
int i=0;
i<gridObstacles.cols; ++
i)
4290 const float * ptr = gridObstacles.ptr<
float>(0,
i);
4291 cv::Point3f pt(ptr[0], ptr[1], gridObstacles.channels()==2?0:ptr[2]);
4294 int x =
int((pt.x - xMin) / cellSize + 0.5f);
4295 int y =
int((pt.y - yMin) / cellSize + 0.5f);
4297 if(
x>=0 &&
x<map.cols &&
4300 bool obstacleDetected =
false;
4302 for(
int j=-cropRadius;
j<=cropRadius && !obstacleDetected; ++
j)
4304 for(
int k=-cropRadius; k<=cropRadius && !obstacleDetected; ++k)
4306 if(
x+
j>=0 &&
x+
j<map.cols &&
4307 y+k>=0 &&
y+k<map.rows &&
4308 map.at<
unsigned char>(
y+k,
x+
j) == 100)
4310 obstacleDetected =
true;
4315 if(map.at<
unsigned char>(
y,
x) != 0 || obstacleDetected)
4324 if(oi != gridObstacles.cols)
4326 UINFO(
"Grid id=%d (%d/%d) filtered %d -> %d",
iter->first, processedGrids, maxPoses, gridObstacles.cols, oi);
4327 gridsScansModified += 1;
4331 cv::Mat newObstacles = cv::Mat(filtered,
cv::Range::all(), cv::Range(0, oi));
4332 bool modifyDb =
true;
4335 s->sensorData().setOccupancyGrid(gridGround, newObstacles, gridEmpty, cellSize,
data.gridViewPoint());
4349 data.gridViewPoint());
4354 if(filterScans && !scan.
isEmpty())
4358 cv::Mat filtered = cv::Mat(1, scan.
size(), scan.
dataType());
4360 for(
int i=0;
i<scan.
size(); ++
i)
4362 const float * ptr = scan.
data().ptr<
float>(0,
i);
4363 cv::Point3f pt(ptr[0], ptr[1], scan.
is2d()?0:ptr[2]);
4366 int x =
int((pt.x - xMin) / cellSize + 0.5f);
4367 int y =
int((pt.y - yMin) / cellSize + 0.5f);
4369 if(
x>=0 &&
x<map.cols &&
4372 bool obstacleDetected =
false;
4374 for(
int j=-cropRadius;
j<=cropRadius && !obstacleDetected; ++
j)
4376 for(
int k=-cropRadius; k<=cropRadius && !obstacleDetected; ++k)
4378 if(
x+
j>=0 &&
x+
j<map.cols &&
4379 y+k>=0 &&
y+k<map.rows &&
4380 map.at<
unsigned char>(
y+k,
x+
j) == 100)
4382 obstacleDetected =
true;
4387 if(map.at<
unsigned char>(
y,
x) != 0 || obstacleDetected)
4396 if(oi != scan.
size())
4398 UINFO(
"Scan id=%d (%d/%d) filtered %d -> %d",
iter->first, processedGrids, maxPoses, (
int)scan.
size(), oi);
4399 gridsScansModified += 1;
4428 bool modifyDb =
true;
4431 s->sensorData().setLaserScan(scan,
true);
4446 return gridsScansModified;
4475 id.push_back(to->
id());
4481 UDEBUG(
"Loaded image data from database");
4493 ULOGGER_ERROR(
"Can't merge the signatures because there are not same type.");
4519 data.imageRaw().type() == CV_8UC1 ||
4520 data.imageRaw().type() == CV_8UC3);
4522 ( (
data.depthOrRightRaw().type() == CV_16UC1 ||
4523 data.depthOrRightRaw().type() == CV_32FC1 ||
4524 data.depthOrRightRaw().type() == CV_8UC1)
4526 ( (
data.imageRaw().empty() &&
data.depthOrRightRaw().type() != CV_8UC1) ||
4527 (
data.depthOrRightRaw().rows <=
data.imageRaw().rows &&
data.depthOrRightRaw().cols <=
data.imageRaw().cols))),
4528 uFormat(
"image=(%d/%d, type=%d, [accepted=%d,%d]) depth=(%d/%d, type=%d [accepted=%d(depth mm),%d(depth m),%d(stereo)]). "
4529 "For stereo, left and right images should be same size. "
4530 "For RGB-D, depth can be X times smaller than RGB (where X is an integer).",
4531 data.imageRaw().cols,
4532 data.imageRaw().rows,
4533 data.imageRaw().type(),
4536 data.depthOrRightRaw().cols,
4537 data.depthOrRightRaw().rows,
4538 data.depthOrRightRaw().type(),
4539 CV_16UC1, CV_32FC1, CV_8UC1).c_str());
4541 if(!
data.depthOrRightRaw().empty() &&
4542 data.cameraModels().empty() &&
4543 data.stereoCameraModels().empty() &&
4546 UERROR(
"No camera calibration found, calibrate your camera!");
4556 std::vector<cv::KeyPoint> keypoints;
4557 cv::Mat descriptors;
4558 bool isIntermediateNode =
data.id() < 0;
4568 UERROR(
"Received image ID is null. "
4569 "Please set parameter Mem/GenerateIds to \"true\" or "
4570 "make sure the input source provides image ids (seq).");
4579 UERROR(
"Id of acquired image (%d) is smaller than the last in memory (%d). "
4580 "Please set parameter Mem/GenerateIds to \"true\" or "
4581 "make sure the input source provides image ids (seq) over the last in "
4582 "memory, which is %d.",
4595 if(
data.cameraModels().size())
4597 UDEBUG(
"Monocular rectification");
4599 UASSERT(
int((
data.imageRaw().cols/
data.cameraModels().size())*
data.cameraModels().size()) ==
data.imageRaw().cols);
4600 int subImageWidth =
data.imageRaw().cols/
data.cameraModels().size();
4601 cv::Mat rectifiedImages(
data.imageRaw().size(),
data.imageRaw().type());
4607 for(
unsigned int i=0;
i<
data.cameraModels().
size(); ++
i)
4609 if(
data.cameraModels()[
i].isValidForRectification())
4616 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)...",
i);
4618 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)... done!",
i);
4623 cv::Mat rectifiedImage =
_rectCameraModels[
i].rectifyImage(cv::Mat(
data.imageRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4624 rectifiedImage.copyTo(cv::Mat(rectifiedImages, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4625 imagesRectified =
true;
4629 UERROR(
"Calibration for camera %d cannot be used to rectify the image. Make sure to do a "
4630 "full calibration. If images are already rectified, set %s parameter back to true.",
4632 Parameters::kRtabmapImagesAlreadyRectified().
c_str());
4633 std::cout <<
data.cameraModels()[
i] << std::endl;
4637 data.setRGBDImage(rectifiedImages,
data.depthOrRightRaw(),
data.cameraModels());
4639 else if(
data.stereoCameraModels().size())
4641 UDEBUG(
"Stereo rectification");
4642 UASSERT(
int((
data.imageRaw().cols/
data.stereoCameraModels().size())*
data.stereoCameraModels().size()) ==
data.imageRaw().cols);
4643 int subImageWidth =
data.imageRaw().cols/
data.stereoCameraModels().size();
4644 UASSERT(subImageWidth ==
data.rightRaw().cols/(
int)
data.stereoCameraModels().size());
4645 cv::Mat rectifiedLefts(
data.imageRaw().size(),
data.imageRaw().type());
4646 cv::Mat rectifiedRights(
data.rightRaw().size(),
data.rightRaw().type());
4653 for(
unsigned int i=0;
i<
data.stereoCameraModels().
size(); ++
i)
4655 if(
data.stereoCameraModels()[
i].isValidForRectification())
4662 UWARN(
"Initializing rectification maps (only done for the first image received)...");
4664 UWARN(
"Initializing rectification maps (only done for the first image received)...done!");
4670 cv::Mat rectifiedLeft =
_rectStereoCameraModels[
i].left().rectifyImage(cv::Mat(
data.imageRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4671 cv::Mat rectifiedRight =
_rectStereoCameraModels[
i].right().rectifyImage(cv::Mat(
data.rightRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.rightRaw().rows)));
4672 rectifiedLeft.copyTo(cv::Mat(rectifiedLefts, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4673 rectifiedRight.copyTo(cv::Mat(rectifiedRights, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.rightRaw().rows)));
4674 imagesRectified =
true;
4678 UERROR(
"Calibration for camera %d cannot be used to rectify the image. Make sure to do a "
4679 "full calibration. If images are already rectified, set %s parameter back to true.",
4681 Parameters::kRtabmapImagesAlreadyRectified().
c_str());
4682 std::cout <<
data.stereoCameraModels()[
i] << std::endl;
4687 data.setStereoImage(
4690 data.stereoCameraModels());
4694 UERROR(
"Stereo calibration cannot be used to rectify images. Make sure to do a "
4695 "full stereo calibration. If images are already rectified, set %s parameter back to true.",
4696 Parameters::kRtabmapImagesAlreadyRectified().
c_str());
4700 if(
stats)
stats->addStatistic(Statistics::kTimingMemRectification(),
t*1000.0
f);
4701 UDEBUG(
"time rectification = %fs",
t);
4713 UDEBUG(
"Start dictionary update thread");
4714 preUpdateThread.
start();
4720 UASSERT(
int((
data.imageRaw().cols/
data.cameraModels().size())*
data.cameraModels().size()) ==
data.imageRaw().cols);
4721 int subInputImageWidth =
data.imageRaw().cols/
data.cameraModels().size();
4722 int subInputDepthWidth =
data.depthRaw().cols/
data.cameraModels().size();
4723 int subOutputImageWidth = 0;
4724 int subOutputDepthWidth = 0;
4725 cv::Mat rotatedColorImages;
4726 cv::Mat rotatedDepthImages;
4727 std::vector<CameraModel> rotatedCameraModels;
4728 bool allOutputSizesAreOkay =
true;
4729 bool atLeastOneCameraRotated =
false;
4730 for(
size_t i=0;
i<
data.cameraModels().
size(); ++
i)
4732 UDEBUG(
"Rotating camera %ld",
i);
4733 cv::Mat rgb = cv::Mat(
data.imageRaw(), cv::Rect(subInputImageWidth*
i, 0, subInputImageWidth,
data.imageRaw().rows));
4734 cv::Mat depth = !
data.depthRaw().empty()?cv::Mat(
data.depthRaw(), cv::Rect(subInputDepthWidth*
i, 0, subInputDepthWidth,
data.depthRaw().rows)):cv::Mat();
4737 if(rotatedColorImages.empty())
4739 rotatedColorImages = cv::Mat(cv::Size(rgb.cols *
data.cameraModels().size(), rgb.rows), rgb.type());
4740 subOutputImageWidth = rgb.cols;;
4743 rotatedDepthImages = cv::Mat(cv::Size(depth.cols *
data.cameraModels().size(), depth.rows), depth.type());
4744 subOutputDepthWidth = depth.cols;
4747 else if(rgb.cols != subOutputImageWidth || depth.cols != subOutputDepthWidth ||
4748 rgb.rows != rotatedColorImages.rows || depth.rows != rotatedDepthImages.rows)
4750 UWARN(
"Rotated image for camera index %d (rgb=%dx%d depth=%dx%d) doesn't tally "
4751 "with the first camera (rgb=%dx%d, depth=%dx%d). Aborting upside up rotation, "
4752 "will use original image orientation. Set parameter %s to false to avoid "
4756 depth.cols, depth.rows,
4757 subOutputImageWidth, rotatedColorImages.rows,
4758 subOutputDepthWidth, rotatedDepthImages.rows,
4759 Parameters::kMemRotateImagesUpsideUp().c_str());
4760 allOutputSizesAreOkay =
false;
4763 rgb.copyTo(cv::Mat(rotatedColorImages, cv::Rect(subOutputImageWidth*
i, 0, subOutputImageWidth, rgb.rows)));
4766 depth.copyTo(cv::Mat(rotatedDepthImages, cv::Rect(subOutputDepthWidth*
i, 0, subOutputDepthWidth, depth.rows)));
4768 rotatedCameraModels.push_back(
model);
4770 if(allOutputSizesAreOkay && atLeastOneCameraRotated)
4772 data.setRGBDImage(rotatedColorImages, rotatedDepthImages, rotatedCameraModels);
4775 if(!
data.keypoints().empty() || !
data.keypoints3D().empty() || !
data.descriptors().empty())
4779 static bool warned =
false;
4782 UWARN(
"Because parameter %s is enabled, parameter %s is inhibited as "
4783 "features have to be regenerated. To avoid this warning, set "
4784 "explicitly %s to false. This message is only "
4786 Parameters::kMemRotateImagesUpsideUp().
c_str(),
4787 Parameters::kMemUseOdomFeatures().
c_str(),
4788 Parameters::kMemUseOdomFeatures().
c_str());
4792 data.setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
4798 static bool warned =
false;
4801 UWARN(
"Parameter %s can only be used with RGB-only or RGB-D cameras. "
4802 "Ignoring upside up rotation. This message is only printed once.",
4803 Parameters::kMemRotateImagesUpsideUp().
c_str());
4808 unsigned int preDecimation = 1;
4809 std::vector<cv::Point3f> keypoints3D;
4811 UDEBUG(
"Received kpts=%d kpts3D=%d, descriptors=%d _useOdometryFeatures=%s",
4814 data.keypoints().empty() ||
4815 (
int)
data.keypoints().size() !=
data.descriptors().rows ||
4820 decimatedData =
data;
4825 if( !
data.cameraModels().empty() &&
4826 data.cameraModels()[0].imageHeight()>0 &&
4827 data.cameraModels()[0].imageWidth()>0)
4831 if(targetSize >=
data.depthRaw().rows)
4833 decimationDepth = 1;
4837 decimationDepth = (
int)
ceil(
float(
data.depthRaw().rows) /
float(targetSize));
4842 std::vector<CameraModel> cameraModels = decimatedData.
cameraModels();
4843 for(
unsigned int i=0;
i<cameraModels.size(); ++
i)
4847 if(!cameraModels.empty())
4855 std::vector<StereoCameraModel> stereoCameraModels = decimatedData.
stereoCameraModels();
4856 for(
unsigned int i=0;
i<stereoCameraModels.size(); ++
i)
4860 if(!stereoCameraModels.empty())
4865 stereoCameraModels);
4869 UINFO(
"Extract features");
4871 if(decimatedData.
imageRaw().channels() == 3)
4873 cv::cvtColor(decimatedData.
imageRaw(), imageMono, CV_BGR2GRAY);
4877 imageMono = decimatedData.
imageRaw();
4883 if(imageMono.rows % decimatedData.
depthRaw().rows == 0 &&
4884 imageMono.cols % decimatedData.
depthRaw().cols == 0 &&
4885 imageMono.rows/decimatedData.
depthRaw().rows == imageMono.cols/decimatedData.
depthRaw().cols)
4891 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).",
4892 Parameters::kMemDepthAsMask().
c_str(),
4893 imageMono.cols, imageMono.rows,
4899 bool useProvided3dPoints =
false;
4902 UDEBUG(
"Using provided keypoints (%d)", (
int)
data.keypoints().size());
4903 keypoints =
data.keypoints();
4905 useProvided3dPoints = keypoints.size() ==
data.keypoints3D().size();
4913 for(
unsigned int i=0;
i < keypoints.size(); ++
i)
4915 cv::KeyPoint & kpt = keypoints[
i];
4918 kpt.pt.x *= decimationRatio;
4919 kpt.pt.y *= decimationRatio;
4920 kpt.size *= decimationRatio;
4921 kpt.octave += log2value;
4923 if(useProvided3dPoints)
4925 keypoints[
i].class_id =
i;
4947 if(tmpMaxFeatureParameter.size())
4949 tmpMaxFeatureParameter.at(Parameters::kKpMaxFeatures()) =
uNumber2Str(oldMaxFeatures);
4953 if(
stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_detection(),
t*1000.0
f);
4954 UDEBUG(
"time keypoints (%d) = %fs", (
int)keypoints.size(),
t);
4959 if(
stats)
stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(),
t*1000.0
f);
4960 UDEBUG(
"time descriptors (%d) = %fs", descriptors.rows,
t);
4963 if(descriptors.rows && descriptors.rows <
_badSignRatio *
float(meanWordsPerLocation))
4965 descriptors = cv::Mat();
4969 if(!imagesRectified && decimatedData.
cameraModels().size())
4971 UASSERT_MSG((
int)keypoints.size() == descriptors.rows,
uFormat(
"%d vs %d", (
int)keypoints.size(), descriptors.rows).c_str());
4972 std::vector<cv::KeyPoint> keypointsValid;
4973 keypointsValid.reserve(keypoints.size());
4974 cv::Mat descriptorsValid;
4975 descriptorsValid.reserve(descriptors.rows);
4980 std::vector<cv::Point2f> pointsIn, pointsOut;
4981 cv::KeyPoint::convert(keypoints,pointsIn);
4984 #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)))
4987 cv::Mat
D(1, 4, CV_64FC1);
4988 D.at<
double>(0,0) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,0);
4989 D.at<
double>(0,1) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,1);
4990 D.at<
double>(0,2) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,4);
4991 D.at<
double>(0,3) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,5);
4992 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5000 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5001 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5006 cv::undistortPoints(pointsIn, pointsOut,
5012 UASSERT(pointsOut.size() == keypoints.size());
5013 for(
unsigned int i=0;
i<pointsOut.size(); ++
i)
5015 if(pointsOut.at(
i).x>=0 && pointsOut.at(
i).x<decimatedData.
cameraModels()[0].imageWidth() &&
5016 pointsOut.at(
i).y>=0 && pointsOut.at(
i).y<decimatedData.
cameraModels()[0].imageHeight())
5018 keypointsValid.push_back(keypoints.at(
i));
5019 keypointsValid.back().pt.x = pointsOut.at(
i).x;
5020 keypointsValid.back().pt.y = pointsOut.at(
i).y;
5021 descriptorsValid.push_back(descriptors.row(
i));
5029 for(
unsigned int i=0;
i<keypoints.size(); ++
i)
5031 int cameraIndex =
int(keypoints.at(
i).pt.x / subImageWidth);
5033 uFormat(
"cameraIndex=%d, models=%d, kpt.x=%f, subImageWidth=%f (Camera model image width=%d)",
5034 cameraIndex, (
int)decimatedData.
cameraModels().size(), keypoints[
i].pt.x, subImageWidth, decimatedData.
cameraModels()[0].imageWidth()).c_str());
5036 std::vector<cv::Point2f> pointsIn, pointsOut;
5037 pointsIn.push_back(cv::Point2f(keypoints.at(
i).pt.x-subImageWidth*cameraIndex, keypoints.at(
i).pt.y));
5038 if(decimatedData.
cameraModels()[cameraIndex].D_raw().cols == 6)
5040 #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)))
5043 cv::Mat
D(1, 4, CV_64FC1);
5044 D.at<
double>(0,0) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,0);
5045 D.at<
double>(0,1) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,1);
5046 D.at<
double>(0,2) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,4);
5047 D.at<
double>(0,3) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,5);
5048 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5056 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5057 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5062 cv::undistortPoints(pointsIn, pointsOut,
5069 if(pointsOut[0].
x>=0 && pointsOut[0].
x<decimatedData.
cameraModels()[cameraIndex].imageWidth() &&
5070 pointsOut[0].y>=0 && pointsOut[0].y<decimatedData.
cameraModels()[cameraIndex].imageHeight())
5072 keypointsValid.push_back(keypoints.at(
i));
5073 keypointsValid.back().pt.x = pointsOut[0].x + subImageWidth*cameraIndex;
5074 keypointsValid.back().pt.y = pointsOut[0].y;
5075 descriptorsValid.push_back(descriptors.row(
i));
5080 keypoints = keypointsValid;
5081 descriptors = descriptorsValid;
5084 if(
stats)
stats->addStatistic(Statistics::kTimingMemRectification(),
t*1000.0
f);
5085 UDEBUG(
"time rectification = %fs",
t);
5088 if(useProvided3dPoints && keypoints.size() !=
data.keypoints3D().size())
5090 UDEBUG(
"Using provided 3d points (%d->%d)", (
int)
data.keypoints3D().size(), (
int)keypoints.size());
5091 keypoints3D.resize(keypoints.size());
5092 for(
size_t i=0;
i<keypoints.size(); ++
i)
5094 UASSERT(keypoints[
i].class_id < (
int)
data.keypoints3D().size());
5095 keypoints3D[
i] =
data.keypoints3D()[keypoints[
i].class_id];
5098 else if(useProvided3dPoints && keypoints.size() ==
data.keypoints3D().size())
5100 UDEBUG(
"Using provided 3d points (%d)", (
int)
data.keypoints3D().size());
5101 keypoints3D =
data.keypoints3D();
5108 if(
stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_3D(),
t*1000.0
f);
5109 UDEBUG(
"time keypoints 3D (%d) = %fs", (
int)keypoints3D.size(),
t);
5117 else if(
data.imageRaw().empty())
5119 UDEBUG(
"Empty image, cannot extract features...");
5121 else if(_feature2D->getMaxFeatures() < 0)
5123 UDEBUG(
"_feature2D->getMaxFeatures()(%d<0) so don't extract any features...", _feature2D->getMaxFeatures());
5127 UDEBUG(
"Intermediate node detected, don't extract features!");
5130 else if(_feature2D->getMaxFeatures() >= 0 && !isIntermediateNode)
5132 UINFO(
"Use odometry features: kpts=%d 3d=%d desc=%d (dim=%d, type=%d)",
5133 (
int)
data.keypoints().size(),
5134 (
int)
data.keypoints3D().size(),
5135 data.descriptors().rows,
5136 data.descriptors().cols,
5137 data.descriptors().type());
5138 keypoints =
data.keypoints();
5139 keypoints3D =
data.keypoints3D();
5140 descriptors =
data.descriptors().clone();
5142 UASSERT(descriptors.empty() || descriptors.rows == (
int)keypoints.size());
5143 UASSERT(keypoints3D.empty() || keypoints3D.size() == keypoints.size());
5145 int maxFeatures = _rawDescriptorsKept&&!pose.isNull()&&_feature2D->getMaxFeatures()>0&&_feature2D->getMaxFeatures()<_visMaxFeatures?_visMaxFeatures:_feature2D->getMaxFeatures();
5146 bool ssc = _rawDescriptorsKept&&!pose.isNull()&&_feature2D->getMaxFeatures()>0&&_feature2D->getMaxFeatures()<_visMaxFeatures?_visSSC:_feature2D->getSSC();
5147 if((
int)keypoints.size() > maxFeatures)
5149 if(
data.cameraModels().size()==1 ||
data.stereoCameraModels().size()==1)
5150 _feature2D->limitKeypoints(keypoints, keypoints3D, descriptors, maxFeatures,
data.cameraModels().size()?
data.cameraModels()[0].imageSize():
data.stereoCameraModels()[0].left().imageSize(), ssc);
5152 _feature2D->limitKeypoints(keypoints, keypoints3D, descriptors, maxFeatures);
5155 if(stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0f);
5156 UDEBUG(
"time keypoints (%d) = %fs", (
int)keypoints.size(), t);
5158 if(descriptors.empty())
5161 if(
data.imageRaw().channels() == 3)
5163 cv::cvtColor(
data.imageRaw(), imageMono, CV_BGR2GRAY);
5167 imageMono =
data.imageRaw();
5170 UASSERT_MSG(imagesRectified,
"Cannot extract descriptors on not rectified image from keypoints which assumed to be undistorted");
5171 descriptors = _feature2D->generateDescriptors(imageMono, keypoints);
5173 else if(!imagesRectified && !
data.cameraModels().empty())
5175 std::vector<cv::KeyPoint> keypointsValid;
5176 keypointsValid.reserve(keypoints.size());
5177 cv::Mat descriptorsValid;
5178 descriptorsValid.reserve(descriptors.rows);
5179 std::vector<cv::Point3f> keypoints3DValid;
5180 keypoints3DValid.reserve(keypoints3D.size());
5183 if(
data.cameraModels().size() == 1)
5185 std::vector<cv::Point2f> pointsIn, pointsOut;
5186 cv::KeyPoint::convert(keypoints,pointsIn);
5187 if(
data.cameraModels()[0].D_raw().cols == 6)
5189 #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)))
5192 cv::Mat
D(1, 4, CV_64FC1);
5193 D.at<
double>(0,0) =
data.cameraModels()[0].D_raw().at<
double>(0,0);
5194 D.at<
double>(0,1) =
data.cameraModels()[0].D_raw().at<
double>(0,1);
5195 D.at<
double>(0,2) =
data.cameraModels()[0].D_raw().at<
double>(0,4);
5196 D.at<
double>(0,3) =
data.cameraModels()[0].D_raw().at<
double>(0,5);
5197 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5198 data.cameraModels()[0].K_raw(),
5200 data.cameraModels()[0].R(),
5201 data.cameraModels()[0].P());
5205 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5206 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5211 cv::undistortPoints(pointsIn, pointsOut,
5212 data.cameraModels()[0].K_raw(),
5213 data.cameraModels()[0].D_raw(),
5214 data.cameraModels()[0].R(),
5215 data.cameraModels()[0].P());
5217 UASSERT(pointsOut.size() == keypoints.size());
5218 for(
unsigned int i=0;
i<pointsOut.size(); ++
i)
5220 if(pointsOut.at(i).x>=0 && pointsOut.at(i).x<
data.cameraModels()[0].imageWidth() &&
5221 pointsOut.at(i).y>=0 && pointsOut.at(i).y<
data.cameraModels()[0].imageHeight())
5223 keypointsValid.push_back(keypoints.at(i));
5224 keypointsValid.back().pt.x = pointsOut.at(i).x;
5225 keypointsValid.back().pt.y = pointsOut.at(i).y;
5226 descriptorsValid.push_back(descriptors.row(i));
5227 if(!keypoints3D.empty())
5229 keypoints3DValid.push_back(keypoints3D.at(i));
5236 float subImageWidth;
5237 if(!
data.imageRaw().empty())
5239 UASSERT(
int((
data.imageRaw().cols/
data.cameraModels().size())*
data.cameraModels().size()) ==
data.imageRaw().cols);
5240 subImageWidth =
data.imageRaw().cols/
data.cameraModels().size();
5245 subImageWidth =
data.cameraModels()[0].imageWidth();
5248 for(
unsigned int i=0;
i<keypoints.size(); ++
i)
5250 int cameraIndex =
int(keypoints.at(i).pt.x / subImageWidth);
5251 UASSERT_MSG(cameraIndex >= 0 && cameraIndex < (
int)
data.cameraModels().size(),
5252 uFormat(
"cameraIndex=%d, models=%d, kpt.x=%f, subImageWidth=%f (Camera model image width=%d)",
5253 cameraIndex, (
int)
data.cameraModels().size(), keypoints[i].pt.x, subImageWidth,
data.cameraModels()[0].imageWidth()).c_str());
5255 std::vector<cv::Point2f> pointsIn, pointsOut;
5256 pointsIn.push_back(cv::Point2f(keypoints.at(i).pt.x-subImageWidth*cameraIndex, keypoints.at(i).pt.y));
5257 if(
data.cameraModels()[cameraIndex].D_raw().cols == 6)
5259 #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)))
5262 cv::Mat
D(1, 4, CV_64FC1);
5263 D.at<
double>(0,0) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,0);
5264 D.at<
double>(0,1) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,1);
5265 D.at<
double>(0,2) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,4);
5266 D.at<
double>(0,3) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,5);
5267 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5268 data.cameraModels()[cameraIndex].K_raw(),
5270 data.cameraModels()[cameraIndex].R(),
5271 data.cameraModels()[cameraIndex].P());
5275 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5276 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5281 cv::undistortPoints(pointsIn, pointsOut,
5282 data.cameraModels()[cameraIndex].K_raw(),
5283 data.cameraModels()[cameraIndex].D_raw(),
5284 data.cameraModels()[cameraIndex].R(),
5285 data.cameraModels()[cameraIndex].P());
5288 if(pointsOut[0].x>=0 && pointsOut[0].x<
data.cameraModels()[cameraIndex].imageWidth() &&
5289 pointsOut[0].y>=0 && pointsOut[0].y<
data.cameraModels()[cameraIndex].imageHeight())
5291 keypointsValid.push_back(keypoints.at(i));
5292 keypointsValid.back().pt.x = pointsOut[0].x + subImageWidth*cameraIndex;
5293 keypointsValid.back().pt.y = pointsOut[0].y;
5294 descriptorsValid.push_back(descriptors.row(i));
5295 if(!keypoints3D.empty())
5297 keypoints3DValid.push_back(keypoints3D.at(i));
5303 keypoints = keypointsValid;
5304 descriptors = descriptorsValid;
5305 keypoints3D = keypoints3DValid;
5308 if(stats)
stats->addStatistic(Statistics::kTimingMemRectification(), t*1000.0f);
5309 UDEBUG(
"time rectification = %fs", t);
5312 if(stats)
stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0f);
5313 UDEBUG(
"time descriptors (%d) = %fs", descriptors.rows, t);
5315 if(keypoints3D.empty() &&
5316 ((!
data.depthRaw().empty() &&
data.cameraModels().size() &&
data.cameraModels()[0].isValidForProjection()) ||
5317 (!
data.rightRaw().empty() &&
data.stereoCameraModels().size() &&
data.stereoCameraModels()[0].isValidForProjection())))
5319 keypoints3D = _feature2D->generateKeypoints3D(data, keypoints);
5321 if(_feature2D->getMinDepth() > 0.0f || _feature2D->getMaxDepth() > 0.0f)
5323 _feature2D->filterKeypointsByDepth(keypoints, descriptors, keypoints3D, _feature2D->getMinDepth(), _feature2D->getMaxDepth());
5326 if(stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_3D(), t*1000.0f);
5327 UDEBUG(
"time keypoints 3D (%d) = %fs", (
int)keypoints3D.size(), t);
5329 UDEBUG(
"ratio=%f, meanWordsPerLocation=%d", _badSignRatio, meanWordsPerLocation);
5330 if(descriptors.rows && descriptors.rows < _badSignRatio *
float(meanWordsPerLocation))
5332 descriptors = cv::Mat();
5338 UDEBUG(
"Joining dictionary update thread...");
5339 preUpdateThread.join();
5340 UDEBUG(
"Joining dictionary update thread... thread finished!");
5344 if(stats)
stats->addStatistic(Statistics::kTimingMemJoining_dictionary_update(), t*1000.0f);
5347 UDEBUG(
"time descriptor and memory update (%d of size=%d) = %fs", descriptors.rows, descriptors.cols, t);
5351 UDEBUG(
"time descriptor (%d of size=%d) = %fs", descriptors.rows, descriptors.cols, t);
5354 std::list<int> wordIds;
5355 if(descriptors.rows)
5359 std::vector<bool> inliers;
5360 cv::Mat descriptorsForQuantization = descriptors;
5361 std::vector<int> quantizedToRawIndices;
5362 if(_feature2D->getMaxFeatures()>0 && descriptors.rows > _feature2D->getMaxFeatures())
5364 UASSERT((
int)keypoints.size() == descriptors.rows);
5365 int inliersCount = 0;
5366 if((_feature2D->getGridRows() > 1 || _feature2D->getGridCols() > 1) &&
5367 (decimatedData.cameraModels().size()==1 || decimatedData.stereoCameraModels().size()==1 ||
5368 data.cameraModels().size()==1 ||
data.stereoCameraModels().size()==1))
5370 Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures(),
5371 decimatedData.cameraModels().size()?decimatedData.cameraModels()[0].imageSize():
5372 decimatedData.stereoCameraModels().size()?decimatedData.stereoCameraModels()[0].left().imageSize():
5373 data.cameraModels().size()?
data.cameraModels()[0].imageSize():
data.stereoCameraModels()[0].left().imageSize(),
5374 _feature2D->getGridRows(), _feature2D->getGridCols(), _feature2D->getSSC());
5378 if(_feature2D->getGridRows() > 1 || _feature2D->getGridCols() > 1)
5380 UWARN(
"Ignored %s and %s parameters as they cannot be used for multi-cameras setup or uncalibrated camera.",
5381 Parameters::kKpGridCols().
c_str(), Parameters::kKpGridRows().
c_str());
5383 if(decimatedData.cameraModels().size()==1 || decimatedData.stereoCameraModels().size()==1 ||
5384 data.cameraModels().size()==1 ||
data.stereoCameraModels().size()==1)
5386 Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures(),
5387 decimatedData.cameraModels().size()?decimatedData.cameraModels()[0].imageSize():
5388 decimatedData.stereoCameraModels().size()?decimatedData.stereoCameraModels()[0].left().imageSize():
5389 data.cameraModels().size()?
data.cameraModels()[0].imageSize():
data.stereoCameraModels()[0].left().imageSize(),
5390 _feature2D->getSSC());
5394 Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures());
5397 for(
size_t i=0;
i<inliers.size(); ++
i)
5403 descriptorsForQuantization = cv::Mat(inliersCount, descriptors.cols, descriptors.type());
5404 quantizedToRawIndices.resize(inliersCount);
5406 UASSERT((
int)inliers.size() == descriptors.rows);
5407 for(
int k=0; k < descriptors.rows; ++k)
5411 UASSERT(oi < quantizedToRawIndices.size());
5412 if(descriptors.type() == CV_32FC1)
5414 memcpy(descriptorsForQuantization.ptr<
float>(oi), descriptors.ptr<
float>(k), descriptors.cols*
sizeof(
float));
5418 memcpy(descriptorsForQuantization.ptr<
char>(oi), descriptors.ptr<
char>(k), descriptors.cols*
sizeof(
char));
5420 quantizedToRawIndices[oi] = k;
5425 uFormat(
"oi=%d inliersCount=%d (maxFeatures=%d, grid=%dx%d)",
5426 oi, inliersCount, _feature2D->getMaxFeatures(), _feature2D->getGridCols(), _feature2D->getGridRows()).c_str());
5430 wordIds = _vwd->addNewWords(descriptorsForQuantization,
id);
5433 if(wordIds.size() < keypoints.size())
5435 std::vector<int> allWordIds;
5436 allWordIds.resize(keypoints.size(),-1);
5438 for(std::list<int>::iterator
iter=wordIds.begin();
iter!=wordIds.end(); ++
iter)
5440 allWordIds[quantizedToRawIndices[
i]] = *
iter;
5444 for(i=0;
i<(
int)allWordIds.size(); ++
i)
5446 if(allWordIds[i] < 0)
5448 allWordIds[
i] = negIndex--;
5455 if(stats)
stats->addStatistic(Statistics::kTimingMemAdd_new_words(), t*1000.0f);
5456 UDEBUG(
"time addNewWords %fs indexed=%d not=%d", t, _vwd->getIndexedWordsCount(), _vwd->getNotIndexedWordsCount());
5460 UDEBUG(
"id %d is a bad signature",
id);
5463 std::multimap<int, int> words;
5464 std::vector<cv::KeyPoint> wordsKpts;
5465 std::vector<cv::Point3f> words3D;
5466 cv::Mat wordsDescriptors;
5467 int words3DValid = 0;
5468 if(wordIds.size() > 0)
5470 UASSERT(wordIds.size() == keypoints.size());
5471 UASSERT(keypoints3D.size() == 0 || keypoints3D.size() == wordIds.size());
5473 float decimationRatio =
float(preDecimation) /
float(_imagePostDecimation);
5474 double log2value =
log(
double(preDecimation))/
log(2.0);
5475 for(std::list<int>::iterator
iter=wordIds.begin();
iter!=wordIds.end() && i < keypoints.size(); ++
iter, ++i)
5477 cv::KeyPoint kpt = keypoints[
i];
5478 if(preDecimation != _imagePostDecimation)
5481 kpt.pt.x *= decimationRatio;
5482 kpt.pt.y *= decimationRatio;
5483 kpt.size *= decimationRatio;
5484 kpt.octave += log2value;
5486 words.insert(std::make_pair(*
iter, words.size()));
5487 wordsKpts.push_back(kpt);
5489 if(keypoints3D.size())
5491 words3D.push_back(keypoints3D.at(i));
5492 if(util3d::isFinite(keypoints3D.at(i)))
5497 if(_rawDescriptorsKept)
5499 wordsDescriptors.push_back(descriptors.row(i));
5505 if(!landmarks.empty() && isIntermediateNode)
5507 UDEBUG(
"Landmarks provided (size=%ld) are ignored because this signature is set as intermediate.", landmarks.size());
5510 else if(_detectMarkers && !isIntermediateNode && !
data.imageRaw().empty())
5512 UDEBUG(
"Detecting markers...");
5513 if(landmarks.empty())
5515 std::vector<CameraModel> models =
data.cameraModels();
5518 for(
size_t i=0;
i<
data.stereoCameraModels().
size(); ++
i)
5520 models.push_back(
data.stereoCameraModels()[i].left());
5524 if(!models.empty() && models[0].isValidForProjection())
5526 std::map<int, MarkerInfo> markers = _markerDetector->detect(
data.imageRaw(), models,
data.depthRaw(), _landmarksSize);
5528 for(std::map<int, MarkerInfo>::iterator
iter=markers.begin();
iter!=markers.end(); ++
iter)
5530 if(
iter->first <= 0)
5532 UERROR(
"Invalid marker received! IDs should be > 0 (it is %d). Ignoring this marker.",
iter->first);
5535 cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1);
5536 covariance(cv::Range(0,3), cv::Range(0,3)) *= _markerLinVariance;
5537 covariance(cv::Range(3,6), cv::Range(3,6)) *= _markerAngVariance;
5538 landmarks.insert(std::make_pair(
iter->first, Landmark(
iter->first,
iter->second.length(),
iter->second.pose(), covariance)));
5540 UDEBUG(
"Markers detected = %d", (
int)markers.size());
5544 UWARN(
"No valid camera calibration for marker detection");
5549 UWARN(
"Input data has already landmarks, cannot do marker detection.");
5552 if(stats)
stats->addStatistic(Statistics::kTimingMemMarkers_detection(), t*1000.0f);
5553 UDEBUG(
"time markers detection = %fs", t);
5556 cv::Mat image =
data.imageRaw();
5557 cv::Mat depthOrRightImage =
data.depthOrRightRaw();
5558 std::vector<CameraModel> cameraModels =
data.cameraModels();
5559 std::vector<StereoCameraModel> stereoCameraModels =
data.stereoCameraModels();
5562 if(_imagePostDecimation > 1 && !isIntermediateNode)
5564 if(_imagePostDecimation == preDecimation && decimatedData.isValid())
5566 image = decimatedData.imageRaw();
5567 depthOrRightImage = decimatedData.depthOrRightRaw();
5568 cameraModels = decimatedData.cameraModels();
5569 stereoCameraModels = decimatedData.stereoCameraModels();
5573 int decimationDepth = _imagePreDecimation;
5574 if( !
data.cameraModels().empty() &&
5575 data.cameraModels()[0].imageHeight()>0 &&
5576 data.cameraModels()[0].imageWidth()>0)
5579 int targetSize =
data.cameraModels()[0].imageHeight() / _imagePreDecimation;
5580 if(targetSize >=
data.depthRaw().rows)
5582 decimationDepth = 1;
5586 decimationDepth = (
int)
ceil(
float(
data.depthRaw().rows) /
float(targetSize));
5589 UDEBUG(
"decimation rgbOrLeft(rows=%d)=%d, depthOrRight(rows=%d)=%d",
data.imageRaw().rows, _imagePostDecimation,
data.depthOrRightRaw().rows, decimationDepth);
5593 for(
unsigned int i=0;
i<cameraModels.size(); ++
i)
5595 cameraModels[
i] = cameraModels[
i].scaled(1.0/
double(_imagePostDecimation));
5597 for(
unsigned int i=0;
i<stereoCameraModels.size(); ++
i)
5599 stereoCameraModels[
i].scale(1.0/
double(_imagePostDecimation));
5603 if(!image.empty() && (depthOrRightImage.cols > image.cols || depthOrRightImage.rows > image.rows))
5605 UWARN(
"Depth image is bigger than RGB image after post decimation, %s=%d is too high! RGB=%dx%d, depth=%dx%d",
5606 Parameters::kMemImagePostDecimation().
c_str(), _imagePostDecimation,
5607 image.cols, image.rows, depthOrRightImage.cols, depthOrRightImage.rows);
5611 if(stats)
stats->addStatistic(Statistics::kTimingMemPost_decimation(), t*1000.0f);
5612 UDEBUG(
"time post-decimation = %fs", t);
5615 if(_stereoFromMotion &&
5617 cameraModels.size() == 1 &&
5619 (words3D.size() == 0 || (words.size() == words3D.size() && words3DValid!=(
int)words3D.size())) &&
5620 _registrationPipeline->isImageRequired() &&
5621 _signatures.size() &&
5622 _signatures.rbegin()->second->mapId() == _idMapCount)
5624 UDEBUG(
"Generate 3D words using odometry (%s=true and words3DValid=%d/%d)",
5625 Parameters::kMemStereoFromMotion().
c_str(), words3DValid, (
int)words3D.size());
5626 Signature * previousS = _signatures.rbegin()->second;
5627 if(previousS->getWords().size() > 8 && words.size() > 8 && !previousS->getPose().isNull())
5629 UDEBUG(
"Previous pose(%d) = %s", previousS->id(), previousS->getPose().prettyPrint().c_str());
5630 UDEBUG(
"Current pose(%d) = %s",
id, pose.prettyPrint().c_str());
5631 Transform cameraTransform = pose.inverse() * previousS->getPose();
5633 Signature cpPrevious(2);
5636 std::vector<cv::KeyPoint> uniqueWordsKpts;
5637 cv::Mat uniqueWordsDescriptors;
5638 std::multimap<int, int> uniqueWords;
5639 for(std::map<int, int>::iterator
iter=uniqueWordsOld.begin();
iter!=uniqueWordsOld.end(); ++
iter)
5641 uniqueWords.insert(std::make_pair(
iter->first, uniqueWords.size()));
5642 uniqueWordsKpts.push_back(previousS->getWordsKpts()[
iter->second]);
5643 uniqueWordsDescriptors.push_back(previousS->getWordsDescriptors().row(
iter->second));
5645 cpPrevious.sensorData().setCameraModels(previousS->sensorData().cameraModels());
5646 cpPrevious.setWords(uniqueWords, uniqueWordsKpts, std::vector<cv::Point3f>(), uniqueWordsDescriptors);
5647 Signature cpCurrent(1);
5649 uniqueWordsKpts.clear();
5650 uniqueWordsDescriptors = cv::Mat();
5651 uniqueWords.clear();
5652 for(std::map<int, int>::iterator
iter=uniqueWordsOld.begin();
iter!=uniqueWordsOld.end(); ++
iter)
5654 uniqueWords.insert(std::make_pair(
iter->first, uniqueWords.size()));
5655 uniqueWordsKpts.push_back(wordsKpts[
iter->second]);
5656 uniqueWordsDescriptors.push_back(wordsDescriptors.row(
iter->second));
5658 cpCurrent.sensorData().setCameraModels(cameraModels);
5660 cpCurrent.setWords(uniqueWords, uniqueWordsKpts, std::vector<cv::Point3f>(), uniqueWordsDescriptors);
5664 RegistrationVis reg(parameters_);
5665 if(_registrationPipeline->isScanRequired())
5668 RegistrationVis vis(parameters_);
5669 tmpt = vis.computeTransformationMod(cpCurrent, cpPrevious, cameraTransform);
5673 tmpt = _registrationPipeline->computeTransformationMod(cpCurrent, cpPrevious, cameraTransform);
5675 UDEBUG(
"t=%s", tmpt.prettyPrint().c_str());
5680 std::map<int, cv::KeyPoint> currentWords;
5681 std::map<int, cv::KeyPoint> previousWords;
5682 for(std::map<int, int>::iterator
iter=currentUniqueWords.begin();
iter!=currentUniqueWords.end(); ++
iter)
5684 currentWords.insert(std::make_pair(
iter->first, cpCurrent.getWordsKpts()[
iter->second]));
5686 for(std::map<int, int>::iterator
iter=previousUniqueWords.begin();
iter!=previousUniqueWords.end(); ++
iter)
5688 previousWords.insert(std::make_pair(
iter->first, cpPrevious.getWordsKpts()[
iter->second]));
5696 UDEBUG(
"inliers=%d", (
int)inliers.size());
5699 float bad_point = std::numeric_limits<float>::quiet_NaN ();
5700 UASSERT(words3D.size() == 0 || words.size() == words3D.size());
5701 bool words3DWasEmpty = words3D.empty();
5702 int added3DPointsWithoutDepth = 0;
5703 for(std::multimap<int, int>::const_iterator
iter=words.begin();
iter!=words.end(); ++
iter)
5705 std::map<int, cv::Point3f>::iterator jter=inliers.find(
iter->first);
5708 if(jter != inliers.end())
5710 words3D.push_back(jter->second);
5711 ++added3DPointsWithoutDepth;
5715 words3D.push_back(cv::Point3f(bad_point,bad_point,bad_point));
5718 else if(!util3d::isFinite(words3D[
iter->second]) && jter != inliers.end())
5720 words3D[
iter->second] = jter->second;
5721 ++added3DPointsWithoutDepth;
5724 UDEBUG(
"added3DPointsWithoutDepth=%d", added3DPointsWithoutDepth);
5725 if(stats)
stats->addStatistic(Statistics::kMemoryTriangulated_points(), (
float)added3DPointsWithoutDepth);
5728 UASSERT(words3D.size() == words.size());
5729 if(stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_3D_motion(), t*1000.0f);
5730 UDEBUG(
"time keypoints 3D by motion (%d) = %fs", (
int)words3D.size(), t);
5735 LaserScan laserScan =
data.laserScanRaw();
5736 if(!isIntermediateNode && laserScan.size())
5738 if(laserScan.rangeMax() == 0.0f)
5740 bool id2d = laserScan.is2d();
5741 float maxRange = 0.0f;
5742 for(
int i=0;
i<laserScan.size(); ++
i)
5744 const float * ptr = laserScan.data().ptr<
float>(0,
i);
5748 r = ptr[0]*ptr[0] + ptr[1]*ptr[1];
5752 r = ptr[0]*ptr[0] + ptr[1]*ptr[1] + ptr[2]*ptr[2];
5761 laserScan=LaserScan(laserScan.data(), laserScan.maxPoints(),
sqrt(maxRange), laserScan.format(), laserScan.localTransform());
5766 _laserScanDownsampleStepSize,
5769 _laserScanVoxelSize,
5771 _laserScanNormalRadius,
5772 _laserScanGroundNormalsUp);
5774 if(stats)
stats->addStatistic(Statistics::kTimingMemScan_filtering(), t*1000.0f);
5775 UDEBUG(
"time normals scan = %fs", t);
5779 if(this->isBinDataKept() && (!isIntermediateNode || _saveIntermediateNodeData))
5781 UDEBUG(
"Bin data kept: rgb=%d, depth=%d, scan=%d, userData=%d",
5783 depthOrRightImage.empty()?0:1,
5784 laserScan.isEmpty()?0:1,
5785 data.userDataRaw().empty()?0:1);
5787 std::vector<unsigned char> imageBytes;
5788 std::vector<unsigned char> depthBytes;
5790 if(_saveDepth16Format && !depthOrRightImage.empty() && depthOrRightImage.type() == CV_32FC1)
5792 UWARN(
"Save depth data to 16 bits format: depth type detected is 32FC1, use 16UC1 depth format to avoid this conversion (or set parameter \"Mem/SaveDepth16Format\"=false to use 32bits format).");
5796 cv::Mat compressedImage;
5797 cv::Mat compressedDepth;
5798 cv::Mat compressedScan;
5799 cv::Mat compressedUserData;
5800 if(_compressionParallelized)
5803 rtabmap::CompressionThread ctDepth(depthOrRightImage, depthOrRightImage.type() == CV_32FC1 || depthOrRightImage.type() == CV_16UC1?std::string(
".png"):_rgbCompressionFormat);
5810 if(!depthOrRightImage.empty())
5814 if(!laserScan.isEmpty())
5816 ctLaserScan.start();
5818 if(!
data.userDataRaw().empty())
5827 compressedImage = ctImage.getCompressedData();
5828 compressedDepth = ctDepth.getCompressedData();
5829 compressedScan = ctLaserScan.getCompressedData();
5830 compressedUserData = ctUserData.getCompressedData();
5835 compressedDepth =
compressImage2(depthOrRightImage, depthOrRightImage.type() == CV_32FC1 || depthOrRightImage.type() == CV_16UC1?std::string(
".png"):_rgbCompressionFormat);
5840 s =
new Signature(
id,
5842 isIntermediateNode?-1:0,
5847 !stereoCameraModels.empty()?
5849 laserScan.angleIncrement() == 0.0f?
5850 LaserScan(compressedScan,
5851 laserScan.maxPoints(),
5852 laserScan.rangeMax(),
5854 laserScan.localTransform()):
5855 LaserScan(compressedScan,
5857 laserScan.rangeMin(),
5858 laserScan.rangeMax(),
5859 laserScan.angleMin(),
5860 laserScan.angleMax(),
5861 laserScan.angleIncrement(),
5862 laserScan.localTransform()),
5868 compressedUserData):
5870 laserScan.angleIncrement() == 0.0f?
5871 LaserScan(compressedScan,
5872 laserScan.maxPoints(),
5873 laserScan.rangeMax(),
5875 laserScan.localTransform()):
5876 LaserScan(compressedScan,
5878 laserScan.rangeMin(),
5879 laserScan.rangeMax(),
5880 laserScan.angleMin(),
5881 laserScan.angleMax(),
5882 laserScan.angleIncrement(),
5883 laserScan.localTransform()),
5889 compressedUserData));
5893 UDEBUG(
"Bin data kept: scan=%d, userData=%d",
5894 laserScan.isEmpty()?0:1,
5895 data.userDataRaw().empty()?0:1);
5898 cv::Mat compressedScan;
5899 cv::Mat compressedUserData;
5900 if(_compressionParallelized)
5904 if(!
data.userDataRaw().empty() && !isIntermediateNode)
5908 if(!laserScan.isEmpty() && !isIntermediateNode)
5910 ctLaserScan.start();
5915 compressedScan = ctLaserScan.getCompressedData();
5916 compressedUserData = ctUserData.getCompressedData();
5924 s =
new Signature(
id,
5926 isIntermediateNode?-1:0,
5931 !stereoCameraModels.empty()?
5933 laserScan.angleIncrement() == 0.0f?
5934 LaserScan(compressedScan,
5935 laserScan.maxPoints(),
5936 laserScan.rangeMax(),
5938 laserScan.localTransform()):
5939 LaserScan(compressedScan,
5941 laserScan.rangeMin(),
5942 laserScan.rangeMax(),
5943 laserScan.angleMin(),
5944 laserScan.angleMax(),
5945 laserScan.angleIncrement(),
5946 laserScan.localTransform()),
5952 compressedUserData):
5954 laserScan.angleIncrement() == 0.0f?
5955 LaserScan(compressedScan,
5956 laserScan.maxPoints(),
5957 laserScan.rangeMax(),
5959 laserScan.localTransform()):
5960 LaserScan(compressedScan,
5962 laserScan.rangeMin(),
5963 laserScan.rangeMax(),
5964 laserScan.angleMin(),
5965 laserScan.angleMax(),
5966 laserScan.angleIncrement(),
5967 laserScan.localTransform()),
5973 compressedUserData));
5976 s->setWords(words, wordsKpts,
5977 _reextractLoopClosureFeatures?std::vector<cv::Point3f>():words3D,
5978 _reextractLoopClosureFeatures?cv::Mat():wordsDescriptors);
5981 if(!cameraModels.empty())
5983 s->sensorData().setRGBDImage(image, depthOrRightImage, cameraModels,
false);
5987 s->sensorData().setStereoImage(image, depthOrRightImage, stereoCameraModels,
false);
5989 s->sensorData().setLaserScan(laserScan,
false);
5990 s->sensorData().setUserData(
data.userDataRaw(),
false);
5992 UDEBUG(
"data.groundTruth() =%s",
data.groundTruth().prettyPrint().c_str());
5993 UDEBUG(
"data.gps() =%s",
data.gps().stamp()?
"true":
"false");
5994 UDEBUG(
"data.envSensors() =%d", (
int)
data.envSensors().size());
5995 UDEBUG(
"data.globalDescriptors()=%d", (
int)
data.globalDescriptors().size());
5996 s->sensorData().setGroundTruth(
data.groundTruth());
5997 s->sensorData().setGPS(
data.gps());
5998 s->sensorData().setEnvSensors(
data.envSensors());
6000 if(!isIntermediateNode)
6002 std::vector<GlobalDescriptor> globalDescriptors =
data.globalDescriptors();
6003 if(_globalDescriptorExtractor)
6005 GlobalDescriptor gdescriptor = _globalDescriptorExtractor->extract(inputData);
6006 if(!gdescriptor.data().empty())
6008 globalDescriptors.push_back(gdescriptor);
6011 s->sensorData().setGlobalDescriptors(globalDescriptors);
6013 else if(!
data.globalDescriptors().empty())
6015 UDEBUG(
"Global descriptors provided (size=%ld) are ignored because this signature is set as intermediate.",
data.globalDescriptors().size());
6019 if(stats)
stats->addStatistic(Statistics::kTimingMemCompressing_data(), t*1000.0f);
6020 UDEBUG(
"time compressing data (id=%d) %fs",
id, t);
6023 s->setEnabled(
true);
6027 if(_createOccupancyGrid && !isIntermediateNode)
6029 if( (_localMapMaker->isGridFromDepth() && !
data.depthOrRightRaw().empty()) ||
6030 (!_localMapMaker->isGridFromDepth() && !
data.laserScanRaw().empty()))
6032 cv::Mat ground, obstacles,
empty;
6033 float cellSize = 0.0f;
6034 cv::Point3f viewPoint(0,0,0);
6035 _localMapMaker->createLocalMap(*s, ground, obstacles,
empty, viewPoint);
6036 cellSize = _localMapMaker->getCellSize();
6037 s->sensorData().setOccupancyGrid(ground, obstacles,
empty, cellSize, viewPoint);
6040 if(stats)
stats->addStatistic(Statistics::kTimingMemOccupancy_grid(), t*1000.0f);
6041 UDEBUG(
"time grid map = %fs", t);
6043 else if(
data.gridCellSize() != 0.0f)
6045 s->sensorData().setOccupancyGrid(
6046 data.gridGroundCellsRaw(),
6047 data.gridObstacleCellsRaw(),
6048 data.gridEmptyCellsRaw(),
6049 data.gridCellSize(),
6050 data.gridViewPoint());
6055 if(!
data.globalPose().isNull() &&
data.globalPoseCovariance().cols==6 &&
data.globalPoseCovariance().rows==6 &&
data.globalPoseCovariance().cols==CV_64FC1)
6057 s->addLink(Link(
s->id(),
s->id(), Link::kPosePrior,
data.globalPose(),
data.globalPoseCovariance().inv()));
6058 UDEBUG(
"Added global pose prior: %s",
data.globalPose().prettyPrint().c_str());
6060 if(
data.gps().stamp() > 0.0)
6062 UWARN(
"GPS constraint ignored as global pose is also set.");
6065 else if(
data.gps().stamp() > 0.0)
6072 data.gps().error() > 0.0)
6074 if(_gpsOrigin.stamp() <= 0.0)
6076 _gpsOrigin =
data.gps();
6077 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());
6079 cv::Point3f pt =
data.gps().toGeodeticCoords().toENU_WGS84(_gpsOrigin.toGeodeticCoords());
6080 Transform gpsPose(pt.x, pt.y, pose.z(), 0, 0, -(
data.gps().bearing()-90.0)*
M_PI/180.0);
6081 cv::Mat gpsInfMatrix = cv::Mat::eye(6,6,CV_64FC1)/9999.0;
6083 UDEBUG(
"Added GPS prior: x=%f y=%f z=%f yaw=%f", gpsPose.x(), gpsPose.y(), gpsPose.z(), gpsPose.theta());
6085 gpsInfMatrix.at<
double>(0,0) = gpsInfMatrix.at<
double>(1,1) = 1.0/
data.gps().error();
6086 gpsInfMatrix.at<
double>(2,2) = 1;
6087 s->addLink(Link(
s->id(),
s->id(), Link::kPosePrior, gpsPose, gpsInfMatrix));
6091 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());
6096 if(_useOdometryGravity && !pose.isNull())
6098 s->addLink(Link(
s->id(),
s->id(), Link::kGravity, pose.rotation()));
6099 UDEBUG(
"Added gravity constraint from odom pose: %s", pose.rotation().prettyPrint().c_str());
6101 else if(!
data.imu().localTransform().isNull() &&
6102 (
data.imu().orientation()[0] != 0 ||
6103 data.imu().orientation()[1] != 0 ||
6104 data.imu().orientation()[2] != 0 ||
6105 data.imu().orientation()[3] != 0))
6108 Transform
orientation(0,0,0,
data.imu().orientation()[0],
data.imu().orientation()[1],
data.imu().orientation()[2],
data.imu().orientation()[3]);
6117 for(Landmarks::const_iterator
iter = landmarks.begin();
iter!=landmarks.end(); ++
iter)
6119 if(
iter->second.id() > 0)
6121 int landmarkId = -
iter->first;
6122 cv::Mat landmarkSize;
6123 if(
iter->second.size() > 0.0f)
6125 landmarkSize = cv::Mat(1,1,CV_32FC1);
6126 landmarkSize.at<
float>(0,0) =
iter->second.size();
6128 std::pair<std::map<int, float>::iterator,
bool> inserted=_landmarksSize.insert(std::make_pair(
iter->first,
iter->second.size()));
6129 if(!inserted.second)
6131 if(inserted.first->second != landmarkSize.at<
float>(0,0))
6133 UWARN(
"Trying to update landmark size buffer for landmark %d with size=%f but "
6134 "it has already a different size set. Keeping old size (%f).",
6135 -landmarkId, inserted.first->second, landmarkSize.at<
float>(0,0));
6141 Transform landmarkPose =
iter->second.pose();
6142 if(_registrationPipeline->force3DoF())
6147 if(
fabs(tx.
z()) > 0.9)
6151 else if(
fabs(ty.
z()) > 0.9)
6157 Link landmark(
s->id(), landmarkId, Link::kLandmark, landmarkPose,
iter->second.covariance().inv(), landmarkSize);
6158 s->addLandmark(landmark);
6161 std::map<int, std::set<int> >
::iterator nter = _landmarksIndex.find(landmarkId);
6162 if(nter!=_landmarksIndex.end())
6164 nter->second.insert(
s->id());
6169 tmp.insert(
s->id());
6170 _landmarksIndex.insert(std::make_pair(landmarkId, tmp));
6175 UERROR(
"Invalid landmark received! IDs should be > 0 (it is %d). Ignoring this landmark.",
iter->second.id());
6182 void Memory::disableWordsRef(
int signatureId)
6184 UDEBUG(
"id=%d", signatureId);
6186 Signature * ss = this->_getSignature(signatureId);
6189 const std::multimap<int, int> & words = ss->
getWords();
6191 int count = _vwd->getTotalActiveReferences();
6193 for(std::list<int>::const_iterator
i=
keys.begin();
i!=
keys.end(); ++
i)
6195 _vwd->removeAllWordRef(*
i, signatureId);
6198 count -= _vwd->getTotalActiveReferences();
6200 UDEBUG(
"%d words total ref removed from signature %d... (total active ref = %d)",
count, ss->
id(), _vwd->getTotalActiveReferences());
6204 void Memory::cleanUnusedWords()
6206 std::vector<VisualWord*> removedWords = _vwd->getUnusedWords();
6207 UDEBUG(
"Removing %d words (dictionary size=%d)...", removedWords.size(), _vwd->getVisualWords().size());
6208 if(removedWords.size())
6211 _vwd->removeWords(removedWords);
6213 for(
unsigned int i=0;
i<removedWords.size(); ++
i)
6217 _dbDriver->asyncSave(removedWords[
i]);
6221 delete removedWords[
i];
6227 void Memory::enableWordsRef(
const std::list<int> & signatureIds)
6229 UDEBUG(
"size=%d", signatureIds.size());
6233 std::map<int, int> refsToChange;
6235 std::set<int> oldWordIds;
6236 std::list<Signature *> surfSigns;
6237 for(std::list<int>::const_iterator
i=signatureIds.begin();
i!=signatureIds.end(); ++
i)
6242 surfSigns.push_back(ss);
6246 for(std::list<int>::const_iterator k=uniqueKeys.begin(); k!=uniqueKeys.end(); ++k)
6248 if(*k>0 && _vwd->getWord(*k) == 0 && _vwd->getUnusedWord(*k) == 0)
6250 oldWordIds.insert(oldWordIds.end(), *k);
6256 if(!_vwd->isIncremental() && oldWordIds.size())
6258 UWARN(
"Dictionary is fixed, but some words retrieved have not been found!?");
6261 UDEBUG(
"oldWordIds.size()=%d, getOldIds time=%fs", oldWordIds.size(),
timer.ticks());
6264 std::list<VisualWord *> vws;
6265 if(oldWordIds.size() && _dbDriver)
6268 _dbDriver->loadWords(oldWordIds, vws);
6270 UDEBUG(
"loading words(%d) time=%fs", oldWordIds.size(),
timer.ticks());
6276 std::vector<int> vwActiveIds = _vwd->findNN(vws);
6277 UDEBUG(
"find active ids (number=%d) time=%fs", vws.size(),
timer.ticks());
6279 for(std::list<VisualWord *>::iterator iterVws=vws.begin(); iterVws!=vws.end(); ++iterVws)
6281 if(vwActiveIds[
i] > 0)
6284 refsToChange.insert(refsToChange.end(), std::pair<int, int>((*iterVws)->id(), vwActiveIds[
i]));
6285 if((*iterVws)->isSaved())
6291 _dbDriver->asyncSave(*iterVws);
6297 _vwd->addWord(*iterVws);
6301 UDEBUG(
"Added %d to dictionary, time=%fs", vws.size()-refsToChange.size(),
timer.ticks());
6304 for(std::map<int, int>::const_iterator
iter=refsToChange.begin();
iter != refsToChange.end(); ++
iter)
6307 for(std::list<Signature *>::iterator
j=surfSigns.begin();
j!=surfSigns.end(); ++
j)
6309 (*j)->changeWordsRef(
iter->first,
iter->second);
6312 UDEBUG(
"changing ref, total=%d, time=%fs", refsToChange.size(),
timer.ticks());
6315 int count = _vwd->getTotalActiveReferences();
6318 for(std::list<Signature *>::iterator
j=surfSigns.begin();
j!=surfSigns.end(); ++
j)
6320 const std::vector<int> &
keys =
uKeys((*j)->getWords());
6324 for(
unsigned int i=0;
i<
keys.size(); ++
i)
6328 _vwd->addWordRef(
keys.at(
i), (*j)->id());
6331 (*j)->setEnabled(
true);
6335 count = _vwd->getTotalActiveReferences() -
count;
6336 UDEBUG(
"%d words total ref added from %d signatures, time=%fs...",
count, surfSigns.size(),
timer.ticks());
6339 std::set<int> Memory::reactivateSignatures(
const std::list<int> & ids,
unsigned int maxLoaded,
double & timeDbAccess)
6347 std::list<int> idsToLoad;
6348 std::map<int, int>::iterator wmIter;
6349 for(std::list<int>::const_iterator
i=ids.begin();
i!=ids.end(); ++
i)
6351 if(!this->getSignature(*
i) && !
uContains(idsToLoad, *
i))
6353 if(!maxLoaded || idsToLoad.size() < maxLoaded)
6355 idsToLoad.push_back(*
i);
6356 UINFO(
"Loading location %d from database...", *
i);
6361 UDEBUG(
"idsToLoad = %d", idsToLoad.size());
6363 std::list<Signature *> reactivatedSigns;
6366 _dbDriver->loadSignatures(idsToLoad, reactivatedSigns);
6368 timeDbAccess =
timer.getElapsedTime();
6369 std::list<int> idsLoaded;
6370 for(std::list<Signature *>::iterator
i=reactivatedSigns.begin();
i!=reactivatedSigns.end(); ++
i)
6372 if(!(*i)->getLandmarks().empty())
6375 for(std::map<int, Link>::const_iterator
iter = (*i)->getLandmarks().begin();
iter!=(*i)->getLandmarks().end(); ++
iter)
6377 int landmarkId =
iter->first;
6380 cv::Mat landmarkSize =
iter->second.uncompressUserDataConst();
6381 if(!landmarkSize.empty() && landmarkSize.type() == CV_32FC1 && landmarkSize.total()==1)
6383 std::pair<std::map<int, float>::iterator,
bool> inserted=_landmarksSize.insert(std::make_pair(-landmarkId, landmarkSize.at<
float>(0,0)));
6384 if(!inserted.second)
6386 if(inserted.first->second != landmarkSize.at<
float>(0,0))
6388 UWARN(
"Trying to update landmark size buffer for landmark %d with size=%f but "
6389 "it has already a different size set. Keeping old size (%f).",
6390 -landmarkId, inserted.first->second, landmarkSize.at<
float>(0,0));
6395 std::map<int, std::set<int> >
::iterator nter = _landmarksIndex.find(landmarkId);
6396 if(nter!=_landmarksIndex.end())
6398 nter->second.insert((*i)->id());
6403 tmp.insert((*i)->id());
6404 _landmarksIndex.insert(std::make_pair(landmarkId, tmp));
6409 idsLoaded.push_back((*i)->id());
6411 this->addSignatureToWmFromLTM(*
i);
6413 this->enableWordsRef(idsLoaded);
6415 return std::set<int>(idsToLoad.begin(), idsToLoad.end());
6420 void Memory::getMetricConstraints(
6421 const std::set<int> & ids,
6422 std::map<int, Transform> & poses,
6423 std::multimap<int, Link> & links,
6424 bool lookInDatabase,
6425 bool landmarksAdded)
6428 for(std::set<int>::const_iterator
iter=ids.begin();
iter!=ids.end(); ++
iter)
6433 poses.insert(std::make_pair(*
iter, pose));
6437 for(std::set<int>::const_iterator
iter=ids.begin();
iter!=ids.end(); ++
iter)
6441 std::multimap<int, Link> tmpLinks = getLinks(*
iter, lookInDatabase,
true);
6442 for(std::multimap<int, Link>::iterator jter=tmpLinks.begin(); jter!=tmpLinks.end(); ++jter)
6444 std::multimap<int, Link>::iterator addedLinksIterator =
graph::findLink(links, *
iter, jter->first);
6445 if( jter->second.isValid() &&
6446 (addedLinksIterator == links.end() || addedLinksIterator->second.from()==addedLinksIterator->second.to()) &&
6447 (
uContains(poses, jter->first) || (landmarksAdded && jter->second.type() == Link::kLandmark)))
6449 if(!lookInDatabase &&
6450 (jter->second.type() == Link::kNeighbor ||
6451 jter->second.type() == Link::kNeighborMerged))
6453 const Signature *
s = this->getSignature(jter->first);
6455 if(
s->getWeight() == -1)
6457 Link link = jter->second;
6458 while(
s &&
s->getWeight() == -1)
6462 std::multimap<int, Link>
n = this->getNeighborLinks(
s->id(),
false);
6464 std::multimap<int, Link>::iterator uter =
n.upper_bound(
s->id());
6467 const Signature * s2 = this->getSignature(uter->first);
6470 link = link.
merge(uter->second, uter->second.type());
6471 poses.erase(
s->id());
6481 links.insert(std::make_pair(*
iter, link));
6485 links.insert(std::make_pair(*
iter, jter->second));
6488 else if(jter->second.type() != Link::kLandmark)
6490 links.insert(std::make_pair(*
iter, jter->second));
6492 else if(landmarksAdded)
6496 poses.insert(std::make_pair(jter->first, poses.at(*
iter) * jter->second.transform()));
6498 links.insert(std::make_pair(jter->first, jter->second.inverse()));