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());
3209 const std::map<int, Transform> & poses,
3215 UDEBUG(
"%d -> %d, Guess=%s", fromId, toId, (poses.at(fromId).inverse() * poses.at(toId)).prettyPrint().c_str());
3219 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
3221 if(
iter->first != fromId)
3226 UDEBUG(
"%d vs %s", fromId, ids.c_str());
3230 std::list<Signature*> scansToLoad;
3231 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
3236 if(
s->sensorData().imageCompressed().empty() &&
3237 s->sensorData().laserScanCompressed().isEmpty())
3239 scansToLoad.push_back(
s);
3259 float guessNorm = guess.
getNorm();
3264 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());
3271 int maxPoints = fromScan.
size();
3272 pcl::PointCloud<pcl::PointXYZ>::Ptr assembledToClouds(
new pcl::PointCloud<pcl::PointXYZ>);
3273 pcl::PointCloud<pcl::PointNormal>::Ptr assembledToNormalClouds(
new pcl::PointCloud<pcl::PointNormal>);
3274 pcl::PointCloud<pcl::PointXYZI>::Ptr assembledToIClouds(
new pcl::PointCloud<pcl::PointXYZI>);
3275 pcl::PointCloud<pcl::PointXYZINormal>::Ptr assembledToNormalIClouds(
new pcl::PointCloud<pcl::PointXYZINormal>);
3276 pcl::PointCloud<pcl::PointXYZRGB>::Ptr assembledToRGBClouds(
new pcl::PointCloud<pcl::PointXYZRGB>);
3277 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr assembledToNormalRGBClouds(
new pcl::PointCloud<pcl::PointXYZRGBNormal>);
3278 UDEBUG(
"maxPoints from(%d) = %d", fromId, maxPoints);
3279 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
3281 if(
iter->first != fromId)
3287 s->sensorData().uncompressData(0, 0, &scan);
3330 if(scan.
size() > maxPoints)
3332 UDEBUG(
"maxPoints scan(%d) = %d",
iter->first, (
int)scan.
size());
3333 maxPoints = scan.
size();
3343 UWARN(
"Depth2D not found for signature %d",
iter->first);
3349 if(assembledToNormalClouds->size())
3353 else if(assembledToClouds->size())
3357 else if(assembledToNormalIClouds->size())
3361 else if(assembledToIClouds->size())
3365 else if(assembledToNormalRGBClouds->size())
3369 UERROR(
"Cannot handle 2d scan with RGB format.");
3376 else if(assembledToRGBClouds->size())
3380 UERROR(
"Cannot handle 2d scan with RGB format.");
3387 UDEBUG(
"assembledScan=%d points", assembledScan.
size());
3419 UINFO(
"already linked! to=%d, from=%d", link.
to(), link.
from());
3423 UDEBUG(
"Add link between %d and %d", toS->
id(), fromS->
id());
3459 else if(!addInDatabase)
3463 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
from());
3467 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
to());
3473 UDEBUG(
"Add link between %d and %d (db)", link.
from(), link.
to());
3479 UDEBUG(
"Add link between %d (db) and %d", link.
from(), link.
to());
3485 UDEBUG(
"Add link between %d (db) and %d (db)", link.
from(), link.
to());
3516 UERROR(
"fromId=%d and toId=%d are not linked!", link.
from(), link.
to());
3519 else if(!updateInDatabase)
3523 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
from());
3527 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
to());
3532 UDEBUG(
"Update link between %d and %d (db)", link.
from(), link.
to());
3539 UDEBUG(
"Update link between %d (db) and %d", link.
from(), link.
to());
3546 UDEBUG(
"Update link between %d (db) and %d (db)", link.
from(), link.
to());
3557 iter->second->removeVirtualLinks();
3567 const std::multimap<int, Link> & links =
s->getLinks();
3568 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
3579 UERROR(
"Link %d of %d not in WM/STM?!?",
iter->first,
s->id());
3583 s->removeVirtualLinks();
3587 UERROR(
"Signature %d not in WM/STM?!?", signatureId);
3593 UINFO(
"Dumping memory to directory \"%s\"", directory.c_str());
3613 fopen_s(&foutSign, fileNameSign,
"w");
3615 foutSign = fopen(fileNameSign,
"w");
3620 fprintf(foutSign,
"SignatureID WordsID...\n");
3621 const std::map<int, Signature *> & signatures = this->
getSignatures();
3622 for(std::map<int, Signature *>::const_iterator
iter=signatures.begin();
iter!=signatures.end(); ++
iter)
3624 fprintf(foutSign,
"%d ",
iter->first);
3632 const std::multimap<int, int> &
ref = ss->
getWords();
3633 for(std::multimap<int, int>::const_iterator jter=
ref.begin(); jter!=
ref.end(); ++jter)
3635 const cv::Point3f & pt = ss->
getWords3()[jter->second];
3637 if(pcl::isFinite(pt) &&
3638 (pt.x != 0 || pt.y != 0 || pt.z != 0))
3640 fprintf(foutSign,
"%d ", (*jter).first);
3647 const std::multimap<int, int> &
ref = ss->
getWords();
3648 for(std::multimap<int, int>::const_iterator jter=
ref.begin(); jter!=
ref.end(); ++jter)
3650 fprintf(foutSign,
"%d ", (*jter).first);
3654 fprintf(foutSign,
"\n");
3665 fopen_s(&foutTree, fileNameTree,
"w");
3667 foutTree = fopen(fileNameTree,
"w");
3672 fprintf(foutTree,
"SignatureID Weight NbLoopClosureIds LoopClosureIds... NbChildLoopClosureIds ChildLoopClosureIds...\n");
3676 fprintf(foutTree,
"%d %d",
i->first,
i->second->getWeight());
3678 std::map<int, Link> loopIds, childIds;
3680 for(std::map<int, Link>::const_iterator
iter =
i->second->getLinks().begin();
3681 iter!=
i->second->getLinks().end();
3687 if(
iter->first <
i->first)
3689 childIds.insert(*
iter);
3691 else if(
iter->second.from() !=
iter->second.to())
3693 loopIds.insert(*
iter);
3698 fprintf(foutTree,
" %d", (
int)loopIds.size());
3699 for(std::map<int, Link>::const_iterator
j=loopIds.begin();
j!=loopIds.end(); ++
j)
3701 fprintf(foutTree,
" %d",
j->first);
3704 fprintf(foutTree,
" %d", (
int)childIds.size());
3705 for(std::map<int, Link>::const_iterator
j=childIds.begin();
j!=childIds.end(); ++
j)
3707 fprintf(foutTree,
" %d",
j->first);
3710 fprintf(foutTree,
"\n");
3720 unsigned long memoryUsage =
sizeof(
Memory);
3721 memoryUsage +=
_signatures.size() * (
sizeof(
int)+
sizeof(std::map<int, Signature *>::iterator)) +
sizeof(std::map<int, Signature *>);
3724 memoryUsage +=
iter->second->getMemoryUsed(
true);
3730 memoryUsage +=
_stMem.size() * (
sizeof(
int)+
sizeof(std::set<int>::iterator)) +
sizeof(std::set<int>);
3731 memoryUsage +=
_workingMem.size() * (
sizeof(
int)+
sizeof(
double)+
sizeof(std::map<int, double>::iterator)) +
sizeof(std::map<int, double>);
3732 memoryUsage +=
_groundTruths.size() * (
sizeof(
int)+
sizeof(
Transform)+12*
sizeof(
float) +
sizeof(std::map<int, Transform>::iterator)) +
sizeof(std::map<int, Transform>);
3733 memoryUsage +=
_labels.size() * (
sizeof(
int)+
sizeof(std::string) +
sizeof(std::map<int, std::string>::iterator)) +
sizeof(std::map<int, std::string>);
3736 memoryUsage+=
iter->second.size();
3738 memoryUsage +=
_landmarksIndex.size() * (
sizeof(
int)+
sizeof(std::set<int>) +
sizeof(std::map<int, std::set<int> >
::iterator)) +
sizeof(std::map<int, std::set<int> >);
3741 memoryUsage+=
iter->second.size()*(
sizeof(
int)+
sizeof(std::set<int>::iterator)) +
sizeof(std::set<int>);
3770 if(
s->getWeight() >= 0 &&
s->id() != signature->
id())
3779 UDEBUG(
"Comparing with signature (%d)...",
id);
3799 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_merged(), merged);
3800 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_sim(), sim);
3802 UDEBUG(
"merged=%d, sim=%f t=%fs", merged, sim,
timer.ticks());
3806 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_merged(), 0);
3807 if(
stats)
stats->addStatistic(Statistics::kMemoryRehearsal_sim(), 0);
3819 std::map<int, Link>::const_iterator
iter = oldS->
getLinks().find(newS->
id());
3823 iter->second.from() !=
iter->second.to())
3826 UWARN(
"already merged, old=%d, new=%d", oldId, newId);
3831 UINFO(
"Rehearsal merging %d (w=%d) and %d (w=%d)",
3836 bool intermediateMerge =
false;
3837 if(!newS->
getLinks().empty() && !newS->
getLinks().begin()->second.transform().isNull())
3852 UINFO(
"Rehearsal ignored because the robot has moved more than %f m or %f rad (\"Mem/RehearsalWeightIgnoredWhileMoving\"=true)",
3856 fullMerge = !isMoving && newS->
hasLink(oldS->
id());
3857 intermediateMerge = !isMoving && !newS->
hasLink(oldS->
id());
3861 fullMerge = newS->
hasLink(oldS->
id()) && newS->
getLinks().begin()->second.transform().isNull();
3863 UDEBUG(
"fullMerge=%s intermediateMerge=%s _idUpdatedToNewOneRehearsal=%s",
3864 fullMerge?
"true":
"false",
3865 intermediateMerge?
"true":
"false",
3878 const std::multimap<int, Link> & links = oldS->
getLinks();
3879 for(std::multimap<int, Link>::const_iterator
iter = links.begin();
iter!=links.end(); ++
iter)
3881 if(
iter->second.from() !=
iter->second.to())
3891 s->removeLink(oldS->
id());
3898 UERROR(
"Didn't find neighbor %d of %d in RAM...", link.
to(), oldS->
id());
3947 oldS->
setWeight(intermediateMerge?-1:0);
3958 newS->
setWeight(intermediateMerge?-1:0);
3966 UERROR(
"newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, newId);
3970 UERROR(
"newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, oldId);
3979 int mapId = -1, weight;
3985 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
3998 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
4011 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
4026 getNodeInfo(
id, odomPose, mapId, weight, label, stamp, groundTruth,
velocity, gps, sensors, lookInDatabase);
4028 if(gps.
stamp() == 0.0)
4032 std::map<int, int> nearestIds;
4033 nearestIds =
getNeighborsId(
id, maxGraphDepth, lookInDatabase?-1:0,
true,
false,
true);
4034 std::multimap<int, int> nearestIdsSorted;
4035 for(std::map<int, int>::iterator
iter=nearestIds.begin();
iter!=nearestIds.end(); ++
iter)
4037 nearestIdsSorted.insert(std::make_pair(
iter->second,
iter->first));
4040 for(std::map<int, int>::iterator
iter=nearestIdsSorted.begin();
iter!=nearestIdsSorted.end(); ++
iter)
4044 if(
s->sensorData().gps().stamp() > 0.0)
4047 if(
path.size() >= 2)
4049 gps =
s->sensorData().gps();
4051 offsetENU = localToENU*(
s->getPose().rotation()*
path.rbegin()->second);
4056 UWARN(
"Failed to find path %d -> %d",
s->id(),
id);
4067 std::string & label,
4070 std::vector<float> & velocity,
4073 bool lookInDatabase)
const
4078 odomPose =
s->getPose().clone();
4080 weight =
s->getWeight();
4081 label = std::string(
s->getLabel());
4082 stamp =
s->getStamp();
4083 groundTruth =
s->getGroundTruthPose().clone();
4084 velocity = std::vector<float>(
s->getVelocity());
4085 gps =
GPS(
s->sensorData().gps());
4086 sensors =
EnvSensors(
s->sensorData().envSensors());
4102 image =
s->sensorData().imageCompressed();
4108 image =
data.imageCompressed();
4118 if(
s && (!
s->isSaved() ||
4119 ((!images || !
s->sensorData().imageCompressed().empty()) &&
4120 (!scan || !
s->sensorData().laserScanCompressed().isEmpty()) &&
4121 (!userData || !
s->sensorData().userDataCompressed().empty()) &&
4122 (!occupancyGrid ||
s->sensorData().gridCellSize() != 0.0f))))
4124 r =
s->sensorData();
4127 r.
setRGBDImage(cv::Mat(), cv::Mat(), std::vector<CameraModel>());
4152 std::multimap<int, int> & words,
4153 std::vector<cv::KeyPoint> & wordsKpts,
4154 std::vector<cv::Point3f> & words3,
4155 cv::Mat & wordsDescriptors,
4156 std::vector<GlobalDescriptor> & globalDescriptors)
const
4162 words =
s->getWords();
4163 wordsKpts =
s->getWordsKpts();
4164 words3 =
s->getWords3();
4165 wordsDescriptors =
s->getWordsDescriptors();
4166 globalDescriptors =
s->sensorData().globalDescriptors();
4171 std::list<Signature*> signatures;
4173 ids.push_back(nodeId);
4174 std::set<int> loadedFromTrash;
4176 if(signatures.size())
4178 words = signatures.front()->getWords();
4179 wordsKpts = signatures.front()->getWordsKpts();
4180 words3 = signatures.front()->getWords3();
4181 wordsDescriptors = signatures.front()->getWordsDescriptors();
4182 globalDescriptors = signatures.front()->sensorData().globalDescriptors();
4183 if(loadedFromTrash.size())
4190 delete signatures.front();
4197 std::vector<CameraModel> & models,
4198 std::vector<StereoCameraModel> & stereoModels)
const
4204 models =
s->sensorData().cameraModels();
4205 stereoModels =
s->sensorData().stereoCameraModels();
4218 UERROR(
"A database must must loaded first...");
4226 const std::map<int, Transform> & poses,
4227 const cv::Mat & map,
4236 UERROR(
"A database must be loaded first...");
4240 if(poses.empty() || poses.lower_bound(1) == poses.end())
4254 for(std::map<int, Transform>::const_iterator
iter=poses.lower_bound(1);
iter!=poses.end(); ++
iter)
4259 UINFO(
"Processing %d grids...", maxPoses);
4260 int processedGrids = 1;
4261 int gridsScansModified = 0;
4262 for(std::map<int, Transform>::const_iterator
iter=poses.lower_bound(1);
iter!=poses.end(); ++
iter, ++processedGrids)
4266 cv::Mat gridObstacles;
4272 data.uncompressData(0,0,&scan,0,&gridGround,&gridObstacles,&gridEmpty);
4274 if(!gridObstacles.empty())
4277 cv::Mat filtered = cv::Mat(1, gridObstacles.cols, gridObstacles.type());
4279 for(
int i=0;
i<gridObstacles.cols; ++
i)
4281 const float * ptr = gridObstacles.ptr<
float>(0,
i);
4282 cv::Point3f pt(ptr[0], ptr[1], gridObstacles.channels()==2?0:ptr[2]);
4285 int x =
int((pt.x - xMin) / cellSize + 0.5f);
4286 int y =
int((pt.y - yMin) / cellSize + 0.5f);
4288 if(
x>=0 &&
x<map.cols &&
4291 bool obstacleDetected =
false;
4293 for(
int j=-cropRadius;
j<=cropRadius && !obstacleDetected; ++
j)
4295 for(
int k=-cropRadius; k<=cropRadius && !obstacleDetected; ++k)
4297 if(
x+
j>=0 &&
x+
j<map.cols &&
4298 y+k>=0 &&
y+k<map.rows &&
4299 map.at<
unsigned char>(
y+k,
x+
j) == 100)
4301 obstacleDetected =
true;
4306 if(map.at<
unsigned char>(
y,
x) != 0 || obstacleDetected)
4315 if(oi != gridObstacles.cols)
4317 UINFO(
"Grid id=%d (%d/%d) filtered %d -> %d",
iter->first, processedGrids, maxPoses, gridObstacles.cols, oi);
4318 gridsScansModified += 1;
4322 cv::Mat newObstacles = cv::Mat(filtered,
cv::Range::all(), cv::Range(0, oi));
4323 bool modifyDb =
true;
4326 s->sensorData().setOccupancyGrid(gridGround, newObstacles, gridEmpty, cellSize,
data.gridViewPoint());
4340 data.gridViewPoint());
4345 if(filterScans && !scan.
isEmpty())
4349 cv::Mat filtered = cv::Mat(1, scan.
size(), scan.
dataType());
4351 for(
int i=0;
i<scan.
size(); ++
i)
4353 const float * ptr = scan.
data().ptr<
float>(0,
i);
4354 cv::Point3f pt(ptr[0], ptr[1], scan.
is2d()?0:ptr[2]);
4357 int x =
int((pt.x - xMin) / cellSize + 0.5f);
4358 int y =
int((pt.y - yMin) / cellSize + 0.5f);
4360 if(
x>=0 &&
x<map.cols &&
4363 bool obstacleDetected =
false;
4365 for(
int j=-cropRadius;
j<=cropRadius && !obstacleDetected; ++
j)
4367 for(
int k=-cropRadius; k<=cropRadius && !obstacleDetected; ++k)
4369 if(
x+
j>=0 &&
x+
j<map.cols &&
4370 y+k>=0 &&
y+k<map.rows &&
4371 map.at<
unsigned char>(
y+k,
x+
j) == 100)
4373 obstacleDetected =
true;
4378 if(map.at<
unsigned char>(
y,
x) != 0 || obstacleDetected)
4387 if(oi != scan.
size())
4389 UINFO(
"Scan id=%d (%d/%d) filtered %d -> %d",
iter->first, processedGrids, maxPoses, (
int)scan.
size(), oi);
4390 gridsScansModified += 1;
4419 bool modifyDb =
true;
4422 s->sensorData().setLaserScan(scan,
true);
4437 return gridsScansModified;
4466 id.push_back(to->
id());
4472 UDEBUG(
"Loaded image data from database");
4484 ULOGGER_ERROR(
"Can't merge the signatures because there are not same type.");
4510 data.imageRaw().type() == CV_8UC1 ||
4511 data.imageRaw().type() == CV_8UC3);
4513 ( (
data.depthOrRightRaw().type() == CV_16UC1 ||
4514 data.depthOrRightRaw().type() == CV_32FC1 ||
4515 data.depthOrRightRaw().type() == CV_8UC1)
4517 ( (
data.imageRaw().empty() &&
data.depthOrRightRaw().type() != CV_8UC1) ||
4518 (
data.depthOrRightRaw().rows <=
data.imageRaw().rows &&
data.depthOrRightRaw().cols <=
data.imageRaw().cols))),
4519 uFormat(
"image=(%d/%d, type=%d, [accepted=%d,%d]) depth=(%d/%d, type=%d [accepted=%d(depth mm),%d(depth m),%d(stereo)]). "
4520 "For stereo, left and right images should be same size. "
4521 "For RGB-D, depth can be X times smaller than RGB (where X is an integer).",
4522 data.imageRaw().cols,
4523 data.imageRaw().rows,
4524 data.imageRaw().type(),
4527 data.depthOrRightRaw().cols,
4528 data.depthOrRightRaw().rows,
4529 data.depthOrRightRaw().type(),
4530 CV_16UC1, CV_32FC1, CV_8UC1).c_str());
4532 if(!
data.depthOrRightRaw().empty() &&
4533 data.cameraModels().empty() &&
4534 data.stereoCameraModels().empty() &&
4537 UERROR(
"No camera calibration found, calibrate your camera!");
4547 std::vector<cv::KeyPoint> keypoints;
4548 cv::Mat descriptors;
4549 bool isIntermediateNode =
data.id() < 0 || (
data.imageRaw().empty() &&
data.keypoints().empty() &&
data.laserScanRaw().empty());
4559 UERROR(
"Received image ID is null. "
4560 "Please set parameter Mem/GenerateIds to \"true\" or "
4561 "make sure the input source provides image ids (seq).");
4570 UERROR(
"Id of acquired image (%d) is smaller than the last in memory (%d). "
4571 "Please set parameter Mem/GenerateIds to \"true\" or "
4572 "make sure the input source provides image ids (seq) over the last in "
4573 "memory, which is %d.",
4586 if(
data.cameraModels().size())
4588 UDEBUG(
"Monocular rectification");
4590 UASSERT(
int((
data.imageRaw().cols/
data.cameraModels().size())*
data.cameraModels().size()) ==
data.imageRaw().cols);
4591 int subImageWidth =
data.imageRaw().cols/
data.cameraModels().size();
4592 cv::Mat rectifiedImages(
data.imageRaw().size(),
data.imageRaw().type());
4598 for(
unsigned int i=0;
i<
data.cameraModels().
size(); ++
i)
4600 if(
data.cameraModels()[
i].isValidForRectification())
4607 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)...",
i);
4609 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)... done!",
i);
4614 cv::Mat rectifiedImage =
_rectCameraModels[
i].rectifyImage(cv::Mat(
data.imageRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4615 rectifiedImage.copyTo(cv::Mat(rectifiedImages, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4616 imagesRectified =
true;
4620 UERROR(
"Calibration for camera %d cannot be used to rectify the image. Make sure to do a "
4621 "full calibration. If images are already rectified, set %s parameter back to true.",
4623 Parameters::kRtabmapImagesAlreadyRectified().
c_str());
4624 std::cout <<
data.cameraModels()[
i] << std::endl;
4628 data.setRGBDImage(rectifiedImages,
data.depthOrRightRaw(),
data.cameraModels());
4630 else if(
data.stereoCameraModels().size())
4632 UDEBUG(
"Stereo rectification");
4633 UASSERT(
int((
data.imageRaw().cols/
data.stereoCameraModels().size())*
data.stereoCameraModels().size()) ==
data.imageRaw().cols);
4634 int subImageWidth =
data.imageRaw().cols/
data.stereoCameraModels().size();
4635 UASSERT(subImageWidth ==
data.rightRaw().cols/(
int)
data.stereoCameraModels().size());
4636 cv::Mat rectifiedLefts(
data.imageRaw().size(),
data.imageRaw().type());
4637 cv::Mat rectifiedRights(
data.rightRaw().size(),
data.rightRaw().type());
4644 for(
unsigned int i=0;
i<
data.stereoCameraModels().
size(); ++
i)
4646 if(
data.stereoCameraModels()[
i].isValidForRectification())
4653 UWARN(
"Initializing rectification maps (only done for the first image received)...");
4655 UWARN(
"Initializing rectification maps (only done for the first image received)...done!");
4661 cv::Mat rectifiedLeft =
_rectStereoCameraModels[
i].left().rectifyImage(cv::Mat(
data.imageRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4662 cv::Mat rectifiedRight =
_rectStereoCameraModels[
i].right().rectifyImage(cv::Mat(
data.rightRaw(), cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.rightRaw().rows)));
4663 rectifiedLeft.copyTo(cv::Mat(rectifiedLefts, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.imageRaw().rows)));
4664 rectifiedRight.copyTo(cv::Mat(rectifiedRights, cv::Rect(subImageWidth*
i, 0, subImageWidth,
data.rightRaw().rows)));
4665 imagesRectified =
true;
4669 UERROR(
"Calibration for camera %d cannot be used to rectify the image. Make sure to do a "
4670 "full calibration. If images are already rectified, set %s parameter back to true.",
4672 Parameters::kRtabmapImagesAlreadyRectified().
c_str());
4673 std::cout <<
data.stereoCameraModels()[
i] << std::endl;
4678 data.setStereoImage(
4681 data.stereoCameraModels());
4685 UERROR(
"Stereo calibration cannot be used to rectify images. Make sure to do a "
4686 "full stereo calibration. If images are already rectified, set %s parameter back to true.",
4687 Parameters::kRtabmapImagesAlreadyRectified().
c_str());
4691 if(
stats)
stats->addStatistic(Statistics::kTimingMemRectification(),
t*1000.0
f);
4692 UDEBUG(
"time rectification = %fs",
t);
4704 UDEBUG(
"Start dictionary update thread");
4705 preUpdateThread.
start();
4711 UASSERT(
int((
data.imageRaw().cols/
data.cameraModels().size())*
data.cameraModels().size()) ==
data.imageRaw().cols);
4712 int subInputImageWidth =
data.imageRaw().cols/
data.cameraModels().size();
4713 int subInputDepthWidth =
data.depthRaw().cols/
data.cameraModels().size();
4714 int subOutputImageWidth = 0;
4715 int subOutputDepthWidth = 0;
4716 cv::Mat rotatedColorImages;
4717 cv::Mat rotatedDepthImages;
4718 std::vector<CameraModel> rotatedCameraModels;
4719 bool allOutputSizesAreOkay =
true;
4720 for(
size_t i=0;
i<
data.cameraModels().
size(); ++
i)
4722 UDEBUG(
"Rotating camera %ld",
i);
4723 cv::Mat rgb = cv::Mat(
data.imageRaw(), cv::Rect(subInputImageWidth*
i, 0, subInputImageWidth,
data.imageRaw().rows));
4724 cv::Mat depth = !
data.depthRaw().empty()?cv::Mat(
data.depthRaw(), cv::Rect(subInputDepthWidth*
i, 0, subInputDepthWidth,
data.depthRaw().rows)):cv::Mat();
4727 if(rotatedColorImages.empty())
4729 rotatedColorImages = cv::Mat(cv::Size(rgb.cols *
data.cameraModels().size(), rgb.rows), rgb.type());
4730 subOutputImageWidth = rgb.cols;;
4733 rotatedDepthImages = cv::Mat(cv::Size(depth.cols *
data.cameraModels().size(), depth.rows), depth.type());
4734 subOutputDepthWidth = depth.cols;
4737 else if(rgb.cols != subOutputImageWidth || depth.cols != subOutputDepthWidth ||
4738 rgb.rows != rotatedColorImages.rows || depth.rows != rotatedDepthImages.rows)
4740 UWARN(
"Rotated image for camera index %d (rgb=%dx%d depth=%dx%d) doesn't tally "
4741 "with the first camera (rgb=%dx%d, depth=%dx%d). Aborting upside up rotation, "
4742 "will use original image orientation. Set parameter %s to false to avoid "
4746 depth.cols, depth.rows,
4747 subOutputImageWidth, rotatedColorImages.rows,
4748 subOutputDepthWidth, rotatedDepthImages.rows,
4749 Parameters::kMemRotateImagesUpsideUp().c_str());
4750 allOutputSizesAreOkay =
false;
4753 rgb.copyTo(cv::Mat(rotatedColorImages, cv::Rect(subOutputImageWidth*
i, 0, subOutputImageWidth, rgb.rows)));
4756 depth.copyTo(cv::Mat(rotatedDepthImages, cv::Rect(subOutputDepthWidth*
i, 0, subOutputDepthWidth, depth.rows)));
4758 rotatedCameraModels.push_back(
model);
4760 if(allOutputSizesAreOkay)
4762 data.setRGBDImage(rotatedColorImages, rotatedDepthImages, rotatedCameraModels);
4765 if(!
data.keypoints().empty() || !
data.keypoints3D().empty() || !
data.descriptors().empty())
4769 static bool warned =
false;
4772 UWARN(
"Because parameter %s is enabled, parameter %s is inhibited as "
4773 "features have to be regenerated. To avoid this warning, set "
4774 "explicitly %s to false. This message is only "
4776 Parameters::kMemRotateImagesUpsideUp().
c_str(),
4777 Parameters::kMemUseOdomFeatures().
c_str(),
4778 Parameters::kMemUseOdomFeatures().
c_str());
4782 data.setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
4788 static bool warned =
false;
4791 UWARN(
"Parameter %s can only be used with RGB-only or RGB-D cameras. "
4792 "Ignoring upside up rotation. This message is only printed once.",
4793 Parameters::kMemRotateImagesUpsideUp().
c_str());
4798 unsigned int preDecimation = 1;
4799 std::vector<cv::Point3f> keypoints3D;
4801 UDEBUG(
"Received kpts=%d kpts3D=%d, descriptors=%d _useOdometryFeatures=%s",
4804 data.keypoints().empty() ||
4805 (
int)
data.keypoints().size() !=
data.descriptors().rows ||
4810 decimatedData =
data;
4815 if( !
data.cameraModels().empty() &&
4816 data.cameraModels()[0].imageHeight()>0 &&
4817 data.cameraModels()[0].imageWidth()>0)
4821 if(targetSize >=
data.depthRaw().rows)
4823 decimationDepth = 1;
4827 decimationDepth = (
int)
ceil(
float(
data.depthRaw().rows) /
float(targetSize));
4832 std::vector<CameraModel> cameraModels = decimatedData.
cameraModels();
4833 for(
unsigned int i=0;
i<cameraModels.size(); ++
i)
4837 if(!cameraModels.empty())
4845 std::vector<StereoCameraModel> stereoCameraModels = decimatedData.
stereoCameraModels();
4846 for(
unsigned int i=0;
i<stereoCameraModels.size(); ++
i)
4850 if(!stereoCameraModels.empty())
4855 stereoCameraModels);
4859 UINFO(
"Extract features");
4861 if(decimatedData.
imageRaw().channels() == 3)
4863 cv::cvtColor(decimatedData.
imageRaw(), imageMono, CV_BGR2GRAY);
4867 imageMono = decimatedData.
imageRaw();
4873 if(imageMono.rows % decimatedData.
depthRaw().rows == 0 &&
4874 imageMono.cols % decimatedData.
depthRaw().cols == 0 &&
4875 imageMono.rows/decimatedData.
depthRaw().rows == imageMono.cols/decimatedData.
depthRaw().cols)
4881 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).",
4882 Parameters::kMemDepthAsMask().
c_str(),
4883 imageMono.cols, imageMono.rows,
4889 bool useProvided3dPoints =
false;
4892 UDEBUG(
"Using provided keypoints (%d)", (
int)
data.keypoints().size());
4893 keypoints =
data.keypoints();
4895 useProvided3dPoints = keypoints.size() ==
data.keypoints3D().size();
4903 for(
unsigned int i=0;
i < keypoints.size(); ++
i)
4905 cv::KeyPoint & kpt = keypoints[
i];
4908 kpt.pt.x *= decimationRatio;
4909 kpt.pt.y *= decimationRatio;
4910 kpt.size *= decimationRatio;
4911 kpt.octave += log2value;
4913 if(useProvided3dPoints)
4915 keypoints[
i].class_id =
i;
4937 if(tmpMaxFeatureParameter.size())
4939 tmpMaxFeatureParameter.at(Parameters::kKpMaxFeatures()) =
uNumber2Str(oldMaxFeatures);
4943 if(
stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_detection(),
t*1000.0
f);
4944 UDEBUG(
"time keypoints (%d) = %fs", (
int)keypoints.size(),
t);
4949 if(
stats)
stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(),
t*1000.0
f);
4950 UDEBUG(
"time descriptors (%d) = %fs", descriptors.rows,
t);
4953 if(descriptors.rows && descriptors.rows <
_badSignRatio *
float(meanWordsPerLocation))
4955 descriptors = cv::Mat();
4959 if(!imagesRectified && decimatedData.
cameraModels().size())
4961 UASSERT_MSG((
int)keypoints.size() == descriptors.rows,
uFormat(
"%d vs %d", (
int)keypoints.size(), descriptors.rows).c_str());
4962 std::vector<cv::KeyPoint> keypointsValid;
4963 keypointsValid.reserve(keypoints.size());
4964 cv::Mat descriptorsValid;
4965 descriptorsValid.reserve(descriptors.rows);
4970 std::vector<cv::Point2f> pointsIn, pointsOut;
4971 cv::KeyPoint::convert(keypoints,pointsIn);
4974 #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)))
4977 cv::Mat
D(1, 4, CV_64FC1);
4978 D.at<
double>(0,0) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,0);
4979 D.at<
double>(0,1) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,1);
4980 D.at<
double>(0,2) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,4);
4981 D.at<
double>(0,3) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,5);
4982 cv::fisheye::undistortPoints(pointsIn, pointsOut,
4990 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
4991 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
4996 cv::undistortPoints(pointsIn, pointsOut,
5002 UASSERT(pointsOut.size() == keypoints.size());
5003 for(
unsigned int i=0;
i<pointsOut.size(); ++
i)
5005 if(pointsOut.at(
i).x>=0 && pointsOut.at(
i).x<decimatedData.
cameraModels()[0].imageWidth() &&
5006 pointsOut.at(
i).y>=0 && pointsOut.at(
i).y<decimatedData.
cameraModels()[0].imageHeight())
5008 keypointsValid.push_back(keypoints.at(
i));
5009 keypointsValid.back().pt.x = pointsOut.at(
i).x;
5010 keypointsValid.back().pt.y = pointsOut.at(
i).y;
5011 descriptorsValid.push_back(descriptors.row(
i));
5019 for(
unsigned int i=0;
i<keypoints.size(); ++
i)
5021 int cameraIndex =
int(keypoints.at(
i).pt.x / subImageWidth);
5023 uFormat(
"cameraIndex=%d, models=%d, kpt.x=%f, subImageWidth=%f (Camera model image width=%d)",
5024 cameraIndex, (
int)decimatedData.
cameraModels().size(), keypoints[
i].pt.x, subImageWidth, decimatedData.
cameraModels()[0].imageWidth()).c_str());
5026 std::vector<cv::Point2f> pointsIn, pointsOut;
5027 pointsIn.push_back(cv::Point2f(keypoints.at(
i).pt.x-subImageWidth*cameraIndex, keypoints.at(
i).pt.y));
5028 if(decimatedData.
cameraModels()[cameraIndex].D_raw().cols == 6)
5030 #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)))
5033 cv::Mat
D(1, 4, CV_64FC1);
5034 D.at<
double>(0,0) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,0);
5035 D.at<
double>(0,1) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,1);
5036 D.at<
double>(0,2) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,4);
5037 D.at<
double>(0,3) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,5);
5038 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5046 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5047 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5052 cv::undistortPoints(pointsIn, pointsOut,
5059 if(pointsOut[0].
x>=0 && pointsOut[0].
x<decimatedData.
cameraModels()[cameraIndex].imageWidth() &&
5060 pointsOut[0].y>=0 && pointsOut[0].y<decimatedData.
cameraModels()[cameraIndex].imageHeight())
5062 keypointsValid.push_back(keypoints.at(
i));
5063 keypointsValid.back().pt.x = pointsOut[0].x + subImageWidth*cameraIndex;
5064 keypointsValid.back().pt.y = pointsOut[0].y;
5065 descriptorsValid.push_back(descriptors.row(
i));
5070 keypoints = keypointsValid;
5071 descriptors = descriptorsValid;
5074 if(
stats)
stats->addStatistic(Statistics::kTimingMemRectification(),
t*1000.0
f);
5075 UDEBUG(
"time rectification = %fs",
t);
5078 if(useProvided3dPoints && keypoints.size() !=
data.keypoints3D().size())
5080 UDEBUG(
"Using provided 3d points (%d->%d)", (
int)
data.keypoints3D().size(), (
int)keypoints.size());
5081 keypoints3D.resize(keypoints.size());
5082 for(
size_t i=0;
i<keypoints.size(); ++
i)
5084 UASSERT(keypoints[
i].class_id < (
int)
data.keypoints3D().size());
5085 keypoints3D[
i] =
data.keypoints3D()[keypoints[
i].class_id];
5088 else if(useProvided3dPoints && keypoints.size() ==
data.keypoints3D().size())
5090 UDEBUG(
"Using provided 3d points (%d)", (
int)
data.keypoints3D().size());
5091 keypoints3D =
data.keypoints3D();
5098 if(
stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_3D(),
t*1000.0
f);
5099 UDEBUG(
"time keypoints 3D (%d) = %fs", (
int)keypoints3D.size(),
t);
5107 else if(
data.imageRaw().empty())
5109 UDEBUG(
"Empty image, cannot extract features...");
5111 else if(_feature2D->getMaxFeatures() < 0)
5113 UDEBUG(
"_feature2D->getMaxFeatures()(%d<0) so don't extract any features...", _feature2D->getMaxFeatures());
5117 UDEBUG(
"Intermediate node detected, don't extract features!");
5120 else if(_feature2D->getMaxFeatures() >= 0 && !isIntermediateNode)
5122 UINFO(
"Use odometry features: kpts=%d 3d=%d desc=%d (dim=%d, type=%d)",
5123 (
int)
data.keypoints().size(),
5124 (
int)
data.keypoints3D().size(),
5125 data.descriptors().rows,
5126 data.descriptors().cols,
5127 data.descriptors().type());
5128 keypoints =
data.keypoints();
5129 keypoints3D =
data.keypoints3D();
5130 descriptors =
data.descriptors().clone();
5132 UASSERT(descriptors.empty() || descriptors.rows == (
int)keypoints.size());
5133 UASSERT(keypoints3D.empty() || keypoints3D.size() == keypoints.size());
5135 int maxFeatures = _rawDescriptorsKept&&!pose.isNull()&&_feature2D->getMaxFeatures()>0&&_feature2D->getMaxFeatures()<_visMaxFeatures?_visMaxFeatures:_feature2D->getMaxFeatures();
5136 bool ssc = _rawDescriptorsKept&&!pose.isNull()&&_feature2D->getMaxFeatures()>0&&_feature2D->getMaxFeatures()<_visMaxFeatures?_visSSC:_feature2D->getSSC();
5137 if((
int)keypoints.size() > maxFeatures)
5139 if(
data.cameraModels().size()==1 ||
data.stereoCameraModels().size()==1)
5140 _feature2D->limitKeypoints(keypoints, keypoints3D, descriptors, maxFeatures,
data.cameraModels().size()?
data.cameraModels()[0].imageSize():
data.stereoCameraModels()[0].left().imageSize(), ssc);
5142 _feature2D->limitKeypoints(keypoints, keypoints3D, descriptors, maxFeatures);
5145 if(stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0f);
5146 UDEBUG(
"time keypoints (%d) = %fs", (
int)keypoints.size(), t);
5148 if(descriptors.empty())
5151 if(
data.imageRaw().channels() == 3)
5153 cv::cvtColor(
data.imageRaw(), imageMono, CV_BGR2GRAY);
5157 imageMono =
data.imageRaw();
5160 UASSERT_MSG(imagesRectified,
"Cannot extract descriptors on not rectified image from keypoints which assumed to be undistorted");
5161 descriptors = _feature2D->generateDescriptors(imageMono, keypoints);
5163 else if(!imagesRectified && !
data.cameraModels().empty())
5165 std::vector<cv::KeyPoint> keypointsValid;
5166 keypointsValid.reserve(keypoints.size());
5167 cv::Mat descriptorsValid;
5168 descriptorsValid.reserve(descriptors.rows);
5169 std::vector<cv::Point3f> keypoints3DValid;
5170 keypoints3DValid.reserve(keypoints3D.size());
5173 if(
data.cameraModels().size() == 1)
5175 std::vector<cv::Point2f> pointsIn, pointsOut;
5176 cv::KeyPoint::convert(keypoints,pointsIn);
5177 if(
data.cameraModels()[0].D_raw().cols == 6)
5179 #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)))
5182 cv::Mat
D(1, 4, CV_64FC1);
5183 D.at<
double>(0,0) =
data.cameraModels()[0].D_raw().at<
double>(0,0);
5184 D.at<
double>(0,1) =
data.cameraModels()[0].D_raw().at<
double>(0,1);
5185 D.at<
double>(0,2) =
data.cameraModels()[0].D_raw().at<
double>(0,4);
5186 D.at<
double>(0,3) =
data.cameraModels()[0].D_raw().at<
double>(0,5);
5187 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5188 data.cameraModels()[0].K_raw(),
5190 data.cameraModels()[0].R(),
5191 data.cameraModels()[0].P());
5195 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5196 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5201 cv::undistortPoints(pointsIn, pointsOut,
5202 data.cameraModels()[0].K_raw(),
5203 data.cameraModels()[0].D_raw(),
5204 data.cameraModels()[0].R(),
5205 data.cameraModels()[0].P());
5207 UASSERT(pointsOut.size() == keypoints.size());
5208 for(
unsigned int i=0;
i<pointsOut.size(); ++
i)
5210 if(pointsOut.at(i).x>=0 && pointsOut.at(i).x<
data.cameraModels()[0].imageWidth() &&
5211 pointsOut.at(i).y>=0 && pointsOut.at(i).y<
data.cameraModels()[0].imageHeight())
5213 keypointsValid.push_back(keypoints.at(i));
5214 keypointsValid.back().pt.x = pointsOut.at(i).x;
5215 keypointsValid.back().pt.y = pointsOut.at(i).y;
5216 descriptorsValid.push_back(descriptors.row(i));
5217 if(!keypoints3D.empty())
5219 keypoints3DValid.push_back(keypoints3D.at(i));
5226 float subImageWidth;
5227 if(!
data.imageRaw().empty())
5229 UASSERT(
int((
data.imageRaw().cols/
data.cameraModels().size())*
data.cameraModels().size()) ==
data.imageRaw().cols);
5230 subImageWidth =
data.imageRaw().cols/
data.cameraModels().size();
5235 subImageWidth =
data.cameraModels()[0].imageWidth();
5238 for(
unsigned int i=0;
i<keypoints.size(); ++
i)
5240 int cameraIndex =
int(keypoints.at(i).pt.x / subImageWidth);
5241 UASSERT_MSG(cameraIndex >= 0 && cameraIndex < (
int)
data.cameraModels().size(),
5242 uFormat(
"cameraIndex=%d, models=%d, kpt.x=%f, subImageWidth=%f (Camera model image width=%d)",
5243 cameraIndex, (
int)
data.cameraModels().size(), keypoints[i].pt.x, subImageWidth,
data.cameraModels()[0].imageWidth()).c_str());
5245 std::vector<cv::Point2f> pointsIn, pointsOut;
5246 pointsIn.push_back(cv::Point2f(keypoints.at(i).pt.x-subImageWidth*cameraIndex, keypoints.at(i).pt.y));
5247 if(
data.cameraModels()[cameraIndex].D_raw().cols == 6)
5249 #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)))
5252 cv::Mat
D(1, 4, CV_64FC1);
5253 D.at<
double>(0,0) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,0);
5254 D.at<
double>(0,1) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,1);
5255 D.at<
double>(0,2) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,4);
5256 D.at<
double>(0,3) =
data.cameraModels()[cameraIndex].D_raw().at<
double>(0,5);
5257 cv::fisheye::undistortPoints(pointsIn, pointsOut,
5258 data.cameraModels()[cameraIndex].K_raw(),
5260 data.cameraModels()[cameraIndex].R(),
5261 data.cameraModels()[cameraIndex].P());
5265 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
5266 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
5271 cv::undistortPoints(pointsIn, pointsOut,
5272 data.cameraModels()[cameraIndex].K_raw(),
5273 data.cameraModels()[cameraIndex].D_raw(),
5274 data.cameraModels()[cameraIndex].R(),
5275 data.cameraModels()[cameraIndex].P());
5278 if(pointsOut[0].x>=0 && pointsOut[0].x<
data.cameraModels()[cameraIndex].imageWidth() &&
5279 pointsOut[0].y>=0 && pointsOut[0].y<
data.cameraModels()[cameraIndex].imageHeight())
5281 keypointsValid.push_back(keypoints.at(i));
5282 keypointsValid.back().pt.x = pointsOut[0].x + subImageWidth*cameraIndex;
5283 keypointsValid.back().pt.y = pointsOut[0].y;
5284 descriptorsValid.push_back(descriptors.row(i));
5285 if(!keypoints3D.empty())
5287 keypoints3DValid.push_back(keypoints3D.at(i));
5293 keypoints = keypointsValid;
5294 descriptors = descriptorsValid;
5295 keypoints3D = keypoints3DValid;
5298 if(stats)
stats->addStatistic(Statistics::kTimingMemRectification(), t*1000.0f);
5299 UDEBUG(
"time rectification = %fs", t);
5302 if(stats)
stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0f);
5303 UDEBUG(
"time descriptors (%d) = %fs", descriptors.rows, t);
5305 if(keypoints3D.empty() &&
5306 ((!
data.depthRaw().empty() &&
data.cameraModels().size() &&
data.cameraModels()[0].isValidForProjection()) ||
5307 (!
data.rightRaw().empty() &&
data.stereoCameraModels().size() &&
data.stereoCameraModels()[0].isValidForProjection())))
5309 keypoints3D = _feature2D->generateKeypoints3D(data, keypoints);
5311 if(_feature2D->getMinDepth() > 0.0f || _feature2D->getMaxDepth() > 0.0f)
5313 _feature2D->filterKeypointsByDepth(keypoints, descriptors, keypoints3D, _feature2D->getMinDepth(), _feature2D->getMaxDepth());
5316 if(stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_3D(), t*1000.0f);
5317 UDEBUG(
"time keypoints 3D (%d) = %fs", (
int)keypoints3D.size(), t);
5319 UDEBUG(
"ratio=%f, meanWordsPerLocation=%d", _badSignRatio, meanWordsPerLocation);
5320 if(descriptors.rows && descriptors.rows < _badSignRatio *
float(meanWordsPerLocation))
5322 descriptors = cv::Mat();
5328 UDEBUG(
"Joining dictionary update thread...");
5329 preUpdateThread.join();
5330 UDEBUG(
"Joining dictionary update thread... thread finished!");
5334 if(stats)
stats->addStatistic(Statistics::kTimingMemJoining_dictionary_update(), t*1000.0f);
5337 UDEBUG(
"time descriptor and memory update (%d of size=%d) = %fs", descriptors.rows, descriptors.cols, t);
5341 UDEBUG(
"time descriptor (%d of size=%d) = %fs", descriptors.rows, descriptors.cols, t);
5344 std::list<int> wordIds;
5345 if(descriptors.rows)
5349 std::vector<bool> inliers;
5350 cv::Mat descriptorsForQuantization = descriptors;
5351 std::vector<int> quantizedToRawIndices;
5352 if(_feature2D->getMaxFeatures()>0 && descriptors.rows > _feature2D->getMaxFeatures())
5354 UASSERT((
int)keypoints.size() == descriptors.rows);
5355 int inliersCount = 0;
5356 if((_feature2D->getGridRows() > 1 || _feature2D->getGridCols() > 1) &&
5357 (decimatedData.cameraModels().size()==1 || decimatedData.stereoCameraModels().size()==1 ||
5358 data.cameraModels().size()==1 ||
data.stereoCameraModels().size()==1))
5360 Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures(),
5361 decimatedData.cameraModels().size()?decimatedData.cameraModels()[0].imageSize():
5362 decimatedData.stereoCameraModels().size()?decimatedData.stereoCameraModels()[0].left().imageSize():
5363 data.cameraModels().size()?
data.cameraModels()[0].imageSize():
data.stereoCameraModels()[0].left().imageSize(),
5364 _feature2D->getGridRows(), _feature2D->getGridCols(), _feature2D->getSSC());
5368 if(_feature2D->getGridRows() > 1 || _feature2D->getGridCols() > 1)
5370 UWARN(
"Ignored %s and %s parameters as they cannot be used for multi-cameras setup or uncalibrated camera.",
5371 Parameters::kKpGridCols().
c_str(), Parameters::kKpGridRows().
c_str());
5373 if(decimatedData.cameraModels().size()==1 || decimatedData.stereoCameraModels().size()==1 ||
5374 data.cameraModels().size()==1 ||
data.stereoCameraModels().size()==1)
5376 Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures(),
5377 decimatedData.cameraModels().size()?decimatedData.cameraModels()[0].imageSize():
5378 decimatedData.stereoCameraModels().size()?decimatedData.stereoCameraModels()[0].left().imageSize():
5379 data.cameraModels().size()?
data.cameraModels()[0].imageSize():
data.stereoCameraModels()[0].left().imageSize(),
5380 _feature2D->getSSC());
5384 Feature2D::limitKeypoints(keypoints, inliers, _feature2D->getMaxFeatures());
5387 for(
size_t i=0;
i<inliers.size(); ++
i)
5393 descriptorsForQuantization = cv::Mat(inliersCount, descriptors.cols, descriptors.type());
5394 quantizedToRawIndices.resize(inliersCount);
5396 UASSERT((
int)inliers.size() == descriptors.rows);
5397 for(
int k=0; k < descriptors.rows; ++k)
5401 UASSERT(oi < quantizedToRawIndices.size());
5402 if(descriptors.type() == CV_32FC1)
5404 memcpy(descriptorsForQuantization.ptr<
float>(oi), descriptors.ptr<
float>(k), descriptors.cols*
sizeof(
float));
5408 memcpy(descriptorsForQuantization.ptr<
char>(oi), descriptors.ptr<
char>(k), descriptors.cols*
sizeof(
char));
5410 quantizedToRawIndices[oi] = k;
5415 uFormat(
"oi=%d inliersCount=%d (maxFeatures=%d, grid=%dx%d)",
5416 oi, inliersCount, _feature2D->getMaxFeatures(), _feature2D->getGridCols(), _feature2D->getGridRows()).c_str());
5420 wordIds = _vwd->addNewWords(descriptorsForQuantization,
id);
5423 if(wordIds.size() < keypoints.size())
5425 std::vector<int> allWordIds;
5426 allWordIds.resize(keypoints.size(),-1);
5428 for(std::list<int>::iterator
iter=wordIds.begin();
iter!=wordIds.end(); ++
iter)
5430 allWordIds[quantizedToRawIndices[
i]] = *
iter;
5434 for(i=0;
i<(
int)allWordIds.size(); ++
i)
5436 if(allWordIds[i] < 0)
5438 allWordIds[
i] = negIndex--;
5445 if(stats)
stats->addStatistic(Statistics::kTimingMemAdd_new_words(), t*1000.0f);
5446 UDEBUG(
"time addNewWords %fs indexed=%d not=%d", t, _vwd->getIndexedWordsCount(), _vwd->getNotIndexedWordsCount());
5450 UDEBUG(
"id %d is a bad signature",
id);
5453 std::multimap<int, int> words;
5454 std::vector<cv::KeyPoint> wordsKpts;
5455 std::vector<cv::Point3f> words3D;
5456 cv::Mat wordsDescriptors;
5457 int words3DValid = 0;
5458 if(wordIds.size() > 0)
5460 UASSERT(wordIds.size() == keypoints.size());
5461 UASSERT(keypoints3D.size() == 0 || keypoints3D.size() == wordIds.size());
5463 float decimationRatio =
float(preDecimation) /
float(_imagePostDecimation);
5464 double log2value =
log(
double(preDecimation))/
log(2.0);
5465 for(std::list<int>::iterator
iter=wordIds.begin();
iter!=wordIds.end() && i < keypoints.size(); ++
iter, ++i)
5467 cv::KeyPoint kpt = keypoints[
i];
5468 if(preDecimation != _imagePostDecimation)
5471 kpt.pt.x *= decimationRatio;
5472 kpt.pt.y *= decimationRatio;
5473 kpt.size *= decimationRatio;
5474 kpt.octave += log2value;
5476 words.insert(std::make_pair(*
iter, words.size()));
5477 wordsKpts.push_back(kpt);
5479 if(keypoints3D.size())
5481 words3D.push_back(keypoints3D.at(i));
5482 if(util3d::isFinite(keypoints3D.at(i)))
5487 if(_rawDescriptorsKept)
5489 wordsDescriptors.push_back(descriptors.row(i));
5495 if(_detectMarkers && !isIntermediateNode && !
data.imageRaw().empty())
5497 UDEBUG(
"Detecting markers...");
5498 if(landmarks.empty())
5500 std::vector<CameraModel> models =
data.cameraModels();
5503 for(
size_t i=0;
i<
data.stereoCameraModels().
size(); ++
i)
5505 models.push_back(
data.stereoCameraModels()[i].left());
5509 if(!models.empty() && models[0].isValidForProjection())
5511 std::map<int, MarkerInfo> markers = _markerDetector->detect(
data.imageRaw(), models,
data.depthRaw(), _landmarksSize);
5513 for(std::map<int, MarkerInfo>::iterator
iter=markers.begin();
iter!=markers.end(); ++
iter)
5515 if(
iter->first <= 0)
5517 UERROR(
"Invalid marker received! IDs should be > 0 (it is %d). Ignoring this marker.",
iter->first);
5520 cv::Mat covariance = cv::Mat::eye(6,6,CV_64FC1);
5521 covariance(cv::Range(0,3), cv::Range(0,3)) *= _markerLinVariance;
5522 covariance(cv::Range(3,6), cv::Range(3,6)) *= _markerAngVariance;
5523 landmarks.insert(std::make_pair(
iter->first, Landmark(
iter->first,
iter->second.length(),
iter->second.pose(), covariance)));
5525 UDEBUG(
"Markers detected = %d", (
int)markers.size());
5529 UWARN(
"No valid camera calibration for marker detection");
5534 UWARN(
"Input data has already landmarks, cannot do marker detection.");
5537 if(stats)
stats->addStatistic(Statistics::kTimingMemMarkers_detection(), t*1000.0f);
5538 UDEBUG(
"time markers detection = %fs", t);
5541 cv::Mat image =
data.imageRaw();
5542 cv::Mat depthOrRightImage =
data.depthOrRightRaw();
5543 std::vector<CameraModel> cameraModels =
data.cameraModels();
5544 std::vector<StereoCameraModel> stereoCameraModels =
data.stereoCameraModels();
5547 if(_imagePostDecimation > 1 && !isIntermediateNode)
5549 if(_imagePostDecimation == preDecimation && decimatedData.isValid())
5551 image = decimatedData.imageRaw();
5552 depthOrRightImage = decimatedData.depthOrRightRaw();
5553 cameraModels = decimatedData.cameraModels();
5554 stereoCameraModels = decimatedData.stereoCameraModels();
5558 int decimationDepth = _imagePreDecimation;
5559 if( !
data.cameraModels().empty() &&
5560 data.cameraModels()[0].imageHeight()>0 &&
5561 data.cameraModels()[0].imageWidth()>0)
5564 int targetSize =
data.cameraModels()[0].imageHeight() / _imagePreDecimation;
5565 if(targetSize >=
data.depthRaw().rows)
5567 decimationDepth = 1;
5571 decimationDepth = (
int)
ceil(
float(
data.depthRaw().rows) /
float(targetSize));
5574 UDEBUG(
"decimation rgbOrLeft(rows=%d)=%d, depthOrRight(rows=%d)=%d",
data.imageRaw().rows, _imagePostDecimation,
data.depthOrRightRaw().rows, decimationDepth);
5578 for(
unsigned int i=0;
i<cameraModels.size(); ++
i)
5580 cameraModels[
i] = cameraModels[
i].scaled(1.0/
double(_imagePostDecimation));
5582 for(
unsigned int i=0;
i<stereoCameraModels.size(); ++
i)
5584 stereoCameraModels[
i].scale(1.0/
double(_imagePostDecimation));
5588 if(!image.empty() && (depthOrRightImage.cols > image.cols || depthOrRightImage.rows > image.rows))
5590 UWARN(
"Depth image is bigger than RGB image after post decimation, %s=%d is too high! RGB=%dx%d, depth=%dx%d",
5591 Parameters::kMemImagePostDecimation().
c_str(), _imagePostDecimation,
5592 image.cols, image.rows, depthOrRightImage.cols, depthOrRightImage.rows);
5596 if(stats)
stats->addStatistic(Statistics::kTimingMemPost_decimation(), t*1000.0f);
5597 UDEBUG(
"time post-decimation = %fs", t);
5600 if(_stereoFromMotion &&
5602 cameraModels.size() == 1 &&
5604 (words3D.size() == 0 || (words.size() == words3D.size() && words3DValid!=(
int)words3D.size())) &&
5605 _registrationPipeline->isImageRequired() &&
5606 _signatures.size() &&
5607 _signatures.rbegin()->second->mapId() == _idMapCount)
5609 UDEBUG(
"Generate 3D words using odometry (%s=true and words3DValid=%d/%d)",
5610 Parameters::kMemStereoFromMotion().
c_str(), words3DValid, (
int)words3D.size());
5611 Signature * previousS = _signatures.rbegin()->second;
5612 if(previousS->getWords().size() > 8 && words.size() > 8 && !previousS->getPose().isNull())
5614 UDEBUG(
"Previous pose(%d) = %s", previousS->id(), previousS->getPose().prettyPrint().c_str());
5615 UDEBUG(
"Current pose(%d) = %s",
id, pose.prettyPrint().c_str());
5616 Transform cameraTransform = pose.inverse() * previousS->getPose();
5618 Signature cpPrevious(2);
5621 std::vector<cv::KeyPoint> uniqueWordsKpts;
5622 cv::Mat uniqueWordsDescriptors;
5623 std::multimap<int, int> uniqueWords;
5624 for(std::map<int, int>::iterator
iter=uniqueWordsOld.begin();
iter!=uniqueWordsOld.end(); ++
iter)
5626 uniqueWords.insert(std::make_pair(
iter->first, uniqueWords.size()));
5627 uniqueWordsKpts.push_back(previousS->getWordsKpts()[
iter->second]);
5628 uniqueWordsDescriptors.push_back(previousS->getWordsDescriptors().row(
iter->second));
5630 cpPrevious.sensorData().setCameraModels(previousS->sensorData().cameraModels());
5631 cpPrevious.setWords(uniqueWords, uniqueWordsKpts, std::vector<cv::Point3f>(), uniqueWordsDescriptors);
5632 Signature cpCurrent(1);
5634 uniqueWordsKpts.clear();
5635 uniqueWordsDescriptors = cv::Mat();
5636 uniqueWords.clear();
5637 for(std::map<int, int>::iterator
iter=uniqueWordsOld.begin();
iter!=uniqueWordsOld.end(); ++
iter)
5639 uniqueWords.insert(std::make_pair(
iter->first, uniqueWords.size()));
5640 uniqueWordsKpts.push_back(wordsKpts[
iter->second]);
5641 uniqueWordsDescriptors.push_back(wordsDescriptors.row(
iter->second));
5643 cpCurrent.sensorData().setCameraModels(cameraModels);
5645 cpCurrent.setWords(uniqueWords, uniqueWordsKpts, std::vector<cv::Point3f>(), uniqueWordsDescriptors);
5649 RegistrationVis reg(parameters_);
5650 if(_registrationPipeline->isScanRequired())
5653 RegistrationVis vis(parameters_);
5654 tmpt = vis.computeTransformationMod(cpCurrent, cpPrevious, cameraTransform);
5658 tmpt = _registrationPipeline->computeTransformationMod(cpCurrent, cpPrevious, cameraTransform);
5660 UDEBUG(
"t=%s", tmpt.prettyPrint().c_str());
5665 std::map<int, cv::KeyPoint> currentWords;
5666 std::map<int, cv::KeyPoint> previousWords;
5667 for(std::map<int, int>::iterator
iter=currentUniqueWords.begin();
iter!=currentUniqueWords.end(); ++
iter)
5669 currentWords.insert(std::make_pair(
iter->first, cpCurrent.getWordsKpts()[
iter->second]));
5671 for(std::map<int, int>::iterator
iter=previousUniqueWords.begin();
iter!=previousUniqueWords.end(); ++
iter)
5673 previousWords.insert(std::make_pair(
iter->first, cpPrevious.getWordsKpts()[
iter->second]));
5681 UDEBUG(
"inliers=%d", (
int)inliers.size());
5684 float bad_point = std::numeric_limits<float>::quiet_NaN ();
5685 UASSERT(words3D.size() == 0 || words.size() == words3D.size());
5686 bool words3DWasEmpty = words3D.empty();
5687 int added3DPointsWithoutDepth = 0;
5688 for(std::multimap<int, int>::const_iterator
iter=words.begin();
iter!=words.end(); ++
iter)
5690 std::map<int, cv::Point3f>::iterator jter=inliers.find(
iter->first);
5693 if(jter != inliers.end())
5695 words3D.push_back(jter->second);
5696 ++added3DPointsWithoutDepth;
5700 words3D.push_back(cv::Point3f(bad_point,bad_point,bad_point));
5703 else if(!util3d::isFinite(words3D[
iter->second]) && jter != inliers.end())
5705 words3D[
iter->second] = jter->second;
5706 ++added3DPointsWithoutDepth;
5709 UDEBUG(
"added3DPointsWithoutDepth=%d", added3DPointsWithoutDepth);
5710 if(stats)
stats->addStatistic(Statistics::kMemoryTriangulated_points(), (
float)added3DPointsWithoutDepth);
5713 UASSERT(words3D.size() == words.size());
5714 if(stats)
stats->addStatistic(Statistics::kTimingMemKeypoints_3D_motion(), t*1000.0f);
5715 UDEBUG(
"time keypoints 3D by motion (%d) = %fs", (
int)words3D.size(), t);
5720 LaserScan laserScan =
data.laserScanRaw();
5721 if(!isIntermediateNode && laserScan.size())
5723 if(laserScan.rangeMax() == 0.0f)
5725 bool id2d = laserScan.is2d();
5726 float maxRange = 0.0f;
5727 for(
int i=0;
i<laserScan.size(); ++
i)
5729 const float * ptr = laserScan.data().ptr<
float>(0,
i);
5733 r = ptr[0]*ptr[0] + ptr[1]*ptr[1];
5737 r = ptr[0]*ptr[0] + ptr[1]*ptr[1] + ptr[2]*ptr[2];
5746 laserScan=LaserScan(laserScan.data(), laserScan.maxPoints(),
sqrt(maxRange), laserScan.format(), laserScan.localTransform());
5751 _laserScanDownsampleStepSize,
5754 _laserScanVoxelSize,
5756 _laserScanNormalRadius,
5757 _laserScanGroundNormalsUp);
5759 if(stats)
stats->addStatistic(Statistics::kTimingMemScan_filtering(), t*1000.0f);
5760 UDEBUG(
"time normals scan = %fs", t);
5764 if(this->isBinDataKept() && (!isIntermediateNode || _saveIntermediateNodeData))
5766 UDEBUG(
"Bin data kept: rgb=%d, depth=%d, scan=%d, userData=%d",
5768 depthOrRightImage.empty()?0:1,
5769 laserScan.isEmpty()?0:1,
5770 data.userDataRaw().empty()?0:1);
5772 std::vector<unsigned char> imageBytes;
5773 std::vector<unsigned char> depthBytes;
5775 if(_saveDepth16Format && !depthOrRightImage.empty() && depthOrRightImage.type() == CV_32FC1)
5777 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).");
5781 cv::Mat compressedImage;
5782 cv::Mat compressedDepth;
5783 cv::Mat compressedScan;
5784 cv::Mat compressedUserData;
5785 if(_compressionParallelized)
5788 rtabmap::CompressionThread ctDepth(depthOrRightImage, depthOrRightImage.type() == CV_32FC1 || depthOrRightImage.type() == CV_16UC1?std::string(
".png"):_rgbCompressionFormat);
5795 if(!depthOrRightImage.empty())
5799 if(!laserScan.isEmpty())
5801 ctLaserScan.start();
5803 if(!
data.userDataRaw().empty())
5812 compressedImage = ctImage.getCompressedData();
5813 compressedDepth = ctDepth.getCompressedData();
5814 compressedScan = ctLaserScan.getCompressedData();
5815 compressedUserData = ctUserData.getCompressedData();
5820 compressedDepth =
compressImage2(depthOrRightImage, depthOrRightImage.type() == CV_32FC1 || depthOrRightImage.type() == CV_16UC1?std::string(
".png"):_rgbCompressionFormat);
5825 s =
new Signature(
id,
5827 isIntermediateNode?-1:0,
5832 !stereoCameraModels.empty()?
5834 laserScan.angleIncrement() == 0.0f?
5835 LaserScan(compressedScan,
5836 laserScan.maxPoints(),
5837 laserScan.rangeMax(),
5839 laserScan.localTransform()):
5840 LaserScan(compressedScan,
5842 laserScan.rangeMin(),
5843 laserScan.rangeMax(),
5844 laserScan.angleMin(),
5845 laserScan.angleMax(),
5846 laserScan.angleIncrement(),
5847 laserScan.localTransform()),
5853 compressedUserData):
5855 laserScan.angleIncrement() == 0.0f?
5856 LaserScan(compressedScan,
5857 laserScan.maxPoints(),
5858 laserScan.rangeMax(),
5860 laserScan.localTransform()):
5861 LaserScan(compressedScan,
5863 laserScan.rangeMin(),
5864 laserScan.rangeMax(),
5865 laserScan.angleMin(),
5866 laserScan.angleMax(),
5867 laserScan.angleIncrement(),
5868 laserScan.localTransform()),
5874 compressedUserData));
5878 UDEBUG(
"Bin data kept: scan=%d, userData=%d",
5879 laserScan.isEmpty()?0:1,
5880 data.userDataRaw().empty()?0:1);
5883 cv::Mat compressedScan;
5884 cv::Mat compressedUserData;
5885 if(_compressionParallelized)
5889 if(!
data.userDataRaw().empty() && !isIntermediateNode)
5893 if(!laserScan.isEmpty() && !isIntermediateNode)
5895 ctLaserScan.start();
5900 compressedScan = ctLaserScan.getCompressedData();
5901 compressedUserData = ctUserData.getCompressedData();
5909 s =
new Signature(
id,
5911 isIntermediateNode?-1:0,
5916 !stereoCameraModels.empty()?
5918 laserScan.angleIncrement() == 0.0f?
5919 LaserScan(compressedScan,
5920 laserScan.maxPoints(),
5921 laserScan.rangeMax(),
5923 laserScan.localTransform()):
5924 LaserScan(compressedScan,
5926 laserScan.rangeMin(),
5927 laserScan.rangeMax(),
5928 laserScan.angleMin(),
5929 laserScan.angleMax(),
5930 laserScan.angleIncrement(),
5931 laserScan.localTransform()),
5937 compressedUserData):
5939 laserScan.angleIncrement() == 0.0f?
5940 LaserScan(compressedScan,
5941 laserScan.maxPoints(),
5942 laserScan.rangeMax(),
5944 laserScan.localTransform()):
5945 LaserScan(compressedScan,
5947 laserScan.rangeMin(),
5948 laserScan.rangeMax(),
5949 laserScan.angleMin(),
5950 laserScan.angleMax(),
5951 laserScan.angleIncrement(),
5952 laserScan.localTransform()),
5958 compressedUserData));
5961 s->setWords(words, wordsKpts,
5962 _reextractLoopClosureFeatures?std::vector<cv::Point3f>():words3D,
5963 _reextractLoopClosureFeatures?cv::Mat():wordsDescriptors);
5966 if(!cameraModels.empty())
5968 s->sensorData().setRGBDImage(image, depthOrRightImage, cameraModels,
false);
5972 s->sensorData().setStereoImage(image, depthOrRightImage, stereoCameraModels,
false);
5974 s->sensorData().setLaserScan(laserScan,
false);
5975 s->sensorData().setUserData(
data.userDataRaw(),
false);
5977 UDEBUG(
"data.groundTruth() =%s",
data.groundTruth().prettyPrint().c_str());
5978 UDEBUG(
"data.gps() =%s",
data.gps().stamp()?
"true":
"false");
5979 UDEBUG(
"data.envSensors() =%d", (
int)
data.envSensors().size());
5980 UDEBUG(
"data.globalDescriptors()=%d", (
int)
data.globalDescriptors().size());
5981 s->sensorData().setGroundTruth(
data.groundTruth());
5982 s->sensorData().setGPS(
data.gps());
5983 s->sensorData().setEnvSensors(
data.envSensors());
5985 std::vector<GlobalDescriptor> globalDescriptors =
data.globalDescriptors();
5986 if(_globalDescriptorExtractor)
5988 GlobalDescriptor gdescriptor = _globalDescriptorExtractor->extract(inputData);
5989 if(!gdescriptor.data().empty())
5991 globalDescriptors.push_back(gdescriptor);
5994 s->sensorData().setGlobalDescriptors(globalDescriptors);
5997 if(stats)
stats->addStatistic(Statistics::kTimingMemCompressing_data(), t*1000.0f);
5998 UDEBUG(
"time compressing data (id=%d) %fs",
id, t);
6001 s->setEnabled(
true);
6005 if(_createOccupancyGrid && !isIntermediateNode)
6007 if( (_localMapMaker->isGridFromDepth() && !
data.depthOrRightRaw().empty()) ||
6008 (!_localMapMaker->isGridFromDepth() && !
data.laserScanRaw().empty()))
6010 cv::Mat ground, obstacles,
empty;
6011 float cellSize = 0.0f;
6012 cv::Point3f viewPoint(0,0,0);
6013 _localMapMaker->createLocalMap(*s, ground, obstacles,
empty, viewPoint);
6014 cellSize = _localMapMaker->getCellSize();
6015 s->sensorData().setOccupancyGrid(ground, obstacles,
empty, cellSize, viewPoint);
6018 if(stats)
stats->addStatistic(Statistics::kTimingMemOccupancy_grid(), t*1000.0f);
6019 UDEBUG(
"time grid map = %fs", t);
6021 else if(
data.gridCellSize() != 0.0f)
6023 s->sensorData().setOccupancyGrid(
6024 data.gridGroundCellsRaw(),
6025 data.gridObstacleCellsRaw(),
6026 data.gridEmptyCellsRaw(),
6027 data.gridCellSize(),
6028 data.gridViewPoint());
6033 if(!
data.globalPose().isNull() &&
data.globalPoseCovariance().cols==6 &&
data.globalPoseCovariance().rows==6 &&
data.globalPoseCovariance().cols==CV_64FC1)
6035 s->addLink(Link(
s->id(),
s->id(), Link::kPosePrior,
data.globalPose(),
data.globalPoseCovariance().inv()));
6036 UDEBUG(
"Added global pose prior: %s",
data.globalPose().prettyPrint().c_str());
6038 if(
data.gps().stamp() > 0.0)
6040 UWARN(
"GPS constraint ignored as global pose is also set.");
6043 else if(
data.gps().stamp() > 0.0)
6050 data.gps().error() > 0.0)
6052 if(_gpsOrigin.stamp() <= 0.0)
6054 _gpsOrigin =
data.gps();
6055 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());
6057 cv::Point3f pt =
data.gps().toGeodeticCoords().toENU_WGS84(_gpsOrigin.toGeodeticCoords());
6058 Transform gpsPose(pt.x, pt.y, pose.z(), 0, 0, -(
data.gps().bearing()-90.0)*
M_PI/180.0);
6059 cv::Mat gpsInfMatrix = cv::Mat::eye(6,6,CV_64FC1)/9999.0;
6061 UDEBUG(
"Added GPS prior: x=%f y=%f z=%f yaw=%f", gpsPose.x(), gpsPose.y(), gpsPose.z(), gpsPose.theta());
6063 gpsInfMatrix.at<
double>(0,0) = gpsInfMatrix.at<
double>(1,1) = 1.0/
data.gps().error();
6064 gpsInfMatrix.at<
double>(2,2) = 1;
6065 s->addLink(Link(
s->id(),
s->id(), Link::kPosePrior, gpsPose, gpsInfMatrix));
6069 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());
6074 if(_useOdometryGravity && !pose.isNull())
6076 s->addLink(Link(
s->id(),
s->id(), Link::kGravity, pose.rotation()));
6077 UDEBUG(
"Added gravity constraint from odom pose: %s", pose.rotation().prettyPrint().c_str());
6079 else if(!
data.imu().localTransform().isNull() &&
6080 (
data.imu().orientation()[0] != 0 ||
6081 data.imu().orientation()[1] != 0 ||
6082 data.imu().orientation()[2] != 0 ||
6083 data.imu().orientation()[3] != 0))
6086 Transform
orientation(0,0,0,
data.imu().orientation()[0],
data.imu().orientation()[1],
data.imu().orientation()[2],
data.imu().orientation()[3]);
6095 for(Landmarks::const_iterator
iter = landmarks.begin();
iter!=landmarks.end(); ++
iter)
6097 if(
iter->second.id() > 0)
6099 int landmarkId = -
iter->first;
6100 cv::Mat landmarkSize;
6101 if(
iter->second.size() > 0.0f)
6103 landmarkSize = cv::Mat(1,1,CV_32FC1);
6104 landmarkSize.at<
float>(0,0) =
iter->second.size();
6106 std::pair<std::map<int, float>::iterator,
bool> inserted=_landmarksSize.insert(std::make_pair(
iter->first,
iter->second.size()));
6107 if(!inserted.second)
6109 if(inserted.first->second != landmarkSize.at<
float>(0,0))
6111 UWARN(
"Trying to update landmark size buffer for landmark %d with size=%f but "
6112 "it has already a different size set. Keeping old size (%f).",
6113 -landmarkId, inserted.first->second, landmarkSize.at<
float>(0,0));
6119 Transform landmarkPose =
iter->second.pose();
6120 if(_registrationPipeline->force3DoF())
6125 if(
fabs(tx.
z()) > 0.9)
6129 else if(
fabs(ty.
z()) > 0.9)
6135 Link landmark(
s->id(), landmarkId, Link::kLandmark, landmarkPose,
iter->second.covariance().inv(), landmarkSize);
6136 s->addLandmark(landmark);
6139 std::map<int, std::set<int> >
::iterator nter = _landmarksIndex.find(landmarkId);
6140 if(nter!=_landmarksIndex.end())
6142 nter->second.insert(
s->id());
6147 tmp.insert(
s->id());
6148 _landmarksIndex.insert(std::make_pair(landmarkId, tmp));
6153 UERROR(
"Invalid landmark received! IDs should be > 0 (it is %d). Ignoring this landmark.",
iter->second.id());
6160 void Memory::disableWordsRef(
int signatureId)
6162 UDEBUG(
"id=%d", signatureId);
6164 Signature * ss = this->_getSignature(signatureId);
6167 const std::multimap<int, int> & words = ss->
getWords();
6169 int count = _vwd->getTotalActiveReferences();
6171 for(std::list<int>::const_iterator
i=
keys.begin();
i!=
keys.end(); ++
i)
6173 _vwd->removeAllWordRef(*
i, signatureId);
6176 count -= _vwd->getTotalActiveReferences();
6178 UDEBUG(
"%d words total ref removed from signature %d... (total active ref = %d)",
count, ss->
id(), _vwd->getTotalActiveReferences());
6182 void Memory::cleanUnusedWords()
6184 std::vector<VisualWord*> removedWords = _vwd->getUnusedWords();
6185 UDEBUG(
"Removing %d words (dictionary size=%d)...", removedWords.size(), _vwd->getVisualWords().size());
6186 if(removedWords.size())
6189 _vwd->removeWords(removedWords);
6191 for(
unsigned int i=0;
i<removedWords.size(); ++
i)
6195 _dbDriver->asyncSave(removedWords[
i]);
6199 delete removedWords[
i];
6205 void Memory::enableWordsRef(
const std::list<int> & signatureIds)
6207 UDEBUG(
"size=%d", signatureIds.size());
6211 std::map<int, int> refsToChange;
6213 std::set<int> oldWordIds;
6214 std::list<Signature *> surfSigns;
6215 for(std::list<int>::const_iterator
i=signatureIds.begin();
i!=signatureIds.end(); ++
i)
6220 surfSigns.push_back(ss);
6224 for(std::list<int>::const_iterator k=uniqueKeys.begin(); k!=uniqueKeys.end(); ++k)
6226 if(*k>0 && _vwd->getWord(*k) == 0 && _vwd->getUnusedWord(*k) == 0)
6228 oldWordIds.insert(oldWordIds.end(), *k);
6234 if(!_vwd->isIncremental() && oldWordIds.size())
6236 UWARN(
"Dictionary is fixed, but some words retrieved have not been found!?");
6239 UDEBUG(
"oldWordIds.size()=%d, getOldIds time=%fs", oldWordIds.size(),
timer.ticks());
6242 std::list<VisualWord *> vws;
6243 if(oldWordIds.size() && _dbDriver)
6246 _dbDriver->loadWords(oldWordIds, vws);
6248 UDEBUG(
"loading words(%d) time=%fs", oldWordIds.size(),
timer.ticks());
6254 std::vector<int> vwActiveIds = _vwd->findNN(vws);
6255 UDEBUG(
"find active ids (number=%d) time=%fs", vws.size(),
timer.ticks());
6257 for(std::list<VisualWord *>::iterator iterVws=vws.begin(); iterVws!=vws.end(); ++iterVws)
6259 if(vwActiveIds[
i] > 0)
6262 refsToChange.insert(refsToChange.end(), std::pair<int, int>((*iterVws)->id(), vwActiveIds[
i]));
6263 if((*iterVws)->isSaved())
6269 _dbDriver->asyncSave(*iterVws);
6275 _vwd->addWord(*iterVws);
6279 UDEBUG(
"Added %d to dictionary, time=%fs", vws.size()-refsToChange.size(),
timer.ticks());
6282 for(std::map<int, int>::const_iterator
iter=refsToChange.begin();
iter != refsToChange.end(); ++
iter)
6285 for(std::list<Signature *>::iterator
j=surfSigns.begin();
j!=surfSigns.end(); ++
j)
6287 (*j)->changeWordsRef(
iter->first,
iter->second);
6290 UDEBUG(
"changing ref, total=%d, time=%fs", refsToChange.size(),
timer.ticks());
6293 int count = _vwd->getTotalActiveReferences();
6296 for(std::list<Signature *>::iterator
j=surfSigns.begin();
j!=surfSigns.end(); ++
j)
6298 const std::vector<int> &
keys =
uKeys((*j)->getWords());
6302 for(
unsigned int i=0;
i<
keys.size(); ++
i)
6306 _vwd->addWordRef(
keys.at(
i), (*j)->id());
6309 (*j)->setEnabled(
true);
6313 count = _vwd->getTotalActiveReferences() -
count;
6314 UDEBUG(
"%d words total ref added from %d signatures, time=%fs...",
count, surfSigns.size(),
timer.ticks());
6317 std::set<int> Memory::reactivateSignatures(
const std::list<int> & ids,
unsigned int maxLoaded,
double & timeDbAccess)
6325 std::list<int> idsToLoad;
6326 std::map<int, int>::iterator wmIter;
6327 for(std::list<int>::const_iterator
i=ids.begin();
i!=ids.end(); ++
i)
6329 if(!this->getSignature(*
i) && !
uContains(idsToLoad, *
i))
6331 if(!maxLoaded || idsToLoad.size() < maxLoaded)
6333 idsToLoad.push_back(*
i);
6334 UINFO(
"Loading location %d from database...", *
i);
6339 UDEBUG(
"idsToLoad = %d", idsToLoad.size());
6341 std::list<Signature *> reactivatedSigns;
6344 _dbDriver->loadSignatures(idsToLoad, reactivatedSigns);
6346 timeDbAccess =
timer.getElapsedTime();
6347 std::list<int> idsLoaded;
6348 for(std::list<Signature *>::iterator
i=reactivatedSigns.begin();
i!=reactivatedSigns.end(); ++
i)
6350 if(!(*i)->getLandmarks().empty())
6353 for(std::map<int, Link>::const_iterator
iter = (*i)->getLandmarks().begin();
iter!=(*i)->getLandmarks().end(); ++
iter)
6355 int landmarkId =
iter->first;
6358 cv::Mat landmarkSize =
iter->second.uncompressUserDataConst();
6359 if(!landmarkSize.empty() && landmarkSize.type() == CV_32FC1 && landmarkSize.total()==1)
6361 std::pair<std::map<int, float>::iterator,
bool> inserted=_landmarksSize.insert(std::make_pair(-landmarkId, landmarkSize.at<
float>(0,0)));
6362 if(!inserted.second)
6364 if(inserted.first->second != landmarkSize.at<
float>(0,0))
6366 UWARN(
"Trying to update landmark size buffer for landmark %d with size=%f but "
6367 "it has already a different size set. Keeping old size (%f).",
6368 -landmarkId, inserted.first->second, landmarkSize.at<
float>(0,0));
6373 std::map<int, std::set<int> >
::iterator nter = _landmarksIndex.find(landmarkId);
6374 if(nter!=_landmarksIndex.end())
6376 nter->second.insert((*i)->id());
6381 tmp.insert((*i)->id());
6382 _landmarksIndex.insert(std::make_pair(landmarkId, tmp));
6387 idsLoaded.push_back((*i)->id());
6389 this->addSignatureToWmFromLTM(*
i);
6391 this->enableWordsRef(idsLoaded);
6393 return std::set<int>(idsToLoad.begin(), idsToLoad.end());
6398 void Memory::getMetricConstraints(
6399 const std::set<int> & ids,
6400 std::map<int, Transform> & poses,
6401 std::multimap<int, Link> & links,
6402 bool lookInDatabase,
6403 bool landmarksAdded)
6406 for(std::set<int>::const_iterator
iter=ids.begin();
iter!=ids.end(); ++
iter)
6411 poses.insert(std::make_pair(*
iter, pose));
6415 for(std::set<int>::const_iterator
iter=ids.begin();
iter!=ids.end(); ++
iter)
6419 std::multimap<int, Link> tmpLinks = getLinks(*
iter, lookInDatabase,
true);
6420 for(std::multimap<int, Link>::iterator jter=tmpLinks.begin(); jter!=tmpLinks.end(); ++jter)
6422 std::multimap<int, Link>::iterator addedLinksIterator =
graph::findLink(links, *
iter, jter->first);
6423 if( jter->second.isValid() &&
6424 (addedLinksIterator == links.end() || addedLinksIterator->second.from()==addedLinksIterator->second.to()) &&
6425 (
uContains(poses, jter->first) || (landmarksAdded && jter->second.type() == Link::kLandmark)))
6427 if(!lookInDatabase &&
6428 (jter->second.type() == Link::kNeighbor ||
6429 jter->second.type() == Link::kNeighborMerged))
6431 const Signature *
s = this->getSignature(jter->first);
6433 if(
s->getWeight() == -1)
6435 Link link = jter->second;
6436 while(
s &&
s->getWeight() == -1)
6440 std::multimap<int, Link>
n = this->getNeighborLinks(
s->id(),
false);
6442 std::multimap<int, Link>::iterator uter =
n.upper_bound(
s->id());
6445 const Signature * s2 = this->getSignature(uter->first);
6448 link = link.
merge(uter->second, uter->second.type());
6449 poses.erase(
s->id());
6459 links.insert(std::make_pair(*
iter, link));
6463 links.insert(std::make_pair(*
iter, jter->second));
6466 else if(jter->second.type() != Link::kLandmark)
6468 links.insert(std::make_pair(*
iter, jter->second));
6470 else if(landmarksAdded)
6474 poses.insert(std::make_pair(jter->first, poses.at(*
iter) * jter->second.transform()));
6476 links.insert(std::make_pair(jter->first, jter->second.inverse()));