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 initDepthFactor_(
Parameters::defaultOdomF2MInitDepthFactor()),
64 floorThreshold_(
Parameters::defaultOdomF2MFloorThreshold()),
65 scanKeyFrameThr_(
Parameters::defaultOdomScanKeyFrameThr()),
66 scanMaximumMapSize_(
Parameters::defaultOdomF2MScanMaxSize()),
67 scanSubtractRadius_(
Parameters::defaultOdomF2MScanSubtractRadius()),
68 scanSubtractAngle_(
Parameters::defaultOdomF2MScanSubtractAngle()),
69 scanMapMaxRange_(
Parameters::defaultOdomF2MScanRange()),
70 bundleAdjustment_(
Parameters::defaultOdomF2MBundleAdjustment()),
71 bundleMaxFrames_(
Parameters::defaultOdomF2MBundleAdjustmentMaxFrames()),
72 bundleMinMotion_(
Parameters::defaultOdomF2MBundleAdjustmentMinMotion()),
73 bundleMaxKeyFramesPerFeature_(
Parameters::defaultOdomF2MBundleAdjustmentMaxKeyFramesPerFeature()),
74 bundleUpdateFeatureMapOnAllFrames_(
Parameters::defaultOdomF2MBundleUpdateFeatureMapOnAllFrames()),
75 validDepthRatio_(
Parameters::defaultOdomF2MValidDepthRatio()),
76 pointToPlaneK_(
Parameters::defaultIcpPointToPlaneK()),
77 pointToPlaneRadius_(
Parameters::defaultIcpPointToPlaneRadius()),
80 lastFrameOldestNewId_(0),
123 UWARN(
"Selected bundle adjustment approach (\"%s\"=\"%d\") is not available, "
124 "local bundle adjustment is then disabled.", Parameters::kOdomF2MBundleAdjustment().
c_str(),
bundleAdjustment_);
135 int corType = Parameters::defaultVisCorType();
139 UWARN(
"%s=%d is not supported by OdometryF2M, using Features matching approach instead (type=0).",
140 Parameters::kVisCorType().
c_str(),
146 int estType = Parameters::defaultVisEstimationType();
150 UWARN(
"%s=%d is not supported by OdometryF2M, using 2D->3D approach instead (type=1).",
151 Parameters::kVisEstimationType().
c_str(),
162 UWARN(
"%s=%d cannot be used with registration not done only with images (%s=%s), disabling bundle adjustment.",
163 Parameters::kOdomF2MBundleAdjustment().
c_str(),
165 Parameters::kRegStrategy().
c_str(),
166 uValue(bundleParameters, Parameters::kRegStrategy(),
uNumber2Str(Parameters::defaultRegStrategy())).
c_str());
221 if(
data.imu().empty())
224 data.setIMU(
IMU(cv::Vec4d(
q.x(),
q.y(),
q.z(),
q.w()), cv::Mat(), cv::Vec3d(), cv::Mat(), cv::Vec3d(), cv::Mat()));
237 bool addKeyFrame =
false;
238 int totalBundleWordReferencesUsed = 0;
239 int totalBundleOutliers = 0;
240 float bundleTime = 0.0f;
241 bool visDepthAsMask = Parameters::defaultVisDepthAsMask();
244 std::vector<CameraModel> lastFrameModels;
261 model.localTransform(),
264 lastFrameModels.push_back(
model);
267 UDEBUG(
"lastFrameModels=%ld", lastFrameModels.size());
280 std::map<int, cv::Point3f> points3DMap;
281 std::map<int, Transform> bundlePoses;
282 std::multimap<int, Link> bundleLinks;
283 std::map<int, std::vector<CameraModel> > bundleModels;
284 float bundleAvgInlierDistance = 0.0f;
286 for(
int guessIteration=0;
297 bundleModels.clear();
299 float maxCorrespondenceDistance = 0.0f;
300 float outlierRatio = 0.0f;
307 maxCorrespondenceDistance = Parameters::defaultIcpMaxCorrespondenceDistance();
308 outlierRatio = Parameters::defaultIcpOutlierRatio();
317 if(guessIteration == 1)
319 UWARN(
"Failed to find a transformation with the provided guess (%s), trying again without a guess.", guess.
prettyPrint().c_str());
329 if(maxCorrespondenceDistance>0.0
f)
347 !lastFrameModels.empty() &&
350 UDEBUG(
"Local Bundle Adjustment");
358 UERROR(
"Bundle Adjustment cannot be used with a registration approach recomputing "
359 "features from the \"from\" signature (e.g., Optical Flow) that would change "
360 "their ids (size=old=%ld new=%ld first/last: old=%d->%d new=%d->%d).",
378 uFormat(
"Frame %d already added! Make sure the input frames have unique IDs!",
lastFrame_->
id()).c_str());
387 bundleModels.insert(std::make_pair(
lastFrame_->
id(), lastFrameModels));
390 std::map<int, std::map<int, FeatureBA> > wordReferences;
391 size_t maxKeyFramesForInlier = 0;
397 std::multimap<int, int>::const_iterator iter3D = tmpMap.
getWords().find(wordId);
399 points3DMap.insert(std::make_pair(wordId, tmpMap.
getWords3()[iter3D->second]));
404 if(
info && refIter->second.size() > maxKeyFramesForInlier)
406 maxKeyFramesForInlier = refIter->second.size();
409 std::map<int, FeatureBA> references;
416 for(std::map<int, FeatureBA>::iterator jter=refIter->second.begin(); jter!=refIter->second.end(); ++jter)
418 if(oi++ %
step == 0 && bundlePoses.find(jter->first)!=bundlePoses.end())
420 references.insert(*jter);
421 ++totalBundleWordReferencesUsed;
425 if(refIter->second.size() > 1)
427 if(references.insert(*refIter->second.rbegin()).second)
429 ++totalBundleWordReferencesUsed;
440 if(lastFrameModels.size()>1)
442 UASSERT(lastFrameModels[0].imageWidth()>0);
443 float subImageWidth = lastFrameModels[0].imageWidth();
444 cameraIndex =
int(kpt.pt.x / subImageWidth);
445 UASSERT(cameraIndex < (
int)lastFrameModels.size());
446 kpt.pt.x = kpt.pt.x - (subImageWidth*
float(cameraIndex));
459 wordReferences.insert(std::make_pair(wordId, references));
470 std::set<int> sbaOutliers;
472 bundlePoses =
sba_->
optimizeBA(-
lastFrame_->
id(), bundlePoses, bundleLinks, bundleModels, points3DMap, wordReferences, &sbaOutliers);
473 bundleTime = bundleTimer.
ticks();
475 totalBundleOutliers = (
int)sbaOutliers.size();
477 UDEBUG(
"bundleTime=%fs (poses=%d wordRef=%d outliers=%d)", bundleTime, (
int)bundlePoses.size(), (
int)
bundleWordReferences_.size(), (
int)sbaOutliers.size());
480 info->localBundlePoses = bundlePoses;
481 info->localBundleModels = bundleModels;
482 info->localBundleMaxKeyFramesForInlier = maxKeyFramesForInlier;
485 UDEBUG(
"Local Bundle Adjustment Before: %s",
transform.prettyPrint().c_str());
488 if(!bundlePoses.rbegin()->second.isNull())
492 info->localBundleOutliersPerCam = std::vector<int>(lastFrameModels.size(),0);
494 if(sbaOutliers.size())
496 regInfo.
inliersPerCam = std::vector<int>(lastFrameModels.size(),0);
497 std::vector<int> newInliers(regInfo.
inliersIDs.size());
501 if(sbaOutliers.find(regInfo.
inliersIDs[
i]) == sbaOutliers.end())
511 newInliers.resize(oi);
512 UDEBUG(
"BA outliers ratio %f",
float(sbaOutliers.size())/
float(regInfo.
inliersIDs.size()));
523 transform = bundlePoses.rbegin()->second;
531 float rollImu,pitchImu,
yaw;
532 iter->second.transform().getEulerAngles(rollImu, pitchImu,
yaw);
563 std::map<int, std::map<int, FeatureBA> >
::iterator wter = wordReferences.find(regInfo.
inliersIDs[
i]);
564 if(wter != wordReferences.end())
566 std::map<int, FeatureBA>::iterator fter = wter->second.find(
bundlePoses_.rbegin()->first);
567 if(fter != wter->second.end())
571 float dx =
f1.kpt.pt.x -
f2.kpt.pt.x;
572 float dy =
f1.kpt.pt.y -
f2.kpt.pt.y;
573 bundleAvgInlierDistance +=
sqrt(dx*dx + dy*dy);
580 bundleAvgInlierDistance /=
count;
582 UDEBUG(
"Average pixel distance between %d inliers: %f",
count, bundleAvgInlierDistance);
585 info->localBundleAvgInlierDistance = bundleAvgInlierDistance;
589 UDEBUG(
"Local Bundle Adjustment After : %s",
transform.prettyPrint().c_str());
593 regInfo.
rejectedMsg =
"Last bundle pose is null?!";
599 regInfo.
rejectedMsg =
"Local bundle adjustment failed!";
614 if(guessIteration == 1)
616 UWARN(
"Trial with no guess still fail.");
631 UWARN(
"Unknown registration error");
634 else if(guessIteration == 1)
636 UWARN(
"Trial with no guess succeeded!");
644 bool modified =
false;
649 std::multimap<int, int> mapWords = tmpMap.
getWords();
650 std::vector<cv::KeyPoint> mapWordsKpts = tmpMap.
getWordsKpts();
651 std::vector<cv::Point3f> mapPoints = tmpMap.
getWords3();
656 bool lastFrameWords3Updated =
false;
657 std::vector<cv::Point3f> lastFrameWords3;
663 !points3DMap.empty())
671 cv::Point3f & pt = lastFrameWords3.at(
iter->second);
674 std::map<int, cv::Point3f>::iterator mapIter = points3DMap.find(
iter->first);
675 if(mapIter != points3DMap.end())
679 lastFrameWords3Updated =
true;
688 !points3DMap.empty())
691 for(std::map<int, cv::Point3f>::iterator
iter=points3DMap.begin();
iter!=points3DMap.end(); ++
iter)
694 mapPoints[mapWords.find(
iter->first)->second] =
iter->second;
709 addKeyFrame = addVisualKeyFrame || addGeometricKeyFrame;
711 UDEBUG(
"keyframeThr=%f visKeyFrameThr_=%d matches=%d inliers=%d (avg dist=%f, min=%f) features=%d mp=%d",
716 bundleAvgInlierDistance,
719 (
int)mapPoints.size());
728 UDEBUG(
"Update local map");
732 UASSERT(mapWords.size() == mapPoints.size());
733 UASSERT(mapWords.size() == mapWordsKpts.size());
734 UASSERT((
int)mapPoints.size() == mapDescriptors.rows);
745 if(
iter != bundleLinks.end())
757 for(std::map<int, cv::Point3f>::iterator
iter=points3DMap.begin();
iter!=points3DMap.end(); ++
iter)
760 mapPoints[mapWords.find(
iter->first)->second] =
iter->second;
766 std::multimap<float, std::pair<int, std::pair<cv::KeyPoint, std::pair<cv::Point3f, std::pair<cv::Mat, int> > > > > newIds;
769 std::set<int> seenStatusUpdated;
772 bool addPointsWithoutDepth =
false;
773 if(!visDepthAsMask && validDepthRatio_ < 1.0f && !lastFrame_->getWords3().
empty())
775 int ptsWithDepth = 0;
787 if(!addPointsWithoutDepth)
789 UWARN(
"Not enough points with valid depth in current frame (%d/%d=%f < %s=%f), points without depth are not added to map.",
794 if(!lastFrameModels.empty())
802 if(lastFrameModels.size()>1)
804 UASSERT(lastFrameModels[0].imageWidth()>0);
805 float subImageWidth = lastFrameModels[0].imageWidth();
806 cameraIndex =
int(kpt.pt.x / subImageWidth);
807 UASSERT(cameraIndex < (
int)lastFrameModels.size());
808 kpt.pt.x = kpt.pt.x - (subImageWidth*
float(cameraIndex));
811 if(mapWords.find(
iter->first) == mapWords.end())
816 std::make_pair(kpt.response>0?1.0f/kpt.response:0.0f,
817 std::make_pair(
iter->first,
827 std::multimap<int, int>::iterator iterKpts = mapWords.find(
iter->first);
828 if(iterKpts!=mapWords.end() && !mapWordsKpts.empty())
830 mapWordsKpts[iterKpts->second].octave = kpt.octave;
834 iterBundlePosesRef->second += 1;
844 std::map<int, FeatureBA> framePt;
854 int frameId = keyframes.rbegin()->first;
864 UDEBUG(
"newIds=%d", (
int)newIds.size());
869 for(std::multimap<
float, std::pair<
int, std::pair<cv::KeyPoint, std::pair<cv::Point3f, std::pair<cv::Mat, int> > > > >::reverse_iterator
iter=newIds.rbegin();
875 int cameraIndex =
iter->second.second.second.second.second;
876 cv::Point3f pt =
iter->second.second.second.first;
880 float x =
iter->second.second.first.pt.x;
881 float y =
iter->second.second.first.pt.y;
883 lastFrameModels[cameraIndex].imageSize(),
886 lastFrameModels[cameraIndex].
cx(),
887 lastFrameModels[cameraIndex].
cy(),
888 lastFrameModels[cameraIndex].
fx(),
889 lastFrameModels[cameraIndex].
fy());
891 pt =
util3d::transformPoint(cv::Point3f(ray[0]*scaleInf, ray[1]*scaleInf, ray[2]*scaleInf), lastFrameModels[cameraIndex].localTransform());
903 iterBundlePosesRef->second += 1;
913 std::map<int, FeatureBA> framePt;
924 mapWords.insert(mapWords.end(), std::make_pair(
iter->second.first, mapWords.size()));
925 mapWordsKpts.push_back(
iter->second.second.first);
927 mapDescriptors.push_back(
iter->second.second.second.second.first);
959 UDEBUG(
"projected added=%d/%d minLastFrameId=%d", oi, (
int)regInfo.
projectedIDs.size(), lastFrameOldestNewId);
961 for(
unsigned int i=0;
i<ids.size() && (
int)mapWords.size() >
maximumMapSize_ && mapWords.size() >= newIds.size(); ++
i)
964 if(inliers.find(
id) == inliers.end())
969 for(std::map<int, FeatureBA>::iterator iterFrame = iterRef->second.begin(); iterFrame != iterRef->second.end(); ++iterFrame)
985 for(std::multimap<int, int>::iterator
iter = mapWords.begin();
986 iter!=mapWords.end() && (
int)mapWords.size() >
maximumMapSize_ && mapWords.size() >= newIds.size();)
988 if(inliers.find(
iter->first) == inliers.end())
993 for(std::map<int, FeatureBA>::iterator iterFrame = iterRef->second.begin(); iterFrame != iterRef->second.end(); ++iterFrame)
1003 mapWords.erase(
iter++);
1012 if(mapWords.size() != mapPoints.size())
1015 std::vector<cv::KeyPoint> mapWordsKptsClean(mapWords.size());
1016 std::vector<cv::Point3f> mapPointsClean(mapWords.size());
1017 cv::Mat mapDescriptorsClean(mapWords.size(), mapDescriptors.cols, mapDescriptors.type());
1019 for(std::multimap<int, int>::iterator
iter = mapWords.begin();
iter!=mapWords.end(); ++
iter, ++index)
1021 mapWordsKptsClean[index] = mapWordsKpts[
iter->second];
1022 mapPointsClean[index] = mapPoints[
iter->second];
1023 mapDescriptors.row(
iter->second).copyTo(mapDescriptorsClean.row(index));
1024 iter->second = index;
1026 mapWordsKpts = mapWordsKptsClean;
1027 mapWordsKptsClean.clear();
1028 mapPoints = mapPointsClean;
1029 mapPointsClean.clear();
1030 mapDescriptors = mapDescriptorsClean;
1033 Link * previousLink = 0;
1036 if(
iter->second <= 0)
1064 if(added || removed)
1068 UDEBUG(
"Update local features map = %fs", tmpTimer.
ticks());
1078 pcl::PointCloud<pcl::PointXYZINormal>::Ptr frameCloudNormals (
new pcl::PointCloud<pcl::PointXYZINormal>());
1093 pcl::IndicesPtr frameCloudNormalsIndices(
new std::vector<int>);
1100 pcl::IndicesPtr(
new std::vector<int>),
1102 pcl::IndicesPtr(
new std::vector<int>),
1105 newPoints = frameCloudNormalsIndices->size();
1109 newPoints = frameCloudNormals->size();
1117 pcl::PointCloud<pcl::PointXYZINormal> tmp;
1118 pcl::copyPointCloud(*frameCloudNormals, *frameCloudNormalsIndices, tmp);
1123 UINFO(
"mapSize=%d newPoints=%d maxPoints=%d",
1124 int(mapCloudNormals->size()),
1128 *mapCloudNormals += tmp;
1138 *mapCloudNormals += tmp;
1142 pcl::PointCloud<pcl::PointXYZI>::Ptr mapCloud (
new pcl::PointCloud<pcl::PointXYZI> ());
1143 copyPointCloud(*mapCloudNormals, *mapCloud);
1145 copyPointCloud(*normals, *mapCloudNormals);
1148 scansBuffer_.push_back(std::make_pair(frameCloudNormals, frameCloudNormalsIndices));
1151 UDEBUG(
"scansBuffer=%d, mapSize=%d newPoints=%d maxPoints=%d",
1153 int(mapCloudNormals->size()),
1161 mapCloudNormals->clear();
1162 std::list<int> toRemove;
1177 pcl::PointCloud<pcl::PointXYZINormal> tmp;
1179 *mapCloudNormals += tmp;
1190 std::vector<std::pair<pcl::PointCloud<pcl::PointXYZINormal>::Ptr, pcl::IndicesPtr> > scansTmp(
scansBuffer_.size()-
i);
1194 UASSERT(oi < (
int)scansTmp.size());
1205 pcl::PointCloud<pcl::PointXYZINormal> tmp;
1207 *mapCloudNormals += tmp;
1218 Transform mapViewpoint(-newFramePose.
x(), -newFramePose.
y(),0,0,0,0);
1223 Transform mapViewpoint(-newFramePose.
x(), -newFramePose.
y(), -newFramePose.
z(),0,0,0);
1229 UDEBUG(
"Update local scan map = %fs", tmpTimer.
ticks());
1258 map_->
setWords(mapWords, mapWordsKpts, mapPoints, mapDescriptors);
1261 if(lastFrameWords3Updated)
1303 regInfo.
covariance = cv::Mat::eye(6,6,CV_64FC1)*9999.0;
1305 bool frameValid =
false;
1310 int ptsWithDepth = 0;
1329 std::multimap<int, int> words;
1330 std::vector<cv::KeyPoint> wordsKpts;
1331 std::vector<cv::Point3f> transformedPoints;
1332 std::multimap<int, int> mapPointWeights;
1333 cv::Mat descriptors;
1343 words.insert(words.end(), std::make_pair(
iter->first, words.size()));
1346 mapPointWeights.insert(std::make_pair(
iter->first, 0));
1355 if(!wordsKpts.empty())
1357 for(std::multimap<int, int>::const_iterator
iter=words.begin();
iter!=words.end(); ++
iter)
1359 if(words.count(
iter->first) == 1)
1362 std::map<int, FeatureBA> framePt;
1364 cv::KeyPoint kpt = wordsKpts[
iter->second];
1366 int cameraIndex = 0;
1367 if(lastFrameModels.size()>1)
1369 UASSERT(lastFrameModels[0].imageWidth()>0);
1370 float subImageWidth = lastFrameModels[0].imageWidth();
1371 cameraIndex =
int(kpt.pt.x / subImageWidth);
1372 kpt.pt.x = kpt.pt.x - (subImageWidth*
float(cameraIndex));
1402 map_->
setWords(words, wordsKpts, transformedPoints, descriptors);
1416 double complexity = 0.0;;
1419 float minComplexity = Parameters::defaultIcpPointToPlaneMinComplexity();
1420 bool p2n = Parameters::defaultIcpPointToPlane();
1423 if(p2n && minComplexity>0.0
f)
1428 if(complexity > minComplexity)
1434 UWARN(
"Scan complexity too low (%f) to init robustly the first "
1435 "keyframe. Make sure the lidar is seeing enough "
1436 "geometry in all axes for good initialization. "
1437 "Accepting as an initial guess (%s) is provided.",
1445 UWARN(
"Input raw scan doesn't have normals, complexity check on first frame is not done.");
1458 UINFO(
"Local map will be updated using range instead of time with range threshold set at %f",
scanMapMaxRange_);
1460 scansBuffer_.push_back(std::make_pair(mapCloudNormals, pcl::IndicesPtr(
new std::vector<int>)));
1464 Transform mapViewpoint(-newFramePose.
x(), -newFramePose.
y(),0,0,0,0);
1474 Transform mapViewpoint(-newFramePose.
x(), -newFramePose.
y(), -newFramePose.
z(),0,0,0);
1487 UWARN(
"Scan complexity too low (%f) to init first keyframe.", complexity);
1492 UWARN(
"Missing scan to initialize odometry.");
1529 info->words.clear();
1542 UERROR(
"SensorData not valid!");
1547 info->features = nFeatures;
1549 info->keyFrameAdded = addKeyFrame;
1550 info->localBundleOutliers = totalBundleOutliers;
1551 info->localBundleConstraints = totalBundleWordReferencesUsed;
1552 info->localBundleTime = bundleTime;
1556 info->
reg = regInfo;
1564 UINFO(
"Odom update time = %fs lost=%s features=%d inliers=%d/%d variance:lin=%f, ang=%f local_map=%d local_scan_map=%d",
1566 output.
isNull()?
"true":
"false",