61 #include <pcl/io/pcd_io.h> 62 #include <pcl/common/common.h> 64 #include <opencv2/imgproc/types_c.h> 74 _similarityThreshold(
Parameters::defaultMemRehearsalSimilarity()),
75 _binDataKept(
Parameters::defaultMemBinDataKept()),
76 _rawDescriptorsKept(
Parameters::defaultMemRawDescriptorsKept()),
77 _saveDepth16Format(
Parameters::defaultMemSaveDepth16Format()),
78 _notLinkedNodesKeptInDb(
Parameters::defaultMemNotLinkedNodesKept()),
79 _saveIntermediateNodeData(
Parameters::defaultMemIntermediateNodeDataKept()),
80 _incrementalMemory(
Parameters::defaultMemIncrementalMemory()),
81 _reduceGraph(
Parameters::defaultMemReduceGraph()),
82 _maxStMemSize(
Parameters::defaultMemSTMSize()),
83 _recentWmRatio(
Parameters::defaultMemRecentWmRatio()),
84 _transferSortingByWeightId(
Parameters::defaultMemTransferSortingByWeightId()),
85 _idUpdatedToNewOneRehearsal(
Parameters::defaultMemRehearsalIdUpdatedToNewOne()),
86 _generateIds(
Parameters::defaultMemGenerateIds()),
87 _badSignaturesIgnored(
Parameters::defaultMemBadSignaturesIgnored()),
88 _mapLabelsAdded(
Parameters::defaultMemMapLabelsAdded()),
89 _depthAsMask(
Parameters::defaultMemDepthAsMask()),
90 _imagePreDecimation(
Parameters::defaultMemImagePreDecimation()),
91 _imagePostDecimation(
Parameters::defaultMemImagePostDecimation()),
92 _compressionParallelized(
Parameters::defaultMemCompressionParallelized()),
93 _laserScanDownsampleStepSize(
Parameters::defaultMemLaserScanDownsampleStepSize()),
94 _laserScanVoxelSize(
Parameters::defaultMemLaserScanVoxelSize()),
95 _laserScanNormalK(
Parameters::defaultMemLaserScanNormalK()),
96 _laserScanNormalRadius(
Parameters::defaultMemLaserScanNormalRadius()),
97 _reextractLoopClosureFeatures(
Parameters::defaultRGBDLoopClosureReextractFeatures()),
98 _localBundleOnLoopClosure(
Parameters::defaultRGBDLocalBundleOnLoopClosure()),
99 _rehearsalMaxDistance(
Parameters::defaultRGBDLinearUpdate()),
100 _rehearsalMaxAngle(
Parameters::defaultRGBDAngularUpdate()),
101 _rehearsalWeightIgnoredWhileMoving(
Parameters::defaultMemRehearsalWeightIgnoredWhileMoving()),
102 _useOdometryFeatures(
Parameters::defaultMemUseOdomFeatures()),
103 _createOccupancyGrid(
Parameters::defaultRGBDCreateOccupancyGrid()),
104 _visMaxFeatures(
Parameters::defaultVisMaxFeatures()),
106 _imagesAlreadyRectified(
Parameters::defaultRtabmapImagesAlreadyRectified()),
107 _rectifyOnlyFeatures(
Parameters::defaultRtabmapRectifyOnlyFeatures()),
108 _covOffDiagonalIgnored(
Parameters::defaultMemCovOffDiagIgnored()),
110 _idMapCount(kIdStart),
112 _lastGlobalLoopClosureId(0),
113 _memoryChanged(
false),
114 _linksChanged(
false),
117 _badSignRatio(
Parameters::defaultKpBadSignRatio()),
118 _tfIdfLikelihoodUsed(
Parameters::defaultKpTfIdfLikelihoodUsed()),
119 _parallelized(
Parameters::defaultKpParallelized())
126 float corRatio = Parameters::defaultIcpCorrespondenceRatio();
132 UWARN(
"%s is >=0.5, which sets correspondence ratio for proximity detection using " 133 "laser scans to 100% (2 x Ratio). You may lower the ratio to accept proximity " 134 "detection with not full scans overlapping.", Parameters::kIcpCorrespondenceRatio().c_str());
211 bool loadAllNodesInWM = Parameters::defaultMemInitWMWithAllNodes();
215 std::list<Signature*> dbSignatures;
230 for(std::list<Signature*>::reverse_iterator iter=dbSignatures.rbegin(); iter!=dbSignatures.rend(); ++iter)
240 _signatures.insert(std::pair<int, Signature *>((*iter)->id(), *iter));
266 UDEBUG(
"Loading dictionary...");
269 UDEBUG(
"load all referenced words in working memory");
271 std::set<int> wordIds;
272 const std::map<int, Signature *> & signatures = this->
getSignatures();
273 for(std::map<int, Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i)
275 const std::multimap<int, cv::KeyPoint> & words = i->second->getWords();
277 for(std::list<int>::iterator iter=keys.begin(); iter!=keys.end(); ++iter)
281 wordIds.insert(*iter);
286 UDEBUG(
"load words %d", (
int)wordIds.size());
291 std::list<VisualWord*> words;
293 for(std::list<VisualWord*>::iterator iter = words.begin(); iter!=words.end(); ++iter)
320 const std::map<int, Signature *> & signatures = this->
getSignatures();
321 for(std::map<int, Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i)
326 const std::multimap<int, cv::KeyPoint> & words = s->
getWords();
329 UDEBUG(
"node=%d, word references=%d", s->
id(), words.size());
330 for(std::multimap<int, cv::KeyPoint>::const_iterator iter = words.begin(); iter!=words.end(); ++iter)
353 parameters.erase(Parameters::kRtabmapWorkingDirectory());
370 void Memory::close(
bool databaseSaved,
bool postInitClosingEvents,
const std::string & ouputDatabasePath)
372 UINFO(
"databaseSaved=%d, postInitClosingEvents=%d", databaseSaved?1:0, postInitClosingEvents?1:0);
375 bool databaseNameChanged =
false;
385 UINFO(
"No changes added to database.");
400 UINFO(
"Saving memory...");
433 UWARN(
"Please call Memory::close() before");
448 ParametersMap::const_iterator iter;
483 UWARN(
"%s is not 0 (Features Matching), the only approach supported for loop closure transformation estimation. Setting to 0...",
484 Parameters::kVisCorType().c_str());
526 if((iter=params.find(Parameters::kKpDetectorStrategy())) != params.end())
534 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));
538 UINFO(
"new detector strategy %d.",
int(detectorStrategy));
554 if((iter=params.find(Parameters::kRegStrategy())) != params.end())
560 UDEBUG(
"new registration strategy %d",
int(regStrategy));
576 if(
uContains(params, Parameters::kIcpCorrespondenceRatio()))
579 float corRatio = Parameters::defaultIcpCorrespondenceRatio();
585 UWARN(
"%s is >=0.5, which sets correspondence ratio for proximity detection using " 586 "laser scans to 100% (2 x Ratio). You may lower the ratio to accept proximity " 587 "detection with not full scans overlapping.", Parameters::kIcpCorrespondenceRatio().c_str());
604 iter = params.find(Parameters::kMemIncrementalMemory());
605 if(iter != params.end())
607 bool value =
uStr2Bool(iter->second.c_str());
617 UWARN(
"Switching from Mapping to Localization mode, the database will be saved and reloaded.");
624 UWARN(
"Switching from Mapping to Localization mode, the database is reloaded!");
632 int visFeatureType = Parameters::defaultVisFeatureType();
633 int kpDetectorStrategy = Parameters::defaultKpDetectorStrategy();
636 if(visFeatureType != kpDetectorStrategy)
638 UWARN(
"%s is enabled, but %s and %s parameters are not the same! Disabling %s...",
639 Parameters::kMemUseOdomFeatures().c_str(),
640 Parameters::kVisFeatureType().c_str(),
641 Parameters::kKpDetectorStrategy().c_str(),
642 Parameters::kMemUseOdomFeatures().c_str());
667 return update(data,
Transform(), cv::Mat(), std::vector<float>(), stats);
673 const cv::Mat & covariance,
674 const std::vector<float> & velocity,
686 UDEBUG(
"pre-updating...");
688 t=timer.
ticks()*1000;
689 if(stats) stats->
addStatistic(Statistics::kTimingMemPre_update(), t);
690 UDEBUG(
"time preUpdate=%f ms", t);
698 UERROR(
"Failed to create a signature...");
701 if(velocity.size()==6)
703 signature->
setVelocity(velocity[0], velocity[1], velocity[2], velocity[3], velocity[4], velocity[5]);
706 t=timer.
ticks()*1000;
707 if(stats) stats->
addStatistic(Statistics::kTimingMemSignature_creation(), t);
708 UDEBUG(
"time creating signature=%f ms", t);
727 t=timer.
ticks()*1000;
728 if(stats) stats->
addStatistic(Statistics::kTimingMemRehearsal(), t);
729 UDEBUG(
"time rehearsal=%f ms", t);
735 UWARN(
"The working memory is empty and the memory is not " 736 "incremental (Mem/IncrementalMemory=False), no loop closure " 737 "can be detected! Please set Mem/IncrementalMemory=true to increase " 738 "the memory with new images or decrease the STM size (which is %d " 739 "including the new one added).", (
int)
_stMem.size());
746 int notIntermediateNodesCount = 0;
747 for(std::set<int>::iterator iter=
_stMem.begin(); iter!=
_stMem.end(); ++iter)
753 ++notIntermediateNodesCount;
756 std::map<int, int> reducedIds;
764 --notIntermediateNodesCount;
772 reducedIds.insert(std::make_pair(
id, reducedTo));
793 UDEBUG(
"adding %d", signature->
id());
803 UASSERT(covariance.cols == 6 && covariance.rows == 6 && covariance.type() == CV_64FC1);
804 double maxAngVar =
uMax3(covariance.at<
double>(3,3), covariance.at<
double>(4,4), covariance.at<
double>(5,5));
805 if(maxAngVar != 1.0 && maxAngVar > 0.1)
807 UWARN(
"Very large angular variance (%f) detected! Please fix odometry " 808 "twist covariance, otherwise poor graph optimizations are " 809 "expected and wrong loop closure detections creating a lot " 810 "of errors in the map could be accepted.", maxAngVar);
816 infMatrix = cv::Mat::zeros(6,6,CV_64FC1);
817 infMatrix.at<
double>(0,0) = 1.0 / covariance.at<
double>(0,0);
818 infMatrix.at<
double>(1,1) = 1.0 / covariance.at<
double>(1,1);
819 infMatrix.at<
double>(2,2) = 1.0 / covariance.at<
double>(2,2);
820 infMatrix.at<
double>(3,3) = 1.0 / covariance.at<
double>(3,3);
821 infMatrix.at<
double>(4,4) = 1.0 / covariance.at<
double>(4,4);
822 infMatrix.at<
double>(5,5) = 1.0 / covariance.at<
double>(5,5);
826 infMatrix = covariance.inv();
828 if((
uIsFinite(covariance.at<
double>(0,0)) && covariance.at<
double>(0,0)>0.0) &&
829 !(
uIsFinite(infMatrix.at<
double>(0,0)) && infMatrix.at<
double>(0,0)>0.0))
831 UERROR(
"Failed to invert the covariance matrix! Covariance matrix should be invertible!");
832 std::cout <<
"Covariance: " << covariance << std::endl;
833 infMatrix = cv::Mat::eye(6,6,CV_64FC1);
848 UDEBUG(
"Ignoring neighbor link between %d and %d because they are not in the same map! (%d vs %d)",
858 UINFO(
"Tagging node %d with label \"%s\"", signature->
id(), tag.c_str());
870 UINFO(
"Tagging node %d with label \"%s\"", signature->
id(), tag.c_str());
881 UDEBUG(
"%d words ref for the signature %d", signature->
getWords().size(), signature->
id());
896 UDEBUG(
"Inserting node %d in WM...", signature->
id());
898 _signatures.insert(std::pair<int, Signature*>(signature->
id(), signature));
903 UERROR(
"Signature is null ?!?");
909 UDEBUG(
"Inserting node %d from STM in WM...",
id);
917 const std::map<int, Link> & links = s->getLinks();
918 std::map<int, Link> neighbors;
919 for(std::map<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
923 merge = iter->second.to() < s->id() &&
924 iter->second.to() != iter->second.from() &&
927 iter->second.userDataCompressed().empty() &&
932 UDEBUG(
"Reduce %d to %d", s->id(), iter->second.to());
935 *reducedTo = iter->second.to();
942 neighbors.insert(*iter);
947 if(s->getLabel().empty())
949 for(std::map<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
960 for(std::map<int, Link>::iterator jter=neighbors.begin(); jter!=neighbors.end(); ++jter)
962 if(!sTo->
hasLink(jter->second.to()))
978 std::map<int, Link> linksCopy = links;
979 for(std::map<int, Link>::iterator iter=linksCopy.begin(); iter!=linksCopy.end(); ++iter)
984 s->removeLink(iter->first);
1025 bool lookInDatabase)
const 1027 std::map<int, Link> links;
1031 const std::map<int, Link> & allLinks = s->
getLinks();
1032 for(std::map<int, Link>::const_iterator iter = allLinks.begin(); iter!=allLinks.end(); ++iter)
1037 links.insert(*iter);
1043 std::map<int, Link> neighbors;
1045 for(std::map<int, Link>::iterator iter=neighbors.begin(); iter!=neighbors.end();)
1050 neighbors.erase(iter++);
1060 UWARN(
"Cannot find signature %d in memory", signatureId);
1067 bool lookInDatabase)
const 1070 std::map<int, Link> loopClosures;
1073 const std::map<int, Link> & allLinks = s->
getLinks();
1074 for(std::map<int, Link>::const_iterator iter = allLinks.begin(); iter!=allLinks.end(); ++iter)
1081 loopClosures.insert(*iter);
1088 for(std::map<int, Link>::iterator iter=loopClosures.begin(); iter!=loopClosures.end();)
1094 loopClosures.erase(iter++);
1102 return loopClosures;
1107 bool lookInDatabase)
const 1109 std::map<int, Link> links;
1121 UWARN(
"Cannot find signature %d in memory", signatureId);
1128 std::multimap<int, Link> links;
1137 links.erase(iter->first);
1138 for(std::map<int, Link>::const_iterator jter=iter->second->getLinks().begin();
1139 jter!=iter->second->getLinks().end();
1142 if(!ignoreNullLinks || jter->second.isValid())
1144 links.insert(std::make_pair(iter->first, jter->second));
1159 int maxCheckedInDatabase,
1160 bool incrementMarginOnLoop,
1162 bool ignoreIntermediateNodes,
1163 bool ignoreLocalSpaceLoopIds,
1164 const std::set<int> & nodesSet,
1165 double * dbAccessTime
1174 std::map<int, int> ids;
1179 int nbLoadedFromDb = 0;
1180 std::list<int> curentMarginList;
1181 std::set<int> currentMargin;
1182 std::set<int> nextMargin;
1183 nextMargin.insert(signatureId);
1185 std::set<int> ignoredIds;
1186 while((maxGraphDepth == 0 || m < maxGraphDepth) && nextMargin.size())
1189 curentMarginList = std::list<int>(nextMargin.rbegin(), nextMargin.rend());
1192 for(std::list<int>::iterator jter = curentMarginList.begin(); jter!=curentMarginList.end(); ++jter)
1194 if(ids.find(*jter) == ids.end() && (nodesSet.empty() || nodesSet.find(*jter) != nodesSet.end()))
1199 std::map<int, Link> tmpLinks;
1200 const std::map<int, Link> * links = &tmpLinks;
1203 if(!ignoreIntermediateNodes || s->
getWeight() != -1)
1205 ids.insert(std::pair<int, int>(*jter, m));
1209 ignoredIds.insert(*jter);
1214 else if(maxCheckedInDatabase == -1 || (maxCheckedInDatabase > 0 &&
_dbDriver && nbLoadedFromDb < maxCheckedInDatabase))
1217 ids.insert(std::pair<int, int>(*jter, m));
1228 for(std::map<int, Link>::const_iterator iter=links->begin(); iter!=links->end(); ++iter)
1230 if( !
uContains(ids, iter->first) && ignoredIds.find(iter->first) == ignoredIds.end())
1236 if(ignoreIntermediateNodes && s->
getWeight()==-1)
1239 if(currentMargin.insert(iter->first).second)
1241 curentMarginList.push_back(iter->first);
1246 nextMargin.insert(iter->first);
1251 if(incrementMarginOnLoop)
1253 nextMargin.insert(iter->first);
1257 if(currentMargin.insert(iter->first).second)
1259 curentMarginList.push_back(iter->first);
1276 const std::map<int, Transform> & optimizedPoses,
1283 std::map<int, float> ids;
1284 std::map<int, float> checkedIds;
1285 std::list<int> curentMarginList;
1286 std::set<int> currentMargin;
1287 std::set<int> nextMargin;
1288 nextMargin.insert(signatureId);
1290 Transform referential = optimizedPoses.at(signatureId);
1292 float radiusSqrd = radius*radius;
1293 while((maxGraphDepth == 0 || m < maxGraphDepth) && nextMargin.size())
1295 curentMarginList = std::list<int>(nextMargin.begin(), nextMargin.end());
1298 for(std::list<int>::iterator jter = curentMarginList.begin(); jter!=curentMarginList.end(); ++jter)
1300 if(checkedIds.find(*jter) == checkedIds.end())
1305 std::map<int, Link> tmpLinks;
1306 const std::map<int, Link> * links = &tmpLinks;
1309 const Transform & t = optimizedPoses.at(*jter);
1312 if(radiusSqrd == 0 || distanceSqrd<radiusSqrd)
1314 ids.insert(std::pair<int, float>(*jter,distanceSqrd));
1321 for(std::map<int, Link>::const_iterator iter=links->begin(); iter!=links->end(); ++iter)
1324 uContains(optimizedPoses, iter->first) &&
1327 nextMargin.insert(iter->first);
1352 int id = *
_stMem.begin();
1354 if(reducedIds && reducedId > 0)
1356 reducedIds->insert(std::make_pair(
id, reducedId));
1367 std::map<int, double>::iterator iter=
_workingMem.find(signatureId);
1387 std::string version =
"0.0.0";
1397 std::string url =
"";
1417 for(std::map<int, Signature*>::const_iterator iter =
_signatures.begin(); iter!=
_signatures.end(); ++iter)
1419 ids.insert(iter->first);
1464 uFormat(
"The number of signatures don't match! _workingMem=%d, _stMem=%d, _signatures=%d",
1467 UDEBUG(
"Adding statistics after run...");
1472 parameters.erase(Parameters::kRtabmapWorkingDirectory());
1486 for(std::map<int, Signature *>::iterator i=mem.begin(); i!=mem.end(); ++i)
1490 UDEBUG(
"deleting from the working and the short-term memory: %d", i->first);
1551 std::map<int, float> likelihood;
1558 else if(ids.empty())
1560 UWARN(
"ids list is empty");
1564 for(std::list<int>::const_iterator iter = ids.begin(); iter!=ids.end(); ++iter)
1572 UFATAL(
"Signature %d not found in WM ?!?", *iter);
1577 likelihood.insert(likelihood.end(), std::pair<int, float>(*iter, sim));
1580 UDEBUG(
"compute likelihood (similarity)... %f s", timer.
ticks());
1587 std::map<int, float> likelihood;
1588 std::map<int, float> calculatedWordsRatio;
1595 else if(ids.empty())
1597 UWARN(
"ids list is empty");
1601 for(std::list<int>::const_iterator iter = ids.begin(); iter!=ids.end(); ++iter)
1603 likelihood.insert(likelihood.end(), std::pair<int, float>(*iter, 0.0f));
1620 UDEBUG(
"processing... ");
1622 for(std::list<int>::const_iterator i=wordIds.begin(); i!=wordIds.end(); ++i)
1634 logNnw = log10(N/nw);
1637 for(std::map<int, int>::const_iterator j=refs.begin(); j!=refs.end(); ++j)
1639 std::map<int, float>::iterator iter = likelihood.find(j->first);
1640 if(iter != likelihood.end())
1643 ni = this->
getNi(j->first);
1647 iter->second += ( nwi * logNnw ) / ni;
1657 UDEBUG(
"compute likelihood (tf-idf) %f s", timer.
ticks());
1665 std::map<int, int> weights;
1673 UFATAL(
"Location %d must exist in memory", iter->first);
1675 weights.insert(weights.end(), std::make_pair(iter->first, s->
getWeight()));
1679 weights.insert(weights.end(), std::make_pair(iter->first, -1));
1688 std::list<int> signaturesRemoved;
1699 int wordsRemoved = 0;
1706 while(wordsRemoved < newWords)
1709 if(signatures.size())
1714 signaturesRemoved.push_back(s->
id());
1728 UDEBUG(
"newWords=%d, wordsRemoved=%d", newWords, wordsRemoved);
1736 for(std::list<Signature *>::iterator iter=signatures.begin(); iter!=signatures.end(); ++iter)
1738 signaturesRemoved.push_back((*iter)->id());
1743 if((
int)signatures.size() < signaturesAdded)
1745 UWARN(
"Less signatures transferred (%d) than added (%d)! The working memory cannot decrease in size.",
1746 (
int)signatures.size(), signaturesAdded);
1750 UDEBUG(
"signaturesRemoved=%d, _signaturesAdded=%d", (
int)signatures.size(), signaturesAdded);
1753 return signaturesRemoved;
1760 int signatureRemoved = 0;
1773 return signatureRemoved;
1814 return std::map<int, Transform>();
1835 const cv::Mat & cloud,
1836 const std::vector<std::vector<std::vector<unsigned int> > > & polygons,
1837 #
if PCL_VERSION_COMPARE(>=, 1, 8, 0)
1838 const std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > & texCoords,
1840 const std::vector<std::vector<Eigen::Vector2f> > & texCoords,
1842 const cv::Mat & textures)
const 1851 std::vector<std::vector<std::vector<unsigned int> > > * polygons,
1852 #
if PCL_VERSION_COMPARE(>=, 1, 8, 0)
1853 std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > * texCoords,
1855 std::vector<std::vector<Eigen::Vector2f> > * texCoords,
1857 cv::Mat * textures)
const 1897 else if(weight == k.
weight)
1903 else if(age == k.
age)
1918 std::list<Signature *> removableSignatures;
1919 std::map<WeightAgeIdKey, Signature *> weightAgeIdMap;
1922 UDEBUG(
"mem.size()=%d, ignoredIds.size()=%d", (
int)
_workingMem.size(), (int)ignoredIds.size());
1927 bool recentWmImmunized =
false;
1929 int currentRecentWmSize = 0;
1936 ++currentRecentWmSize;
1939 if(currentRecentWmSize>1 && currentRecentWmSize < recentWmMaxSize)
1941 recentWmImmunized =
true;
1943 else if(currentRecentWmSize == 0 &&
_workingMem.size() > 1)
1957 for(std::map<int, double>::const_iterator memIter =
_workingMem.begin(); memIter !=
_workingMem.end(); ++memIter)
1964 else if(memIter->first > 0 && ignoredIds.find(memIter->first) == ignoredIds.end() && (!lastInSTM || !lastInSTM->
hasLink(memIter->first)))
1970 bool foundInSTM =
false;
1971 for(std::map<int, Link>::const_iterator iter = s->
getLinks().begin(); iter!=s->
getLinks().end(); ++iter)
1975 UDEBUG(
"Ignored %d because it has a link (%d) to STM", s->
id(), iter->first);
1997 int recentWmCount = 0;
2000 UDEBUG(
"signatureMap.size()=%d _lastGlobalLoopClosureId=%d currentRecentWmSize=%d recentWmMaxSize=%d",
2002 for(std::map<WeightAgeIdKey, Signature*>::iterator iter=weightAgeIdMap.begin();
2003 iter!=weightAgeIdMap.end();
2006 if(!recentWmImmunized)
2008 UDEBUG(
"weight=%d, id=%d",
2009 iter->second->getWeight(),
2010 iter->second->id());
2011 removableSignatures.push_back(iter->second);
2016 if(currentRecentWmSize - recentWmCount < recentWmMaxSize)
2018 UDEBUG(
"switched recentWmImmunized");
2019 recentWmImmunized =
true;
2025 UDEBUG(
"weight=%d, id=%d",
2026 iter->second->getWeight(),
2027 iter->second->id());
2028 removableSignatures.push_back(iter->second);
2030 if(removableSignatures.size() >= (
unsigned int)count)
2038 ULOGGER_WARN(
"not enough signatures to get an old one...");
2040 return removableSignatures;
2055 uFormat(
"Deleting location (%d) outside the " 2056 "STM is not implemented!", s->
id()).c_str());
2057 const std::map<int, Link> & links = s->
getLinks();
2058 for(std::map<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
2060 if(iter->second.from() != iter->second.to())
2065 uFormat(
"A neighbor (%d) of the deleted location %d is " 2066 "not found in WM/STM! Are you deleting a location " 2067 "outside the STM?", iter->first, s->
id()).c_str());
2069 if(iter->first > s->
id() && links.size()>1 && sTo->
hasLink(s->
id()))
2071 UWARN(
"Link %d of %d is newer, removing neighbor link " 2072 "may split the map!",
2073 iter->first, s->
id());
2102 for(std::list<int>::const_iterator i=keys.begin(); i!=keys.end(); ++i)
2108 std::vector<VisualWord*> wordToDelete;
2109 wordToDelete.push_back(w);
2113 deletedWords->push_back(w->
id());
2173 UDEBUG(
"label=%s", label.c_str());
2180 if(iter->second->getLabel().compare(label) == 0)
2182 id = iter->second->id();
2186 if(
id == 0 &&
_dbDriver && lookInDatabase)
2198 if(idFound == 0 || idFound ==
id)
2205 UWARN(
"Label \"%s\" set to node %d", label.c_str(), id);
2212 std::list<Signature *> signatures;
2214 if(signatures.size())
2216 signatures.front()->setLabel(label);
2217 UWARN(
"Label \"%s\" set to node %d", label.c_str(), id);
2224 UERROR(
"Node %d not found, failed to set label \"%s\"!",
id, label.c_str());
2229 UWARN(
"Node %d has already label \"%s\"", idFound, label.c_str());
2236 std::map<int, std::string> labels;
2237 for(std::map<int, Signature*>::const_iterator iter =
_signatures.begin(); iter!=
_signatures.end(); ++iter)
2239 if(!iter->second->getLabel().empty())
2241 labels.insert(std::make_pair(iter->first, iter->second->getLabel()));
2261 UERROR(
"Node %d not found in RAM, failed to set user data (size=%d)!",
id, data.total());
2268 UDEBUG(
"Deleting location %d", locationId);
2278 UDEBUG(
"Saving location data %d", locationId);
2302 UINFO(
"removing link between location %d and %d", oldS->
id(), newS->
id());
2323 bool noChildrenAnymore =
true;
2324 for(std::map<int, Link>::const_iterator iter=newS->
getLinks().begin(); iter!=newS->
getLinks().end(); ++iter)
2329 iter->first < newS->
id())
2331 noChildrenAnymore =
false;
2342 UERROR(
"Signatures %d and %d don't have bidirectional link!", oldS->
id(), newS->
id());
2349 UERROR(
"Signature %d is not in working memory... cannot remove link.", newS->
id());
2353 UERROR(
"Signature %d is not in working memory... cannot remove link.", oldS->
id());
2360 UDEBUG(
"id=%d image=%d scan=%d userData=%d",
id, image?1:0, scan?1:0, userData?1:0);
2388 bool useKnownCorrespondencesIfPossible)
2397 transform =
computeTransform(*fromS, *toS, guess, info, useKnownCorrespondencesIfPossible);
2401 std::string msg =
uFormat(
"Did not find nodes %d and/or %d", fromId, toId);
2417 bool useKnownCorrespondencesIfPossible)
const 2437 cv::Mat imgBuf, depthBuf, userBuf;
2452 std::vector<int> inliersV;
2463 tmpFrom.
setWords(std::multimap<int, cv::KeyPoint>());
2464 tmpFrom.
setWords3(std::multimap<int, cv::Point3f>());
2466 tmpFrom.
sensorData().
setFeatures(std::vector<cv::KeyPoint>(), std::vector<cv::Point3f>(), cv::Mat());
2467 tmpTo.
setWords(std::multimap<int, cv::KeyPoint>());
2468 tmpTo.
setWords3(std::multimap<int, cv::Point3f>());
2472 else if(useKnownCorrespondencesIfPossible)
2504 std::multimap<int, cv::Point3f> words3DMap;
2505 std::multimap<int, cv::KeyPoint> wordsMap;
2506 std::multimap<int, cv::Mat> wordsDescriptorsMap;
2508 const std::map<int, Link> & links = fromS.
getLinks();
2511 UDEBUG(
"fromS.getWords3()=%d uniques=%d", (
int)fromS.
getWords3().size(), (int)words3.size());
2512 for(std::map<int, cv::Point3f>::const_iterator jter=words3.begin(); jter!=words3.end(); ++jter)
2516 words3DMap.insert(*jter);
2517 wordsMap.insert(*fromS.
getWords().find(jter->first));
2522 UDEBUG(
"words3DMap=%d", (
int)words3DMap.size());
2524 for(std::map<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
2526 int id = iter->first;
2529 for(std::map<int, cv::Point3f>::const_iterator jter=words3.begin(); jter!=words3.end(); ++jter)
2531 if( jter->first > 0 &&
2533 words3DMap.find(jter->first) == words3DMap.end())
2535 words3DMap.insert(std::make_pair(jter->first,
util3d::transformPoint(jter->second, iter->second.transform())));
2536 wordsMap.insert(*s->
getWords().find(jter->first));
2541 UDEBUG(
"words3DMap=%d", (
int)words3DMap.size());
2544 tmpFrom2.setWords(wordsMap);
2545 tmpFrom2.setWordsDescriptors(wordsDescriptorsMap);
2549 if(!transform.
isNull() && info)
2552 std::map<int, Transform> bundlePoses;
2553 std::multimap<int, Link> bundleLinks;
2554 std::map<int, CameraModel> bundleModels;
2555 std::map<int, std::map<int, cv::Point3f> > wordReferences;
2557 std::map<int, Link> links = fromS.
getLinks();
2559 links.insert(std::make_pair(fromS.
id(),
Link()));
2561 for(std::map<int, Link>::iterator iter=links.begin(); iter!=links.end(); ++iter)
2563 int id = iter->first;
2565 if(
id == tmpTo.
id())
2591 UFATAL(
"no valid camera model to use local bundle adjustment on loop closure!");
2593 bundleModels.insert(std::make_pair(
id, model));
2595 if(iter->second.isValid())
2597 bundleLinks.insert(std::make_pair(iter->second.from(), iter->second));
2598 bundlePoses.insert(std::make_pair(
id, iter->second.transform()));
2605 for(std::map<int, cv::KeyPoint>::const_iterator jter=words.begin(); jter!=words.end(); ++jter)
2607 if(points3DMap.find(jter->first)!=points3DMap.end() &&
2608 (
id == tmpTo.
id() || jter->first > 0))
2610 std::multimap<int, cv::Point3f>::const_iterator kter = s->
getWords3().find(jter->first);
2612 wordReferences.insert(std::make_pair(jter->first, std::map<int, cv::Point3f>()));
2613 wordReferences.at(jter->first).insert(std::make_pair(
id, cv::Point3f(jter->second.pt.x, jter->second.pt.y, pt3d.z)));
2620 std::set<int> sbaOutliers;
2624 bundlePoses = sba.
optimizeBA(-toS.
id(), bundlePoses, bundleLinks, bundleModels, points3DMap, wordReferences, &sbaOutliers);
2627 UDEBUG(
"bundleTime=%fs (poses=%d wordRef=%d outliers=%d)", bundleTime.
ticks(), (int)bundlePoses.size(), (int)wordReferences.size(), (int)sbaOutliers.size());
2629 UDEBUG(
"Local Bundle Adjustment Before: %s", transform.prettyPrint().c_str());
2630 if(!bundlePoses.rbegin()->second.isNull())
2632 if(sbaOutliers.size())
2634 std::vector<int> newInliers(info->
inliersIDs.size());
2636 for(
unsigned int i=0; i<info->
inliersIDs.size(); ++i)
2638 if(sbaOutliers.find(info->
inliersIDs[i]) == sbaOutliers.end())
2643 newInliers.resize(oi);
2644 UDEBUG(
"BA outliers ratio %f",
float(sbaOutliers.size())/
float(info->
inliersIDs.size()));
2645 info->
inliers = (int)newInliers.size();
2651 transform.setNull();
2655 transform = bundlePoses.rbegin()->second;
2658 UDEBUG(
"Local Bundle Adjustment After : %s", transform.prettyPrint().c_str());
2680 if(fabs(pitch) > CV_PI/2 ||
2681 fabs(yaw) > CV_PI/2)
2684 std::string msg =
uFormat(
"Too large rotation detected! (pitch=%f, yaw=%f) max is %f",
2685 roll, pitch, yaw, CV_PI/2);
2701 const std::map<int, Transform> & poses,
2707 UDEBUG(
"%d -> %d, Guess=%s", fromId, toId, (poses.at(fromId).inverse() * poses.at(toId)).prettyPrint().c_str());
2711 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
2713 if(iter->first != fromId)
2718 UDEBUG(
"%d vs %s", fromId, ids.c_str());
2722 std::list<Signature*> depthToLoad;
2723 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
2731 depthToLoad.push_back(s);
2751 float guessNorm = guess.
getNorm();
2756 UINFO(
"Too far scans between %d and %d to compute transformation: guessNorm=%f, scan range from=%f to=%f", fromId, toId, guessNorm, fromScan.
maxRange(), toScan.
maxRange());
2764 int maxPoints = fromScan.
size();
2765 pcl::PointCloud<pcl::PointXYZ>::Ptr assembledToClouds(
new pcl::PointCloud<pcl::PointXYZ>);
2766 pcl::PointCloud<pcl::PointNormal>::Ptr assembledToNormalClouds(
new pcl::PointCloud<pcl::PointNormal>);
2767 pcl::PointCloud<pcl::PointXYZI>::Ptr assembledToIClouds(
new pcl::PointCloud<pcl::PointXYZI>);
2768 pcl::PointCloud<pcl::PointXYZINormal>::Ptr assembledToNormalIClouds(
new pcl::PointCloud<pcl::PointXYZINormal>);
2769 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
2771 if(iter->first != fromId)
2807 if(scan.
size() > maxPoints)
2809 maxPoints = scan.
size();
2814 UWARN(
"Incompatible scan format %d vs %d", (
int)fromScan.
format(), (int)scan.
format());
2819 UWARN(
"Depth2D not found for signature %d", iter->first);
2824 cv::Mat assembledScan;
2825 if(assembledToNormalClouds->size())
2829 else if(assembledToClouds->size())
2833 else if(assembledToNormalIClouds->size())
2837 else if(assembledToIClouds->size())
2865 if(toS->hasLink(link.
from()))
2868 UINFO(
"already linked! to=%d, from=%d", link.
to(), link.
from());
2872 UDEBUG(
"Add link between %d and %d", toS->id(), fromS->id());
2875 fromS->addLink(link);
2892 UASSERT(fromS->getWeight() >= 0 && toS->getWeight() >=0);
2896 fromS->setWeight(fromS->getWeight() + toS->getWeight());
2901 toS->setWeight(toS->getWeight() + fromS->getWeight());
2902 fromS->setWeight(0);
2908 else if(!addInDatabase)
2912 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
from());
2916 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
to());
2922 UDEBUG(
"Add link between %d and %d (db)", link.
from(), link.
to());
2923 fromS->addLink(link);
2928 UDEBUG(
"Add link between %d (db) and %d", link.
from(), link.
to());
2934 UDEBUG(
"Add link between %d (db) and %d (db)", link.
from(), link.
to());
2953 toS->removeLink(link.
from());
2965 UERROR(
"fromId=%d and toId=%d are not linked!", link.
from(), link.
to());
2968 else if(!updateInDatabase)
2972 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
from());
2976 UERROR(
"from=%d, to=%d, Signature %d not found in working/st memories", link.
from(), link.
to(), link.
to());
2981 UDEBUG(
"Update link between %d and %d (db)", link.
from(), link.
to());
2988 UDEBUG(
"Update link between %d (db) and %d", link.
from(), link.
to());
2989 toS->removeLink(link.
from());
2995 UDEBUG(
"Update link between %d (db) and %d (db)", link.
from(), link.
to());
3006 iter->second->removeVirtualLinks();
3016 const std::map<int, Link> & links = s->
getLinks();
3017 for(std::map<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
3028 UERROR(
"Link %d of %d not in WM/STM?!?", iter->first, s->
id());
3036 UERROR(
"Signature %d not in WM/STM?!?", signatureId);
3042 UINFO(
"Dumping memory to directory \"%s\"", directory.c_str());
3043 this->
dumpDictionary((directory+
"/DumpMemoryWordRef.txt").c_str(), (directory+
"/DumpMemoryWordDesc.txt").c_str());
3044 this->
dumpSignatures((directory +
"/DumpMemorySign.txt").c_str(),
false);
3045 this->
dumpSignatures((directory +
"/DumpMemorySign3.txt").c_str(),
true);
3046 this->
dumpMemoryTree((directory +
"/DumpMemoryTree.txt").c_str());
3062 fopen_s(&foutSign, fileNameSign,
"w");
3064 foutSign = fopen(fileNameSign,
"w");
3069 fprintf(foutSign,
"SignatureID WordsID...\n");
3070 const std::map<int, Signature *> & signatures = this->
getSignatures();
3071 for(std::map<int, Signature *>::const_iterator iter=signatures.begin(); iter!=signatures.end(); ++iter)
3073 fprintf(foutSign,
"%d ", iter->first);
3079 const std::multimap<int, cv::Point3f> & ref = ss->
getWords3();
3080 for(std::multimap<int, cv::Point3f>::const_iterator jter=ref.begin(); jter!=ref.end(); ++jter)
3084 (jter->second.x != 0 || jter->second.y != 0 || jter->second.z != 0))
3086 fprintf(foutSign,
"%d ", (*jter).first);
3092 const std::multimap<int, cv::KeyPoint> & ref = ss->
getWords();
3093 for(std::multimap<int, cv::KeyPoint>::const_iterator jter=ref.begin(); jter!=ref.end(); ++jter)
3095 fprintf(foutSign,
"%d ", (*jter).first);
3099 fprintf(foutSign,
"\n");
3110 fopen_s(&foutTree, fileNameTree,
"w");
3112 foutTree = fopen(fileNameTree,
"w");
3117 fprintf(foutTree,
"SignatureID Weight NbLoopClosureIds LoopClosureIds... NbChildLoopClosureIds ChildLoopClosureIds...\n");
3121 fprintf(foutTree,
"%d %d", i->first, i->second->getWeight());
3123 std::map<int, Link> loopIds, childIds;
3125 for(std::map<int, Link>::const_iterator iter = i->second->getLinks().begin();
3126 iter!=i->second->getLinks().end();
3132 if(iter->first < i->first)
3134 childIds.insert(*iter);
3136 else if(iter->second.from() != iter->second.to())
3138 loopIds.insert(*iter);
3143 fprintf(foutTree,
" %d", (
int)loopIds.size());
3144 for(std::map<int, Link>::const_iterator j=loopIds.begin(); j!=loopIds.end(); ++j)
3146 fprintf(foutTree,
" %d", j->first);
3149 fprintf(foutTree,
" %d", (
int)childIds.size());
3150 for(std::map<int, Link>::const_iterator j=childIds.begin(); j!=childIds.end(); ++j)
3152 fprintf(foutTree,
" %d", j->first);
3155 fprintf(foutTree,
"\n");
3175 for(std::set<int>::reverse_iterator iter=
_stMem.rbegin(); iter!=
_stMem.rend(); ++iter)
3188 UDEBUG(
"Comparing with signature (%d)...",
id);
3208 if(stats) stats->
addStatistic(Statistics::kMemoryRehearsal_merged(), merged);
3209 if(stats) stats->
addStatistic(Statistics::kMemoryRehearsal_sim(), sim);
3211 UDEBUG(
"merged=%d, sim=%f t=%fs", merged, sim, timer.
ticks());
3215 if(stats) stats->
addStatistic(Statistics::kMemoryRehearsal_merged(), 0);
3216 if(stats) stats->
addStatistic(Statistics::kMemoryRehearsal_sim(), 0);
3228 std::map<int, Link>::const_iterator iter = oldS->
getLinks().find(newS->
id());
3229 if(iter != oldS->
getLinks().end() &&
3232 iter->second.from() != iter->second.to())
3235 UWARN(
"already merged, old=%d, new=%d", oldId, newId);
3240 UINFO(
"Rehearsal merging %d (w=%d) and %d (w=%d)",
3245 bool intermediateMerge =
false;
3246 if(!newS->
getLinks().empty() && !newS->
getLinks().begin()->second.transform().isNull())
3252 newS->
getLinks().begin()->second.transform().getTranslationAndEulerAngles(x,y,z, roll,pitch,yaw);
3261 UINFO(
"Rehearsal ignored because the robot has moved more than %f m or %f rad (\"Mem/RehearsalWeightIgnoredWhileMoving\"=true)",
3265 fullMerge = !isMoving && newS->
hasLink(oldS->
id());
3266 intermediateMerge = !isMoving && !newS->
hasLink(oldS->
id());
3270 fullMerge = newS->
hasLink(oldS->
id()) && newS->
getLinks().begin()->second.transform().isNull();
3283 const std::map<int, Link> & links = oldS->
getLinks();
3284 for(std::map<int, Link>::const_iterator iter = links.begin(); iter!=links.end(); ++iter)
3286 if(iter->second.from() != iter->second.to())
3288 Link link = iter->second;
3297 s->addLink(mergedLink.
inverse());
3303 UERROR(
"Didn't find neighbor %d of %d in RAM...", link.
to(), oldS->
id());
3349 oldS->
setWeight(intermediateMerge?-1:0);
3360 newS->
setWeight(intermediateMerge?-1:0);
3368 UERROR(
"newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, newId);
3372 UERROR(
"newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, oldId);
3384 std::vector<float> velocity;
3386 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth, velocity, gps, lookInDatabase);
3396 std::vector<float> velocity;
3398 getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth, velocity, gps, lookInDatabase);
3406 std::string & label,
3409 std::vector<float> & velocity,
3411 bool lookInDatabase)
const 3428 return _dbDriver->
getNodeInfo(signatureId, odomPose, mapId, weight, label, stamp, groundTruth, velocity, gps);
3452 UDEBUG(
"nodeId=%d", nodeId);
3465 if(uncompressedData)
3474 std::multimap<int, cv::KeyPoint> & words,
3475 std::multimap<int, cv::Point3f> & words3,
3476 std::multimap<int, cv::Mat> & wordsDescriptors)
3478 UDEBUG(
"nodeId=%d", nodeId);
3489 std::list<Signature*> signatures;
3491 ids.push_back(nodeId);
3492 std::set<int> loadedFromTrash;
3494 if(signatures.size())
3496 words = signatures.front()->getWords();
3497 words3 = signatures.front()->getWords3();
3498 wordsDescriptors = signatures.front()->getWordsDescriptors();
3499 if(loadedFromTrash.size())
3506 delete signatures.front();
3513 std::vector<CameraModel> & models,
3516 UDEBUG(
"nodeId=%d", nodeId);
3531 bool images,
bool scan,
bool userData,
bool occupancyGrid)
const 3556 UERROR(
"A database must must loaded first...");
3569 ni = (int)((
Signature *)s)->getWords().size();
3589 id.push_back(to->
id());
3595 UDEBUG(
"Loaded image data from database");
3609 ULOGGER_ERROR(
"Can't merge the signatures because there are not same type.");
3635 data.
imageRaw().type() == CV_8UC1 ||
3636 data.
imageRaw().type() == CV_8UC3);
3644 uFormat(
"image=(%d/%d) depth=(%d/%d, type=%d [accepted=%d,%d,%d])",
3650 CV_16UC1, CV_32FC1, CV_8UC1).c_str());
3657 UERROR(
"Camera calibration not valid, calibrate your camera!");
3667 std::vector<cv::KeyPoint> keypoints;
3668 cv::Mat descriptors;
3669 bool isIntermediateNode = data.
id() < 0 || data.
imageRaw().empty();
3679 UERROR(
"Received image ID is null. " 3680 "Please set parameter Mem/GenerateIds to \"true\" or " 3681 "make sure the input source provides image ids (seq).");
3690 UERROR(
"Id of acquired image (%d) is smaller than the last in memory (%d). " 3691 "Please set parameter Mem/GenerateIds to \"true\" or " 3692 "make sure the input source provides image ids (seq) over the last in " 3693 "memory, which is %d.",
3717 for(
unsigned int i=0; i<data.
cameraModels().size(); ++i)
3726 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)...", i);
3728 UWARN(
"Initializing rectification maps for camera %d (only done for the first image received)... done!", i);
3734 rectifiedImage.copyTo(cv::Mat(rectifiedImages, cv::Rect(subImageWidth*i, 0, subImageWidth, data.
imageRaw().rows)));
3735 imagesRectified =
true;
3739 UERROR(
"Calibration for camera %d cannot be used to rectify the image. Make sure to do a " 3740 "full calibration. If images are already rectified, set %s parameter back to true.",
3742 Parameters::kRtabmapImagesAlreadyRectified().c_str());
3755 UWARN(
"Initializing rectification maps (only done for the first image received)...");
3757 UWARN(
"Initializing rectification maps (only done for the first image received)...done!");
3764 imagesRectified =
true;
3768 UERROR(
"Stereo calibration cannot be used to rectify images. Make sure to do a " 3769 "full stereo calibration. If images are already rectified, set %s parameter back to true.",
3770 Parameters::kRtabmapImagesAlreadyRectified().c_str());
3774 if(stats) stats->
addStatistic(Statistics::kTimingMemRectification(), t*1000.0
f);
3775 UDEBUG(
"time rectification = %fs", t);
3787 UDEBUG(
"Start dictionary update thread");
3788 preUpdateThread.
start();
3791 int preDecimation = 1;
3792 std::vector<cv::Point3f> keypoints3D;
3798 decimatedData = data;
3802 if(!decimatedData.
rightRaw().empty() ||
3808 std::vector<CameraModel> cameraModels = decimatedData.
cameraModels();
3809 for(
unsigned int i=0; i<cameraModels.size(); ++i)
3822 UINFO(
"Extract features");
3824 if(decimatedData.
imageRaw().channels() == 3)
3826 cv::cvtColor(decimatedData.
imageRaw(), imageMono, CV_BGR2GRAY);
3830 imageMono = decimatedData.
imageRaw();
3836 if(imageMono.rows % decimatedData.
depthRaw().rows == 0 &&
3837 imageMono.cols % decimatedData.
depthRaw().cols == 0 &&
3838 imageMono.rows/decimatedData.
depthRaw().rows == imageMono.cols/decimatedData.
depthRaw().cols)
3859 if(tmpMaxFeatureParameter.size())
3861 tmpMaxFeatureParameter.at(Parameters::kKpMaxFeatures()) =
uNumber2Str(oldMaxFeatures);
3865 if(stats) stats->
addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0
f);
3866 UDEBUG(
"time keypoints (%d) = %fs", (
int)keypoints.size(), t);
3870 if(stats) stats->
addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0f);
3871 UDEBUG(
"time descriptors (%d) = %fs", descriptors.rows, t);
3874 if(descriptors.rows && descriptors.rows <
_badSignRatio *
float(meanWordsPerLocation))
3876 descriptors = cv::Mat();
3880 if(!imagesRectified && decimatedData.
cameraModels().size())
3882 std::vector<cv::KeyPoint> keypointsValid;
3883 keypointsValid.reserve(keypoints.size());
3884 cv::Mat descriptorsValid;
3885 descriptorsValid.reserve(descriptors.rows);
3890 std::vector<cv::Point2f> pointsIn, pointsOut;
3891 cv::KeyPoint::convert(keypoints,pointsIn);
3894 #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))) 3897 cv::Mat D(1, 4, CV_64FC1);
3898 D.at<
double>(0,0) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,1);
3899 D.at<
double>(0,1) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,1);
3900 D.at<
double>(0,2) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,4);
3901 D.at<
double>(0,3) = decimatedData.
cameraModels()[0].D_raw().at<
double>(0,5);
3902 cv::fisheye::undistortPoints(pointsIn, pointsOut,
3910 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
3911 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
3916 cv::undistortPoints(pointsIn, pointsOut,
3922 UASSERT(pointsOut.size() == keypoints.size());
3923 for(
unsigned int i=0; i<pointsOut.size(); ++i)
3925 if(pointsOut.at(i).x>=0 && pointsOut.at(i).x<decimatedData.
cameraModels()[0].imageWidth() &&
3926 pointsOut.at(i).y>=0 && pointsOut.at(i).y<decimatedData.
cameraModels()[0].imageHeight())
3928 keypointsValid.push_back(keypoints.at(i));
3929 keypointsValid.back().pt.x = pointsOut.at(i).x;
3930 keypointsValid.back().pt.y = pointsOut.at(i).y;
3931 descriptorsValid.push_back(descriptors.row(i));
3939 for(
unsigned int i=0; i<keypoints.size(); ++i)
3941 int cameraIndex = int(keypoints.at(i).pt.x / subImageWidth);
3943 uFormat(
"cameraIndex=%d, models=%d, kpt.x=%f, subImageWidth=%f (Camera model image width=%d)",
3944 cameraIndex, (
int)decimatedData.
cameraModels().size(), keypoints[i].pt.x, subImageWidth, decimatedData.
cameraModels()[0].imageWidth()).c_str());
3946 std::vector<cv::Point2f> pointsIn, pointsOut;
3947 pointsIn.push_back(cv::Point2f(keypoints.at(i).pt.x-subImageWidth*cameraIndex, keypoints.at(i).pt.y));
3948 if(decimatedData.
cameraModels()[cameraIndex].D_raw().cols == 6)
3950 #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))) 3953 cv::Mat D(1, 4, CV_64FC1);
3954 D.at<
double>(0,0) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,1);
3955 D.at<
double>(0,1) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,1);
3956 D.at<
double>(0,2) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,4);
3957 D.at<
double>(0,3) = decimatedData.
cameraModels()[cameraIndex].D_raw().at<
double>(0,5);
3958 cv::fisheye::undistortPoints(pointsIn, pointsOut,
3966 UWARN(
"Too old opencv version (%d,%d,%d) to support fisheye model (min 2.4.10 required)!",
3967 CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
3972 cv::undistortPoints(pointsIn, pointsOut,
3979 if(pointsOut[0].x>=0 && pointsOut[0].x<decimatedData.
cameraModels()[cameraIndex].imageWidth() &&
3980 pointsOut[0].y>=0 && pointsOut[0].y<decimatedData.
cameraModels()[cameraIndex].imageHeight())
3982 keypointsValid.push_back(keypoints.at(i));
3983 keypointsValid.back().pt.x = pointsOut[0].x + subImageWidth*cameraIndex;
3984 keypointsValid.back().pt.y = pointsOut[0].y;
3985 descriptorsValid.push_back(descriptors.row(i));
3990 keypoints = keypointsValid;
3991 descriptors = descriptorsValid;
3994 if(stats) stats->
addStatistic(Statistics::kTimingMemRectification(), t*1000.0f);
3995 UDEBUG(
"time rectification = %fs", t);
4003 if(stats) stats->
addStatistic(Statistics::kTimingMemKeypoints_3D(), t*1000.0
f);
4004 UDEBUG(
"time keypoints 3D (%d) = %fs", (
int)keypoints3D.size(), t);
4008 else if(data.imageRaw().empty())
4010 UDEBUG(
"Empty image, cannot extract features...");
4018 UDEBUG(
"Intermediate node detected, don't extract features!");
4023 UINFO(
"Use odometry features: kpts=%d 3d=%d desc=%d (dim=%d, type=%d)",
4024 (
int)data.keypoints().size(),
4025 (int)data.keypoints3D().size(),
4026 data.descriptors().rows,
4027 data.descriptors().cols,
4028 data.descriptors().type());
4029 keypoints = data.keypoints();
4030 keypoints3D = data.keypoints3D();
4031 descriptors = data.descriptors().clone();
4033 UASSERT(descriptors.empty() || descriptors.rows == (int)keypoints.size());
4034 UASSERT(keypoints3D.empty() || keypoints3D.size() == keypoints.size());
4037 if((
int)keypoints.size() > maxFeatures)
4042 if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_detection(), t*1000.0
f);
4043 UDEBUG(
"time keypoints (%d) = %fs", (
int)keypoints.size(), t);
4045 if(descriptors.empty())
4048 if(data.imageRaw().channels() == 3)
4050 cv::cvtColor(data.imageRaw(), imageMono, CV_BGR2GRAY);
4054 imageMono = data.imageRaw();
4057 UASSERT_MSG(imagesRectified,
"Cannot extract descriptors on not rectified image from keypoints which assumed to be undistorted");
4062 if(stats) stats->addStatistic(Statistics::kTimingMemDescriptors_extraction(), t*1000.0f);
4063 UDEBUG(
"time descriptors (%d) = %fs", descriptors.rows, t);
4065 if(keypoints3D.empty() &&
4066 ((!data.depthRaw().empty() && data.cameraModels().size() && data.cameraModels()[0].isValidForProjection()) ||
4067 (!data.rightRaw().empty() && data.stereoCameraModel().isValidForProjection())))
4074 UASSERT((
int)keypoints.size() == descriptors.rows &&
4075 keypoints3D.size() == keypoints.size());
4076 std::vector<cv::KeyPoint> validKeypoints(keypoints.size());
4077 std::vector<cv::Point3f> validKeypoints3D(keypoints.size());
4078 cv::Mat validDescriptors(descriptors.size(), descriptors.type());
4081 for(
unsigned int i=0; i<keypoints3D.size(); ++i)
4085 validKeypoints[oi] = keypoints[i];
4086 validKeypoints3D[oi] = keypoints3D[i];
4087 descriptors.row(i).copyTo(validDescriptors.row(oi));
4091 UDEBUG(
"Removed %d invalid 3D points", (
int)keypoints3D.size()-oi);
4092 validKeypoints.resize(oi);
4093 validKeypoints3D.resize(oi);
4094 keypoints = validKeypoints;
4095 keypoints3D = validKeypoints3D;
4096 descriptors = validDescriptors.rowRange(0, oi).clone();
4100 if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_3D(), t*1000.0f);
4101 UDEBUG(
"time keypoints 3D (%d) = %fs", (
int)keypoints3D.size(), t);
4104 if(descriptors.rows && descriptors.rows <
_badSignRatio *
float(meanWordsPerLocation))
4106 descriptors = cv::Mat();
4112 UDEBUG(
"Joining dictionary update thread...");
4113 preUpdateThread.join();
4114 UDEBUG(
"Joining dictionary update thread... thread finished!");
4118 if(stats) stats->addStatistic(Statistics::kTimingMemJoining_dictionary_update(), t*1000.0
f);
4121 UDEBUG(
"time descriptor and memory update (%d of size=%d) = %fs", descriptors.rows, descriptors.cols, t);
4125 UDEBUG(
"time descriptor (%d of size=%d) = %fs", descriptors.rows, descriptors.cols, t);
4128 std::list<int> wordIds;
4129 if(descriptors.rows)
4133 std::vector<bool> inliers;
4134 cv::Mat descriptorsForQuantization = descriptors;
4135 std::vector<int> quantizedToRawIndices;
4138 UASSERT((
int)keypoints.size() == descriptors.rows);
4144 UASSERT((
int)inliers.size() == descriptors.rows);
4145 for(
int k=0; k < descriptors.rows; ++k)
4149 UASSERT(oi < quantizedToRawIndices.size());
4150 if(descriptors.type() == CV_32FC1)
4152 memcpy(descriptorsForQuantization.ptr<
float>(oi), descriptors.ptr<
float>(k), descriptors.cols*
sizeof(
float));
4156 memcpy(descriptorsForQuantization.ptr<
char>(oi), descriptors.ptr<
char>(k), descriptors.cols*
sizeof(
char));
4158 quantizedToRawIndices[oi] = k;
4169 if(wordIds.size() < keypoints.size())
4171 std::vector<int> allWordIds;
4172 allWordIds.resize(keypoints.size(),-1);
4174 for(std::list<int>::iterator iter=wordIds.begin(); iter!=wordIds.end(); ++iter)
4176 allWordIds[quantizedToRawIndices[i]] = *iter;
4180 for(i=0; i<(int)allWordIds.size(); ++i)
4182 if(allWordIds[i] < 0)
4184 allWordIds[i] = negIndex--;
4191 if(stats) stats->addStatistic(Statistics::kTimingMemAdd_new_words(), t*1000.0f);
4196 UDEBUG(
"id %d is a bad signature",
id);
4199 std::multimap<int, cv::KeyPoint> words;
4200 std::multimap<int, cv::Point3f> words3D;
4201 std::multimap<int, cv::Mat> wordsDescriptors;
4202 if(wordIds.size() > 0)
4204 UASSERT(wordIds.size() == keypoints.size());
4205 UASSERT(keypoints3D.size() == 0 || keypoints3D.size() == wordIds.size());
4208 double log2value =
log(
double(preDecimation))/
log(2.0);
4209 for(std::list<int>::iterator iter=wordIds.begin(); iter!=wordIds.end() && i < keypoints.size(); ++iter, ++i)
4211 cv::KeyPoint kpt = keypoints[i];
4215 kpt.pt.x *= decimationRatio;
4216 kpt.pt.y *= decimationRatio;
4217 kpt.size *= decimationRatio;
4218 kpt.octave += log2value;
4220 words.insert(std::pair<int, cv::KeyPoint>(*iter, kpt));
4222 if(keypoints3D.size())
4224 words3D.insert(std::pair<int, cv::Point3f>(*iter, keypoints3D.at(i)));
4228 wordsDescriptors.insert(std::pair<int, cv::Mat>(*iter, descriptors.row(i).clone()));
4233 cv::Mat image = data.imageRaw();
4234 cv::Mat depthOrRightImage = data.depthOrRightRaw();
4235 std::vector<CameraModel> cameraModels = data.cameraModels();
4243 image = decimatedData.imageRaw();
4244 depthOrRightImage = decimatedData.depthOrRightRaw();
4245 cameraModels = decimatedData.cameraModels();
4246 stereoCameraModel = decimatedData.stereoCameraModel();
4250 if(!data.rightRaw().empty() ||
4251 (data.depthRaw().rows == image.rows && data.depthRaw().cols == image.cols))
4256 for(
unsigned int i=0; i<cameraModels.size(); ++i)
4267 if(stats) stats->addStatistic(Statistics::kTimingMemPost_decimation(), t*1000.0f);
4268 UDEBUG(
"time post-decimation = %fs", t);
4272 if(!pose.isNull() &&
4273 cameraModels.size() == 1 &&
4275 (words3D.size() == 0 || (triangulateWordsWithoutDepth && words.size() == words3D.size())) &&
4280 UDEBUG(
"Generate 3D words using odometry");
4285 UDEBUG(
"Current pose(%d) = %s",
id, pose.prettyPrint().c_str());
4293 cpPrevious.
setWords(std::multimap<int, cv::KeyPoint>(uniqueWords.begin(), uniqueWords.end()));
4294 cpPrevious.
setWordsDescriptors(std::multimap<int, cv::Mat>(uniqueWordsDescriptors.begin(), uniqueWordsDescriptors.end()));
4299 cpCurrent.
setWords(std::multimap<int, cv::KeyPoint>(uniqueWords.begin(), uniqueWords.end()));
4300 cpCurrent.
setWordsDescriptors(std::multimap<int, cv::Mat>(uniqueWordsDescriptors.begin(), uniqueWordsDescriptors.end()));
4312 UDEBUG(
"inliers=%d", (
int)inliers.size());
4315 float bad_point = std::numeric_limits<float>::quiet_NaN ();
4316 UASSERT(words3D.size() == 0 || words.size() == words3D.size());
4317 bool words3DWasEmpty = words3D.empty();
4318 int added3DPointsWithoutDepth = 0;
4319 for(std::multimap<int, cv::KeyPoint>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
4321 std::map<int, cv::Point3f>::iterator jter=inliers.find(iter->first);
4322 std::multimap<int, cv::Point3f>::iterator iter3D = words3D.find(iter->first);
4323 if(iter3D == words3D.end())
4325 if(jter != inliers.end())
4327 words3D.insert(std::make_pair(iter->first, jter->second));
4328 ++added3DPointsWithoutDepth;
4332 words3D.insert(std::make_pair(iter->first, cv::Point3f(bad_point,bad_point,bad_point)));
4337 iter3D->second = jter->second;
4338 ++added3DPointsWithoutDepth;
4340 else if(words3DWasEmpty && jter == inliers.end())
4343 words3D.insert(std::make_pair(iter->first, cv::Point3f(bad_point,bad_point,bad_point)));
4346 UDEBUG(
"added3DPointsWithoutDepth=%d", added3DPointsWithoutDepth);
4347 if(stats) stats->addStatistic(Statistics::kMemoryTriangulated_points(), (
float)added3DPointsWithoutDepth);
4350 UASSERT(words3D.size() == words.size());
4351 if(stats) stats->addStatistic(Statistics::kTimingMemKeypoints_3D_motion(), t*1000.0f);
4352 UDEBUG(
"time keypoints 3D by motion (%d) = %fs", (
int)words3D.size(), t);
4357 LaserScan laserScan = data.laserScanRaw();
4358 if(!isIntermediateNode && laserScan.size())
4360 if(laserScan.maxRange() == 0.0f)
4362 bool id2d = laserScan.
is2d();
4363 float maxRange = 0.0f;
4364 for(
int i=0; i<laserScan.size(); ++i)
4366 const float * ptr = laserScan.data().ptr<
float>(0, i);
4370 r = ptr[0]*ptr[0] + ptr[1]*ptr[1];
4374 r = ptr[0]*ptr[0] + ptr[1]*ptr[1] + ptr[2]*ptr[2];
4383 laserScan=
LaserScan(laserScan.data(), laserScan.maxPoints(),
sqrt(maxRange), laserScan.format(), laserScan.localTransform());
4395 if(stats) stats->addStatistic(Statistics::kTimingMemScan_filtering(), t*1000.0f);
4396 UDEBUG(
"time normals scan = %fs", t);
4402 UDEBUG(
"Bin data kept: rgb=%d, depth=%d, scan=%d, userData=%d",
4404 depthOrRightImage.empty()?0:1,
4405 laserScan.isEmpty()?0:1,
4406 data.userDataRaw().empty()?0:1);
4408 std::vector<unsigned char> imageBytes;
4409 std::vector<unsigned char> depthBytes;
4411 if(
_saveDepth16Format && !depthOrRightImage.empty() && depthOrRightImage.type() == CV_32FC1)
4413 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).");
4417 cv::Mat compressedImage;
4418 cv::Mat compressedDepth;
4419 cv::Mat compressedScan;
4420 cv::Mat compressedUserData;
4431 if(!depthOrRightImage.empty())
4435 if(!laserScan.isEmpty())
4437 ctLaserScan.start();
4439 if(!data.userDataRaw().empty())
4450 compressedScan = ctLaserScan.getCompressedData();
4451 compressedUserData = ctUserData.getCompressedData();
4456 compressedDepth =
compressImage2(depthOrRightImage, depthOrRightImage.type() == CV_32FC1 || depthOrRightImage.type() == CV_16UC1?std::string(
".png"):std::string(
".jpg"));
4463 isIntermediateNode?-1:0,
4470 LaserScan(compressedScan, laserScan.maxPoints(), laserScan.maxRange(), laserScan.format(), laserScan.localTransform()),
4476 compressedUserData):
4478 LaserScan(compressedScan, laserScan.maxPoints(), laserScan.maxRange(), laserScan.format(), laserScan.localTransform()),
4484 compressedUserData));
4488 UDEBUG(
"Bin data kept: scan=%d, userData=%d",
4489 laserScan.isEmpty()?0:1,
4490 data.userDataRaw().empty()?0:1);
4493 cv::Mat compressedScan;
4494 cv::Mat compressedUserData;
4499 if(!data.userDataRaw().empty() && !isIntermediateNode)
4503 if(!laserScan.isEmpty() && !isIntermediateNode)
4505 ctLaserScan.start();
4510 compressedScan = ctLaserScan.getCompressedData();
4511 compressedUserData = ctUserData.getCompressedData();
4521 isIntermediateNode?-1:0,
4528 LaserScan(compressedScan, laserScan.maxPoints(), laserScan.maxRange(), laserScan.format(), laserScan.localTransform()),
4534 compressedUserData):
4536 LaserScan(compressedScan, laserScan.maxPoints(), laserScan.maxRange(), laserScan.format(), laserScan.localTransform()),
4542 compressedUserData));
4559 if(stats) stats->addStatistic(Statistics::kTimingMemCompressing_data(), t*1000.0f);
4560 UDEBUG(
"time compressing data (id=%d) %fs",
id, t);
4567 cv::Mat ground, obstacles, empty;
4568 float cellSize = 0.0f;
4569 cv::Point3f viewPoint(0,0,0);
4576 if(stats) stats->addStatistic(Statistics::kTimingMemOccupancy_grid(), t*1000.0f);
4577 UDEBUG(
"time grid map = %fs", t);
4582 if(!isIntermediateNode)
4584 if(!data.globalPose().isNull() && data.globalPoseCovariance().cols==6 && data.globalPoseCovariance().rows==6 && data.globalPoseCovariance().cols==CV_64FC1)
4593 else if(data.gps().stamp() > 0.0)
4622 UDEBUG(
"id=%d", signatureId);
4627 const std::multimap<int, cv::KeyPoint> & words = ss->
getWords();
4631 for(std::list<int>::const_iterator i=keys.begin(); i!=keys.end(); ++i)
4646 if(removedWords.size())
4651 for(
unsigned int i=0; i<removedWords.size(); ++i)
4659 delete removedWords[i];
4667 UDEBUG(
"size=%d", signatureIds.size());
4671 std::map<int, int> refsToChange;
4673 std::set<int> oldWordIds;
4674 std::list<Signature *> surfSigns;
4675 for(std::list<int>::const_iterator i=signatureIds.begin(); i!=signatureIds.end(); ++i)
4680 surfSigns.push_back(ss);
4684 for(std::list<int>::const_iterator k=uniqueKeys.begin(); k!=uniqueKeys.end(); ++k)
4688 oldWordIds.insert(oldWordIds.end(), *k);
4696 UWARN(
"Dictionary is fixed, but some words retrieved have not been found!?");
4699 UDEBUG(
"oldWordIds.size()=%d, getOldIds time=%fs", oldWordIds.size(), timer.ticks());
4702 std::list<VisualWord *> vws;
4708 UDEBUG(
"loading words(%d) time=%fs", oldWordIds.size(), timer.ticks());
4714 std::vector<int> vwActiveIds =
_vwd->
findNN(vws);
4715 UDEBUG(
"find active ids (number=%d) time=%fs", vws.size(), timer.ticks());
4717 for(std::list<VisualWord *>::iterator iterVws=vws.begin(); iterVws!=vws.end(); ++iterVws)
4719 if(vwActiveIds[i] > 0)
4722 refsToChange.insert(refsToChange.end(), std::pair<int, int>((*iterVws)->id(), vwActiveIds[i]));
4723 if((*iterVws)->isSaved())
4739 UDEBUG(
"Added %d to dictionary, time=%fs", vws.size()-refsToChange.size(), timer.ticks());
4742 for(std::map<int, int>::const_iterator iter=refsToChange.begin(); iter != refsToChange.end(); ++iter)
4745 for(std::list<Signature *>::iterator j=surfSigns.begin(); j!=surfSigns.end(); ++j)
4747 (*j)->changeWordsRef(iter->first, iter->second);
4750 UDEBUG(
"changing ref, total=%d, time=%fs", refsToChange.size(), timer.ticks());
4756 for(std::list<Signature *>::iterator j=surfSigns.begin(); j!=surfSigns.end(); ++j)
4758 const std::vector<int> & keys =
uKeys((*j)->getWords());
4762 for(
unsigned int i=0; i<keys.size(); ++i)
4769 (*j)->setEnabled(
true);
4774 UDEBUG(
"%d words total ref added from %d signatures, time=%fs...", count, surfSigns.size(), timer.ticks());
4785 std::list<int> idsToLoad;
4786 std::map<int, int>::iterator wmIter;
4787 for(std::list<int>::const_iterator i=ids.begin(); i!=ids.end(); ++i)
4791 if(!maxLoaded || idsToLoad.size() < maxLoaded)
4793 idsToLoad.push_back(*i);
4794 UINFO(
"Loading location %d from database...", *i);
4799 UDEBUG(
"idsToLoad = %d", idsToLoad.size());
4801 std::list<Signature *> reactivatedSigns;
4807 std::list<int> idsLoaded;
4808 for(std::list<Signature *>::iterator i=reactivatedSigns.begin(); i!=reactivatedSigns.end(); ++i)
4810 idsLoaded.push_back((*i)->id());
4816 return std::set<int>(idsToLoad.begin(), idsToLoad.end());
4822 const std::set<int> & ids,
4823 std::map<int, Transform> & poses,
4824 std::multimap<int, Link> & links,
4825 bool lookInDatabase)
4828 for(std::set<int>::const_iterator iter=ids.begin(); iter!=ids.end(); ++iter)
4833 poses.insert(std::make_pair(*iter, pose));
4837 for(std::set<int>::const_iterator iter=ids.begin(); iter!=ids.end(); ++iter)
4841 std::map<int, Link> tmpLinks =
getLinks(*iter, lookInDatabase);
4842 for(std::map<int, Link>::iterator jter=tmpLinks.begin(); jter!=tmpLinks.end(); ++jter)
4844 if( jter->second.isValid() &&
4848 if(!lookInDatabase &&
4852 Link link = jter->second;
4861 std::map<int, Link>::iterator uter = n.upper_bound(s->
id());
4867 link = link.
merge(uter->second, uter->second.type());
4868 poses.erase(s->
id());
4879 links.insert(std::make_pair(*iter, link));
4883 links.insert(std::make_pair(*iter, jter->second));
const std::multimap< int, cv::Point3f > & getWords3() const
GLM_FUNC_DECL genType log(genType const &x)
LaserScan RTABMAP_EXP laserScanFromPointCloud(const pcl::PCLPointCloud2 &cloud, bool filterNaNs=true)
std::list< K > uUniqueKeys(const std::multimap< K, V > &mm)
GLM_FUNC_DECL T roll(detail::tquat< T, P > const &x)
bool isUserDataRequired() const
bool RTABMAP_EXP isFinite(const cv::Point3f &pt)
cv::Mat loadOptimizedMesh(std::vector< std::vector< std::vector< unsigned int > > > *polygons=0, std::vector< std::vector< Eigen::Vector2f > > *texCoords=0, cv::Mat *textures=0) const
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
void removeLink(int idA, int idB)
cv::Mat loadPreviewImage() const
OccupancyGrid * _occupancy
void getLastNodeId(int &id) const
int getMinVisualCorrespondences() const
bool labelSignature(int id, const std::string &label)
cv::Mat loadPreviewImage() const
cv::Mat loadOptimizedMesh(std::vector< std::vector< std::vector< unsigned int > > > *polygons=0, std::vector< std::vector< Eigen::Vector2f > > *texCoords=0, cv::Mat *textures=0) const
std::map< K, V > uMultimapToMapUnique(const std::multimap< K, V > &m)
std::map< int, cv::Point3f > RTABMAP_EXP generateWords3DMono(const std::map< int, cv::KeyPoint > &kpts, const std::map< int, cv::KeyPoint > &previousKpts, const CameraModel &cameraModel, Transform &cameraTransform, int pnpIterations=100, float pnpReprojError=8.0f, int pnpFlags=0, int pnpRefineIterations=1, float ransacParam1=3.0f, float ransacParam2=0.99f, const std::map< int, cv::Point3f > &refGuess3D=std::map< int, cv::Point3f >(), double *variance=0)
void asyncSave(Signature *s)
static void limitKeypoints(std::vector< cv::KeyPoint > &keypoints, int maxKeypoints)
Signature * _lastSignature
void addSignatureToWmFromLTM(Signature *signature)
virtual Feature2D::Type getType() const =0
void setOccupancyGrid(const cv::Mat &ground, const cv::Mat &obstacles, const cv::Mat &empty, float cellSize, const cv::Point3f &viewPoint)
float _similarityThreshold
float getCellSize() const
static void post(UEvent *event, bool async=true, const UEventsSender *sender=0)
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
std::vector< cv::Point3f > generateKeypoints3D(const SensorData &data, const std::vector< cv::KeyPoint > &keypoints) const
void saveOptimizedPoses(const std::map< int, Transform > &optimizedPoses, const Transform &lastlocalizationPose) const
std::vector< K > uKeys(const std::multimap< K, V > &mm)
void addInfoAfterRun(int stMemSize, int lastSignAdded, int processMemUsed, int databaseMemUsed, int dictionarySize, const ParametersMap ¶meters) const
Transform getGroundTruthPose(int signatureId, bool lookInDatabase=false) const
const LaserScan & laserScanCompressed() const
const Transform & getGroundTruthPose() const
const std::multimap< int, cv::KeyPoint > & getWords() const
void setWords3(const std::multimap< int, cv::Point3f > &words3)
bool _imagesAlreadyRectified
std::map< int, Link > getLinks(int signatureId, bool lookInDatabase=false) const
cv::Mat generateDescriptors(const cv::Mat &image, std::vector< cv::KeyPoint > &keypoints) const
const std::vector< float > & getVelocity() const
virtual void parseParameters(const ParametersMap ¶meters)
void removeVirtualLinks(int signatureId)
#define ULOGGER_INFO(...)
void loadLinks(int signatureId, std::map< int, Link > &links, Link::Type type=Link::kUndef) const
bool isInSTM(int signatureId) const
void removeRawData(int id, bool image=true, bool scan=true, bool userData=true)
void setWords(const std::multimap< int, cv::KeyPoint > &words)
Transform computeTransformationMod(Signature &from, Signature &to, Transform guess=Transform::getIdentity(), RegistrationInfo *info=0) const
const Signature * getSignature(int id) const
Transform computeTransformation(const Signature &from, const Signature &to, Transform guess=Transform::getIdentity(), RegistrationInfo *info=0) const
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
std::string getDatabaseUrl() const
void getAllNodeIds(std::set< int > &ids, bool ignoreChildren=false, bool ignoreBadSignatures=false) const
float getMinDepth() const
std::pair< std::string, std::string > ParametersPair
bool UTILITE_EXP uStr2Bool(const char *str)
bool _transferSortingByWeightId
void generateGraph(const std::string &fileName, const std::set< int > &ids=std::set< int >())
bool _tfIdfLikelihoodUsed
std::vector< cv::KeyPoint > generateKeypoints(const cv::Mat &image, const cv::Mat &mask=cv::Mat()) const
void setReducedIds(const std::map< int, int > &reducedIds)
bool operator<(const WeightAgeIdKey &k) const
SensorData getNodeData(int nodeId, bool uncompressedData=false) const
void getAllLinks(std::multimap< int, Link > &links, bool ignoreNullLinks=true) const
Signature * createSignature(const SensorData &data, const Transform &pose, Statistics *stats=0)
const cv::Mat & descriptors() const
double transVariance() const
Signature * _getSignature(int id) const
bool _compressionParallelized
void getNodeData(int signatureId, SensorData &data, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const
virtual std::list< int > addNewWords(const cv::Mat &descriptors, int signatureId)
cv::Mat getImageCompressed(int signatureId) const
std::map< std::string, std::string > ParametersMap
void removeVirtualLinks()
virtual std::map< int, Transform > optimizeBA(int rootId, const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, const std::map< int, CameraModel > &models, std::map< int, cv::Point3f > &points3DMap, const std::map< int, std::map< int, cv::Point3f > > &wordReferences, std::set< int > *outliers=0)
const std::map< int, int > & getReferences() const
void loadWords(const std::set< int > &wordIds, std::list< VisualWord * > &vws)
float gridCellSize() const
void close(bool databaseSaved=true, bool postInitClosingEvents=false, const std::string &ouputDatabasePath="")
const std::vector< cv::KeyPoint > & keypoints() const
const std::multimap< int, cv::Mat > & getWordsDescriptors() const
void setCameraModels(const std::vector< CameraModel > &models)
Basic mathematics functions.
void addWordRef(int wordId, int signatureId)
void load(VWDictionary *dictionary, bool lastStateOnly=true) const
void setGPS(const GPS &gps)
std::vector< int > inliersIDs
Memory(const ParametersMap ¶meters=ParametersMap())
Some conversion functions.
const std::string & getUrl() const
Registration * _registrationPipeline
void getNodeCalibration(int nodeId, std::vector< CameraModel > &models, StereoCameraModel &stereoModel)
bool getNodeInfo(int signatureId, Transform &pose, int &mapId, int &weight, std::string &label, double &stamp, Transform &groundTruthPose, std::vector< float > &velocity, GPS &gps) const
const VisualWord * getWord(int id) const
void exportDictionary(const char *fileNameReferences, const char *fileNameDescriptors) const
const LaserScan & laserScanRaw() const
GLM_FUNC_DECL T pitch(detail::tquat< T, P > const &x)
void deleteLocation(int locationId, std::list< int > *deletedWords=0)
std::string getDatabaseVersion() const
void dumpDictionary(const char *fileNameRef, const char *fileNameDesc) const
const cv::Mat & imageRaw() const
void generateGraph(const std::string &fileName, const std::set< int > &ids=std::set< int >(), const std::map< int, Signature * > &otherSignatures=std::map< int, Signature * >())
void setUserData(const cv::Mat &userData)
unsigned int getIndexedWordsCount() const
bool _reextractLoopClosureFeatures
std::map< int, Link > getNeighborLinks(int signatureId, bool lookInDatabase=false) const
void setEnabled(bool enabled)
void initRectificationMap()
const Transform & transform() const
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP laserScanToPointCloud(const LaserScan &laserScan, const Transform &transform=Transform())
void setUserDataRaw(const cv::Mat &userDataRaw)
int getMaxFeatures() const
float getMaxDepth() const
void getAllLabels(std::map< int, std::string > &labels) const
void setImageRaw(const cv::Mat &imageRaw)
void saveLocationData(int locationId)
PreUpdateThread(VWDictionary *vwp)
virtual void dumpSignatures(const char *fileNameSign, bool words3D) const
std::vector< VisualWord * > getUnusedWords() const
bool init(const std::string &dbUrl, bool dbOverwritten=false, const ParametersMap ¶meters=ParametersMap(), bool postInitClosingEvents=false)
void savePreviewImage(const cv::Mat &image) const
void getNodeWords(int nodeId, std::multimap< int, cv::KeyPoint > &words, std::multimap< int, cv::Point3f > &words3, std::multimap< int, cv::Mat > &wordsDescriptors)
cv::Mat RTABMAP_EXP interpolate(const cv::Mat &image, int factor, float depthErrorRatio=0.02f)
double getEmptyTrashesTime() const
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud< pcl::PointXYZ > &cloud, const Transform &transform=Transform(), bool filterNaNs=true)
const std::string & getLabel() const
bool uIsFinite(const T &value)
void moveToTrash(Signature *s, bool keepLinkedToGraph=true, std::list< int > *deletedWords=0)
void getNodeIdByLabel(const std::string &label, int &id) const
bool openConnection(const std::string &url, bool overwritten=false)
#define UASSERT(condition)
void setLastWordId(int id)
std::set< int > reactivateSignatures(const std::list< int > &ids, unsigned int maxLoaded, double &timeDbAccess)
bool isValidForProjection() const
const CameraModel & left() const
virtual void parseParameters(const ParametersMap ¶meters)
bool isIncrementalFlann() const
void createLocalMap(const Signature &node, cv::Mat &groundCells, cv::Mat &obstacleCells, cv::Mat &emptyCells, cv::Point3f &viewPoint) const
T uMax3(const T &a, const T &b, const T &c)
static Feature2D * create(const ParametersMap ¶meters=ParametersMap())
void setWeight(int weight)
std::map< int, Transform > loadOptimizedPoses(Transform *lastlocalizationPose) const
std::map< int, Transform > loadOptimizedPoses(Transform *lastlocalizationPose) const
bool hasLink(int idTo) const
virtual void dumpMemory(std::string directory) const
#define UASSERT_MSG(condition, msg_str)
void clearCompressedData()
void closeConnection(bool save=true, const std::string &outputUrl="")
pcl::PointCloud< pcl::PointXYZINormal >::Ptr RTABMAP_EXP laserScanToPointCloudINormal(const LaserScan &laserScan, const Transform &transform=Transform(), float intensity=0.0f)
void loadSignatures(const std::list< int > &ids, std::list< Signature * > &signatures, std::set< int > *loadedFromTrash=0)
bool update(const SensorData &data, Statistics *stats=0)
float _laserScanDownsampleStepSize
void rehearsal(Signature *signature, Statistics *stats=0)
cv::Mat RTABMAP_EXP decimate(const cv::Mat &image, int d)
int getSignatureIdByLabel(const std::string &label, bool lookInDatabase=true) const
const std::map< int, Signature * > & getSignatures() const
Link merge(const Link &link, Type outputType) const
bool isScanRequired() const
void disableWordsRef(int signatureId)
cv::Mat load2DMap(float &xMin, float &yMin, float &cellSize) const
std::vector< int > findNN(const std::list< VisualWord * > &vws) const
virtual void parseParameters(const ParametersMap ¶meters)
bool getCalibration(int signatureId, std::vector< CameraModel > &models, StereoCameraModel &stereoModel) const
void setWordsDescriptors(const std::multimap< int, cv::Mat > &descriptors)
Transform computeTransform(Signature &fromS, Signature &toS, Transform guess, RegistrationInfo *info=0, bool useKnownCorrespondencesIfPossible=false) const
std::list< V > uVectorToList(const std::vector< V > &v)
WeightAgeIdKey(int w, double a, int i)
const cv::Mat & userDataCompressed() const
bool _localBundleOnLoopClosure
void save2DMap(const cv::Mat &map, float xMin, float yMin, float cellSize) const
void setVelocity(float vx, float vy, float vz, float vroll, float vpitch, float vyaw)
RegistrationIcp * _registrationIcpMulti
void clear(bool printWarningsIfNotEmpty=true)
void updateLink(const Link &link)
Transform localTransform() const
long getMemoryUsed() const
static const int kIdStart
bool _createOccupancyGrid
void loadNodeData(std::list< Signature * > &signatures, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const
void saveOptimizedMesh(const cv::Mat &cloud, const std::vector< std::vector< std::vector< unsigned int > > > &polygons=std::vector< std::vector< std::vector< unsigned int > > >(), const std::vector< std::vector< Eigen::Vector2f > > &texCoords=std::vector< std::vector< Eigen::Vector2f > >(), const cv::Mat &textures=cv::Mat()) const
std::list< int > forget(const std::set< int > &ignoredIds=std::set< int >())
SensorData getSignatureDataConst(int locationId, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const
const cv::Mat & depthOrRightRaw() const
cv::Mat RTABMAP_EXP compressData2(const cv::Mat &data)
static const int kIdInvalid
static ULogger::Level level()
std::map< int, int > getNeighborsId(int signatureId, int maxGraphDepth, int maxCheckedInDatabase=-1, bool incrementMarginOnLoop=false, bool ignoreLoopIds=false, bool ignoreIntermediateNodes=false, bool ignoreLocalSpaceLoopIds=false, const std::set< int > &nodesSet=std::set< int >(), double *dbAccessTime=0) const
void moveSignatureToWMFromSTM(int id, int *reducedTo=0)
std::list< Signature * > getRemovableSignatures(int count, const std::set< int > &ignoredIds=std::set< int >())
float _laserScanVoxelSize
bool _rectifyOnlyFeatures
void addStatistics(const Statistics &statistics) const
bool uContains(const std::list< V > &list, const V &value)
void setPose(const Transform &pose)
void setSaved(bool saved)
void setLabel(const std::string &label)
static DBDriver * create(const ParametersMap ¶meters=ParametersMap())
const VWDictionary * getVWDictionary() const
bool _saveIntermediateNodeData
float compareTo(const Signature &signature) const
std::vector< CameraModel > _rectCameraModels
cv::Mat rectifyImage(const cv::Mat &raw, int interpolation=cv::INTER_LINEAR) const
void enableWordsRef(const std::list< int > &signatureIds)
int incrementMapId(std::map< int, int > *reducedIds=0)
const cv::Mat & userDataCompressed() const
void uSleep(unsigned int ms)
int getLastSignatureId() const
void removeAllVirtualLinks()
StereoCameraModel _rectStereoCameraModel
static const ParametersMap & getDefaultParameters()
const std::map< int, Link > & getLinks() const
bool _notLinkedNodesKeptInDb
const std::vector< CameraModel > & cameraModels() const
const Transform & getPose() const
virtual void parseParameters(const ParametersMap ¶meters)
static Registration * create(const ParametersMap ¶meters)
void getMetricConstraints(const std::set< int > &ids, std::map< int, Transform > &poses, std::multimap< int, Link > &links, bool lookInDatabase=false)
bool _badSignaturesIgnored
bool _useOdometryFeatures
static const int kIdVirtual
SensorData & sensorData()
void removeWords(const std::vector< VisualWord * > &words)
bool isValidForRectification() const
const CameraModel & right() const
void updateLink(const Link &link, bool updateInDatabase=false)
std::map< int, Link > getLoopClosureLinks(int signatureId, bool lookInDatabase=false) const
std::multimap< int, Link >::iterator RTABMAP_EXP findLink(std::multimap< int, Link > &links, int from, int to, bool checkBothWays=true)
float _rehearsalMaxDistance
const Signature * getLastWorkingSignature() const
std::map< int, std::string > getAllLabels() const
const cv::Mat & getCompressedData() const
bool rehearsalMerge(int oldId, int newId)
pcl::PointCloud< pcl::PointNormal >::Ptr RTABMAP_EXP laserScanToPointCloudNormal(const LaserScan &laserScan, const Transform &transform=Transform())
bool getNodeInfo(int signatureId, Transform &odomPose, int &mapId, int &weight, std::string &label, double &stamp, Transform &groundTruth, std::vector< float > &velocity, GPS &gps, bool lookInDatabase=false) const
static long int getMemoryUsage()
std::map< int, float > getNeighborsIdRadius(int signatureId, float radius, const std::map< int, Transform > &optimizedPoses, int maxGraphDepth) const
void savePreviewImage(const cv::Mat &image) const
void saveStatistics(const Statistics &statistics)
#define ULOGGER_WARN(...)
void saveOptimizedPoses(const std::map< int, Transform > &optimizedPoses, const Transform &lastlocalizationPose) const
ULogger class and convenient macros.
const StereoCameraModel & stereoCameraModel() const
cv::Mat load2DMap(float &xMin, float &yMin, float &cellSize) const
bool isBinDataKept() const
unsigned int getNotIndexedWordsCount() const
void removeAllWordRef(int wordId, int signatureId)
bool isImageRequired() const
bool _idUpdatedToNewOneRehearsal
void setTimestampUpdateEnabled(bool enabled)
GLM_FUNC_DECL T yaw(detail::tquat< T, P > const &x)
bool memoryChanged() const
const cv::Mat & imageCompressed() const
std::map< int, float > computeLikelihood(const Signature *signature, const std::list< int > &ids)
std::string getDatabaseVersion() const
std::map< int, int > getWeights() const
float _laserScanNormalRadius
unsigned int getUnusedWordsSize() const
void loadLastNodes(std::list< Signature * > &signatures) const
void parseParameters(const ParametersMap ¶meters)
void addLink(const Link &link)
void setGroundTruth(const Transform &pose)
cv::Mat RTABMAP_EXP cvtDepthFromFloat(const cv::Mat &depth32F)
std::multimap< int, Link > getAllLinks(bool lookInDatabase, bool ignoreNullLinks=true) const
std::set< int > getAllSignatureIds() const
LaserScan RTABMAP_EXP commonFiltering(const LaserScan &scan, int downsamplingStep, float rangeMin=0.0f, float rangeMax=0.0f, float voxelSize=0.0f, int normalK=0, float normalRadius=0.0f, bool forceGroundNormalsUp=false)
ParametersMap parameters_
bool isIncremental() const
void updateAge(int signatureId)
void saveOptimizedMesh(const cv::Mat &cloud, const std::vector< std::vector< std::vector< unsigned int > > > &polygons=std::vector< std::vector< std::vector< unsigned int > > >(), const std::vector< std::vector< Eigen::Vector2f > > &texCoords=std::vector< std::vector< Eigen::Vector2f > >(), const cv::Mat &textures=cv::Mat()) const
Transform getOdomPose(int signatureId, bool lookInDatabase=false) const
pcl::PointCloud< pcl::PointXYZI >::Ptr RTABMAP_EXP laserScanToPointCloudI(const LaserScan &laserScan, const Transform &transform=Transform(), float intensity=0.0f)
std::map< int, Signature * > _signatures
void join(bool killFirst=false)
void removeLink(int idTo)
virtual void addWord(VisualWord *vw)
void dumpMemoryTree(const char *fileNameTree) const
void addLink(const Link &link)
bool _rehearsalWeightIgnoredWhileMoving
bool _covOffDiagonalIgnored
#define ULOGGER_ERROR(...)
VisualWord * getUnusedWord(int id) const
bool isBadSignature() const
void copyData(const Signature *from, Signature *to)
int getTotalActiveReferences() const
virtual bool isInMemory() const
void setStereoCameraModel(const StereoCameraModel &stereoCameraModel)
bool isIncremental() const
void getInvertedIndexNi(int signatureId, int &ni) const
void setDepthOrRightRaw(const cv::Mat &depthOrImageRaw)
int _lastGlobalLoopClosureId
void save2DMap(const cv::Mat &map, float xMin, float yMin, float cellSize) const
Transform computeIcpTransformMulti(int newId, int oldId, const std::map< int, Transform > &poses, RegistrationInfo *info=0)
void addSignatureToStm(Signature *signature, const cv::Mat &covariance)
virtual ~PreUpdateThread()
std::string UTILITE_EXP uFormat(const char *fmt,...)
std::string UTILITE_EXP uNumber2Str(unsigned int number)
virtual void parseParameters(const ParametersMap ¶meters)
bool setUserData(int id, const cv::Mat &data)
void getLastWordId(int &id) const
virtual void parseParameters(const ParametersMap ¶meters)
std::map< int, double > _workingMem
int getNi(int signatureId) const
V uValue(const std::map< K, V > &m, const K &key, const V &defaultValue=V())
void emptyTrashes(bool async=false)
void setFeatures(const std::vector< cv::KeyPoint > &keypoints, const std::vector< cv::Point3f > &keypoints3D, const cv::Mat &descriptors)
double getDbSavingTime() const
void loadDataFromDb(bool postInitClosingEvents)
bool addLink(const Link &link, bool addInDatabase=false)
const std::map< int, VisualWord * > & getVisualWords() const
bool hasIntensity() const
int getDatabaseMemoryUsed() const
void addStatistic(const std::string &name, float value)
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
bool isRectificationMapInitialized()
const Transform & localTransform() const
void setLaserScanRaw(const LaserScan &laserScanRaw)
cv::Mat RTABMAP_EXP compressImage2(const cv::Mat &image, const std::string &format=".png")