45 #include <opencv2/calib3d/calib3d.hpp> 47 #include <pcl/common/io.h> 50 #define ISFINITE(value) _finite(value) 52 #define ISFINITE(value) std::isfinite(value) 59 maximumMapSize_(
Parameters::defaultOdomF2MMaxSize()),
60 keyFrameThr_(
Parameters::defaultOdomKeyFrameThr()),
61 visKeyFrameThr_(
Parameters::defaultOdomVisKeyFrameThr()),
62 maxNewFeatures_(
Parameters::defaultOdomF2MMaxNewFeatures()),
63 scanKeyFrameThr_(
Parameters::defaultOdomScanKeyFrameThr()),
64 scanMaximumMapSize_(
Parameters::defaultOdomF2MScanMaxSize()),
65 scanSubtractRadius_(
Parameters::defaultOdomF2MScanSubtractRadius()),
66 scanSubtractAngle_(
Parameters::defaultOdomF2MScanSubtractAngle()),
67 scanMapMaxRange_(
Parameters::defaultOdomF2MScanRange()),
68 bundleAdjustment_(
Parameters::defaultOdomF2MBundleAdjustment()),
69 bundleMaxFrames_(
Parameters::defaultOdomF2MBundleAdjustmentMaxFrames()),
70 validDepthRatio_(
Parameters::defaultOdomF2MValidDepthRatio()),
71 pointToPlaneK_(
Parameters::defaultIcpPointToPlaneK()),
72 pointToPlaneRadius_(
Parameters::defaultIcpPointToPlaneRadius()),
75 lastFrameOldestNewId_(0),
114 UWARN(
"Selected bundle adjustment approach (\"%s\"=\"%d\") is not available, " 115 "local bundle adjustment is then disabled.", Parameters::kOdomF2MBundleAdjustment().c_str(),
bundleAdjustment_);
125 int corType = Parameters::defaultVisCorType();
129 UWARN(
"%s=%d is not supported by OdometryF2M, using Features matching approach instead (type=0).",
130 Parameters::kVisCorType().c_str(),
136 int estType = Parameters::defaultVisEstimationType();
140 UWARN(
"%s=%d is not supported by OdometryF2M, using 2D->3D approach instead (type=1).",
141 Parameters::kVisEstimationType().c_str(),
147 bool forwardEst = Parameters::defaultVisForwardEstOnly();
151 UWARN(
"%s=false is not supported by OdometryF2M, setting to true.",
152 Parameters::kVisForwardEstOnly().c_str());
160 UWARN(
"%s=%d cannot be used with registration not done only with images (%s=%s), disabling bundle adjustment.",
161 Parameters::kOdomF2MBundleAdjustment().c_str(),
163 Parameters::kRegStrategy().c_str(),
164 uValue(bundleParameters, Parameters::kRegStrategy(),
uNumber2Str(Parameters::defaultRegStrategy())).c_str());
227 UERROR(
"IMU received doesn't have orientation set, it is ignored. If you are using RTAB-Map standalone, enable IMU filtering in Preferences->Source panel. On ROS, use \"imu_filter_madgwick\" or \"imu_complementary_filter\" packages to compute the orientation.");
238 Transform newFramePose =
Transform(previous.
x(), previous.
y(), previous.
z(), imuQuat.x(), imuQuat.y(), imuQuat.z(), imuQuat.w());
239 UWARN(
"Updated initial pose from %s to %s with IMU orientation", previous.
prettyPrint().c_str(), newFramePose.
prettyPrint().c_str());
241 this->
reset(newFramePose);
264 UERROR(
"Odometry bundle adjustment doesn't work with multi-cameras. It is disabled.");
267 bool addKeyFrame =
false;
268 int totalBundleWordReferencesUsed = 0;
269 int totalBundleOutliers = 0;
270 float bundleTime = 0.0f;
271 bool visDepthAsMask = Parameters::defaultVisDepthAsMask();
285 std::map<int, cv::Point3f> points3DMap;
286 std::map<int, Transform> bundlePoses;
287 std::multimap<int, Link> bundleLinks;
288 std::map<int, CameraModel> bundleModels;
290 for(
int guessIteration=0;
301 bundleModels.clear();
303 float maxCorrespondenceDistance = 0.0f;
304 float pmOutlierRatio = 0.0f;
311 maxCorrespondenceDistance = Parameters::defaultIcpMaxCorrespondenceDistance();
312 pmOutlierRatio = Parameters::defaultIcpPMOutlierRatio();
321 if(guessIteration == 1)
323 UWARN(
"Failed to find a transformation with the provided guess (%s), trying again without a guess.", guess.
prettyPrint().c_str());
333 if(maxCorrespondenceDistance>0.0
f)
345 if(!transform.isNull())
353 UDEBUG(
"Local Bundle Adjustment");
361 UERROR(
"Bundle Adjustment cannot be used with a registration approach recomputing features from the \"from\" signature (e.g., Optical Flow).");
376 uFormat(
"Frame %d already added! Make sure the input frames have unique IDs!",
lastFrame_->
id()).c_str());
378 bundlePoses.insert(std::make_pair(
lastFrame_->
id(), transform));
403 UFATAL(
"no valid camera model to do odometry bundle adjustment!");
405 bundleModels.insert(std::make_pair(
lastFrame_->
id(), model));
409 std::map<int, std::map<int, FeatureBA> > wordReferences;
410 for(
unsigned int i=0; i<regInfo.
inliersIDs.size(); ++i)
415 std::multimap<int, int>::const_iterator iter3D = tmpMap.
getWords().find(wordId);
417 points3DMap.insert(std::make_pair(wordId, tmpMap.
getWords3()[iter3D->second]));
423 std::map<int, FeatureBA> references;
430 for(std::map<int, FeatureBA>::iterator jter=refIter->second.begin(); jter!=refIter->second.end(); ++jter)
432 if(oi++ % step == 0 && bundlePoses.find(jter->first)!=bundlePoses.end())
434 references.insert(*jter);
435 ++totalBundleWordReferencesUsed;
439 if(refIter->second.size() > 1)
441 if(references.insert(*refIter->second.rbegin()).second)
443 ++totalBundleWordReferencesUsed;
461 wordReferences.insert(std::make_pair(wordId, references));
472 std::set<int> sbaOutliers;
474 bundlePoses =
sba_->
optimizeBA(-
lastFrame_->
id(), bundlePoses, bundleLinks, bundleModels, points3DMap, wordReferences, &sbaOutliers);
475 bundleTime = bundleTimer.
ticks();
477 totalBundleOutliers = (int)sbaOutliers.size();
479 UDEBUG(
"bundleTime=%fs (poses=%d wordRef=%d outliers=%d)", bundleTime, (
int)bundlePoses.size(), (int)
bundleWordReferences_.size(), (int)sbaOutliers.size());
486 UDEBUG(
"Local Bundle Adjustment Before: %s", transform.prettyPrint().c_str());
489 if(!bundlePoses.rbegin()->second.isNull())
491 if(sbaOutliers.size())
493 std::vector<int> newInliers(regInfo.
inliersIDs.size());
495 for(
unsigned int i=0; i<regInfo.
inliersIDs.size(); ++i)
497 if(sbaOutliers.find(regInfo.
inliersIDs[i]) == sbaOutliers.end())
502 newInliers.resize(oi);
503 UDEBUG(
"BA outliers ratio %f",
float(sbaOutliers.size())/
float(regInfo.
inliersIDs.size()));
504 regInfo.
inliers = (int)newInliers.size();
514 transform = bundlePoses.rbegin()->second;
516 UASSERT(iter != bundleLinks.end());
517 iter->second.setTransform(
bundlePoses_.rbegin()->second.inverse()*transform);
522 float rollImu,pitchImu,
yaw;
523 iter->second.transform().getEulerAngles(rollImu, pitchImu, yaw);
525 transform.getEulerAngles(roll, pitch, yaw);
531 UDEBUG(
"Local Bundle Adjustment After : %s", transform.prettyPrint().c_str());
535 UWARN(
"Local bundle adjustment failed! transform is not refined.");
540 if(!transform.isNull())
547 if(transform.isNull())
549 if(guessIteration == 1)
551 UWARN(
"Trial with no guess still fail.");
566 UWARN(
"Unknown registration error");
569 else if(guessIteration == 1)
571 UWARN(
"Trial with no guess succeeded!");
579 bool modified =
false;
584 std::multimap<int, int> mapWords = tmpMap.
getWords();
585 std::vector<cv::KeyPoint> mapWordsKpts = tmpMap.
getWordsKpts();
586 std::vector<cv::Point3f> mapPoints = tmpMap.
getWords3();
599 addKeyFrame = addKeyFrame || addVisualKeyFrame || addGeometricKeyFrame;
609 UDEBUG(
"Update local map");
612 UASSERT(mapWords.size() == mapPoints.size());
613 UASSERT(mapWords.size() == mapWordsKpts.size());
614 UASSERT((
int)mapPoints.size() == mapDescriptors.rows);
622 UASSERT(iter != bundleLinks.end());
625 if(iter != bundleLinks.end())
635 for(std::map<int, cv::Point3f>::iterator iter=points3DMap.begin(); iter!=points3DMap.end(); ++iter)
637 UASSERT(mapWords.count(iter->first) == 1);
639 mapPoints[mapWords.find(iter->first)->second] = iter->second;
644 std::multimap<float, std::pair<int, std::pair<cv::KeyPoint, std::pair<cv::Point3f, cv::Mat> > > > newIds;
647 std::set<int> seenStatusUpdated;
661 UFATAL(
"no valid camera model!");
666 bool addPointsWithoutDepth =
false;
669 int ptsWithDepth = 0;
681 if(!addPointsWithoutDepth)
683 UWARN(
"Not enough points with valid depth in current frame (%d/%d=%f < %s=%f), points without depth are not added to map.",
692 if(mapWords.find(iter->first) == mapWords.end())
697 std::make_pair(kpt.response>0?1.0f/kpt.response:0.0f,
698 std::make_pair(iter->first,
707 std::multimap<int, int>::iterator iterKpts = mapWords.find(iter->first);
708 if(iterKpts!=mapWords.end() && !mapWordsKpts.empty())
710 mapWordsKpts[iterKpts->second].octave = kpt.octave;
714 iterBundlePosesRef->second += 1;
724 std::map<int, FeatureBA> framePt;
735 UDEBUG(
"newIds=%d", (
int)newIds.size());
739 for(std::multimap<
float, std::pair<
int, std::pair<cv::KeyPoint, std::pair<cv::Point3f, cv::Mat> > > >::reverse_iterator iter=newIds.rbegin();
750 iterBundlePosesRef->second += 1;
760 std::map<int, FeatureBA> framePt;
771 mapWords.insert(mapWords.end(), std::make_pair(iter->second.first, mapWords.size()));
772 mapWordsKpts.push_back(iter->second.second.first);
773 cv::Point3f pt = iter->second.second.second.first;
777 float x = iter->second.second.first.pt.x;
778 float y = iter->second.second.first.pt.y;
784 int cameraIndex = int(x / subImageWidth);
786 x = x-subImageWidth*cameraIndex;
805 float scaleInf = (0.05 * model.
fx()) / 0.01;
809 mapDescriptors.push_back(iter->second.second.second.second);
828 for(
unsigned int i=0; i<regInfo.
projectedIDs.size(); ++i)
836 UDEBUG(
"projected added=%d/%d minLastFrameId=%d", oi, (
int)regInfo.
projectedIDs.size(), lastFrameOldestNewId);
838 for(
unsigned int i=0; i<ids.size() && (int)mapWords.size() >
maximumMapSize_ && mapWords.size() >= newIds.size(); ++i)
841 if(inliers.find(
id) == inliers.end())
846 for(std::map<int, FeatureBA>::iterator iterFrame = iterRef->second.begin(); iterFrame != iterRef->second.end(); ++iterFrame)
862 for(std::multimap<int, int>::iterator iter = mapWords.begin();
863 iter!=mapWords.end() && (int)mapWords.size() >
maximumMapSize_ && mapWords.size() >= newIds.size();)
865 if(inliers.find(iter->first) == inliers.end())
867 std::map<int, std::map<int, FeatureBA> >::iterator iterRef =
bundleWordReferences_.find(iter->first);
870 for(std::map<int, FeatureBA>::iterator iterFrame = iterRef->second.begin(); iterFrame != iterRef->second.end(); ++iterFrame)
880 mapWords.erase(iter++);
889 if(mapWords.size() != mapPoints.size())
892 std::vector<cv::KeyPoint> mapWordsKptsClean(mapWords.size());
893 std::vector<cv::Point3f> mapPointsClean(mapWords.size());
894 cv::Mat mapDescriptorsClean(mapWords.size(), mapDescriptors.cols, mapDescriptors.type());
896 for(std::multimap<int, int>::iterator iter = mapWords.begin(); iter!=mapWords.end(); ++iter, ++index)
898 mapWordsKptsClean[index] = mapWordsKpts[iter->second];
899 mapPointsClean[index] = mapPoints[iter->second];
900 mapDescriptors.row(iter->second).copyTo(mapDescriptorsClean.row(index));
901 iter->second = index;
903 mapWordsKpts = mapWordsKptsClean;
904 mapWordsKptsClean.clear();
905 mapPoints = mapPointsClean;
906 mapPointsClean.clear();
907 mapDescriptors = mapDescriptorsClean;
910 Link * previousLink = 0;
913 if(iter->second <= 0)
919 UASSERT(previousLink->
to() == iter->first);
920 *previousLink = previousLink->
merge(
bundleLinks_.find(iter->first)->second, previousLink->type());
945 UDEBUG(
"Update local features map = %fs", tmpTimer.
ticks());
955 pcl::PointCloud<pcl::PointXYZINormal>::Ptr frameCloudNormals (
new pcl::PointCloud<pcl::PointXYZINormal>());
970 pcl::IndicesPtr frameCloudNormalsIndices(
new std::vector<int>);
977 pcl::IndicesPtr(
new std::vector<int>),
979 pcl::IndicesPtr(
new std::vector<int>),
982 newPoints = frameCloudNormalsIndices->size();
986 newPoints = mapCloudNormals->size();
994 pcl::PointCloud<pcl::PointXYZINormal> tmp;
995 pcl::copyPointCloud(*frameCloudNormals, *frameCloudNormalsIndices, tmp);
1000 UINFO(
"mapSize=%d newPoints=%d maxPoints=%d",
1001 int(mapCloudNormals->size()),
1005 *mapCloudNormals += tmp;
1012 mapCloudNormals =
util3d::cropBox(mapCloudNormals, Eigen::Vector4f(boxMin.x, boxMin.y, boxMin.z, 0 ), Eigen::Vector4f(boxMax.x, boxMax.y, boxMax.z, 0 ));
1015 *mapCloudNormals += tmp;
1019 pcl::PointCloud<pcl::PointXYZI>::Ptr mapCloud (
new pcl::PointCloud<pcl::PointXYZI> ());
1020 copyPointCloud(*mapCloudNormals, *mapCloud);
1022 copyPointCloud(*normals, *mapCloudNormals);
1025 scansBuffer_.push_back(std::make_pair(frameCloudNormals, frameCloudNormalsIndices));
1028 UDEBUG(
"scansBuffer=%d, mapSize=%d newPoints=%d maxPoints=%d",
1030 int(mapCloudNormals->size()),
1038 mapCloudNormals->clear();
1039 std::list<int> toRemove;
1054 pcl::PointCloud<pcl::PointXYZINormal> tmp;
1056 *mapCloudNormals += tmp;
1067 std::vector<std::pair<pcl::PointCloud<pcl::PointXYZINormal>::Ptr, pcl::IndicesPtr> > scansTmp(
scansBuffer_.size()-i);
1071 UASSERT(oi < (
int)scansTmp.size());
1082 pcl::PointCloud<pcl::PointXYZINormal> tmp;
1084 *mapCloudNormals += tmp;
1095 Transform mapViewpoint(-newFramePose.
x(), -newFramePose.
y(),0,0,0,0);
1100 Transform mapViewpoint(-newFramePose.
x(), -newFramePose.
y(), -newFramePose.
z(),0,0,0);
1106 UDEBUG(
"Update local scan map = %fs", tmpTimer.
ticks());
1135 map_->
setWords(mapWords, mapWordsKpts, mapPoints, mapDescriptors);
1149 for(std::multimap<int, int>::const_iterator iter=tmpMap.
getWords().begin(); iter!=tmpMap.
getWords().end(); ++iter)
1151 info->
localMap.insert(std::make_pair(iter->first, tmpMap.
getWords3()[iter->second]));
1172 regInfo.
covariance = cv::Mat::eye(6,6,CV_64FC1)*9999.0;
1174 bool frameValid =
false;
1179 int ptsWithDepth = 0;
1198 std::multimap<int, int> words;
1199 std::vector<cv::KeyPoint> wordsKpts;
1200 std::vector<cv::Point3f> transformedPoints;
1201 std::multimap<int, int> mapPointWeights;
1202 cv::Mat descriptors;
1212 words.insert(words.end(), std::make_pair(iter->first, words.size()));
1215 mapPointWeights.insert(std::make_pair(iter->first, 0));
1234 UFATAL(
"no valid camera model!");
1238 if(!wordsKpts.empty())
1240 for(std::multimap<int, int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
1242 if(words.count(iter->first) == 1)
1245 std::map<int, FeatureBA> framePt;
1284 UFATAL(
"invalid camera model!");
1295 map_->
setWords(words, wordsKpts, transformedPoints, descriptors);
1309 double complexity = 0.0;;
1312 float minComplexity = Parameters::defaultIcpPointToPlaneMinComplexity();
1313 bool p2n = Parameters::defaultIcpPointToPlane();
1316 if(p2n && minComplexity>0.0
f)
1321 if(complexity > minComplexity)
1328 UWARN(
"Input raw scan doesn't have normals, complexity check on first frame is not done.");
1341 UINFO(
"Local map will be updated using range instead of time with range threshold set at %f",
scanMapMaxRange_);
1343 scansBuffer_.push_back(std::make_pair(mapCloudNormals, pcl::IndicesPtr(
new std::vector<int>)));
1347 Transform mapViewpoint(-newFramePose.
x(), -newFramePose.
y(),0,0,0,0);
1358 Transform mapViewpoint(-newFramePose.
x(), -newFramePose.
y(), -newFramePose.
z(),0,0,0);
1372 UWARN(
"Scan complexity too low (%f) to init first keyframe.", complexity);
1377 UWARN(
"Missing scan to initialize odometry.");
1414 info->
words.clear();
1437 info->
reg = regInfo;
1445 UINFO(
"Odom update time = %fs lost=%s features=%d inliers=%d/%d variance:lin=%f, ang=%f local_map=%d local_scan_map=%d",
1447 output.
isNull()?
"true":
"false",
GLM_FUNC_DECL T roll(detail::tquat< T, P > const &x)
bool RTABMAP_EXP isFinite(const cv::Point3f &pt)
static bool parse(const ParametersMap ¶meters, const std::string &key, bool &value)
int getMinVisualCorrespondences() const
float gravitySigma() const
pcl::PointCloud< pcl::PointXYZRGB >::Ptr RTABMAP_EXP subtractFiltering(const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &cloud, const pcl::PointCloud< pcl::PointXYZRGB >::Ptr &substractCloud, float radiusSearch, int minNeighborsInRadius=1)
ParametersMap parameters_
unsigned int framesProcessed() const
std::map< int, CameraModel > localBundleModels
const cv::Size & imageSize() const
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
const cv::Mat & data() const
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP transformPointCloud(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const Transform &transform)
void setLaserScan(const LaserScan &laserScan, bool clearPreviousData=true)
OdometryF2M(const rtabmap::ParametersMap ¶meters=rtabmap::ParametersMap())
bool isInfoDataFilled() const
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, FeatureBA > > &wordReferences, std::set< int > *outliers=0)
virtual void reset(const Transform &initialPose=Transform::getIdentity())
Transform computeTransformationMod(Signature &from, Signature &to, Transform guess=Transform::getIdentity(), RegistrationInfo *info=0) const
std::map< int, cv::Point3f > localMap
float pointToPlaneRadius_
Registration * regPipeline_
std::vector< std::pair< pcl::PointCloud< pcl::PointXYZINormal >::Ptr, pcl::IndicesPtr > > scansBuffer_
std::pair< std::string, std::string > ParametersPair
const cv::Mat & descriptors() const
std::map< std::string, std::string > ParametersMap
std::string UTILITE_EXP uBool2Str(bool boolean)
virtual Transform computeTransform(SensorData &data, const Transform &guess=Transform(), OdometryInfo *info=0)
const std::vector< cv::KeyPoint > & keypoints() const
const Transform & getPose() const
Basic mathematics functions.
std::vector< int > inliersIDs
Some conversion functions.
std::map< int, std::map< int, FeatureBA > > bundleWordReferences_
const LaserScan & laserScanRaw() const
GLM_FUNC_DECL T pitch(detail::tquat< T, P > const &x)
const cv::Mat & imageRaw() const
float scanSubtractRadius_
int localBundleConstraints
static bool isAvailable(Optimizer::Type type)
GLM_FUNC_DECL genType step(genType const &edge, genType const &x)
const std::vector< cv::KeyPoint > & getWordsKpts() const
std::multimap< int, Link > bundleIMUOrientations_
cv::Mat RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud< pcl::PointXYZ > &cloud, const Transform &transform=Transform(), bool filterNaNs=true)
#define UASSERT(condition)
bool isValidForProjection() const
const CameraModel & left() const
const std::multimap< int, int > & getWords() const
std::map< int, int > bundlePoseReferences_
int lastFrameOldestNewId_
#define UASSERT_MSG(condition, msg_str)
pcl::PointCloud< pcl::PointXYZINormal >::Ptr RTABMAP_EXP laserScanToPointCloudINormal(const LaserScan &laserScan, const Transform &transform=Transform(), float intensity=0.0f)
std::vector< int > projectedIDs
Link merge(const Link &link, Type outputType) const
bool isScanRequired() const
std::map< int, Transform > bundlePoses_
virtual void parseParameters(const ParametersMap ¶meters)
std::map< int, Transform > localBundlePoses
cv::Mat RTABMAP_EXP computeNormals(const cv::Mat &laserScan, int searchK, float searchRadius)
const cv::Mat & getWordsDescriptors() const
Transform localTransform() const
virtual bool canProcessIMU() const
const std::vector< CameraModel > & cameraModels() const
static Registration * create(const ParametersMap ¶meters)
const std::vector< cv::Point3f > & getWords3() const
Eigen::Vector3f RTABMAP_EXP projectDepthTo3DRay(const cv::Size &imageSize, float x, float y, float cx, float cy, float fx, float fy)
std::multimap< int, cv::KeyPoint > words
SensorData & sensorData()
std::multimap< int, Link >::iterator RTABMAP_EXP findLink(std::multimap< int, Link > &links, int from, int to, bool checkBothWays=true)
void setWords(const std::multimap< int, int > &words, const std::vector< cv::KeyPoint > &keypoints, const std::vector< cv::Point3f > &words3, const cv::Mat &descriptors)
pcl::IndicesPtr RTABMAP_EXP cropBox(const pcl::PCLPointCloud2::Ptr &cloud, const pcl::IndicesPtr &indices, const Eigen::Vector4f &min, const Eigen::Vector4f &max, const Transform &transform=Transform::getIdentity(), bool negative=false)
ULogger class and convenient macros.
const StereoCameraModel & stereoCameraModel() const
bool isImageRequired() const
GLM_FUNC_DECL T yaw(detail::tquat< T, P > const &x)
std::vector< int > matchesIDs
virtual void reset(const Transform &initialPose=Transform::getIdentity())
std::multimap< int, Link > bundleLinks_
pcl::PointCloud< pcl::PointXYZ >::Ptr RTABMAP_EXP voxelize(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const pcl::IndicesPtr &indices, float voxelSize)
const std::map< double, Transform > & imus() const
std::string UTILITE_EXP uFormat(const char *fmt,...)
std::string UTILITE_EXP uNumber2Str(unsigned int number)
static Optimizer * create(const ParametersMap ¶meters)
std::map< int, CameraModel > bundleModels_
V uValue(const std::map< K, V > &m, const K &key, const V &defaultValue=V())
float RTABMAP_EXP computeNormalsComplexity(const LaserScan &scan, const Transform &t=Transform::getIdentity(), cv::Mat *pcaEigenVectors=0, cv::Mat *pcaEigenValues=0)
void setFeatures(const std::vector< cv::KeyPoint > &keypoints, const std::vector< cv::Point3f > &keypoints3D, const cv::Mat &descriptors)
const std::vector< cv::Point3f > & keypoints3D() const
RegistrationInfo copyWithoutData() const
void uInsert(std::map< K, V > &map, const std::pair< K, V > &pair)
const Transform & localTransform() const
LaserScan RTABMAP_EXP laserScanFromPointCloud(const pcl::PCLPointCloud2 &cloud, bool filterNaNs=true, bool is2D=false, const Transform &transform=Transform())