mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 17:40:23 +08:00
New parameter: OdomF2M/ValidDepthRatio
This commit is contained in:
@@ -429,6 +429,7 @@ class RTABMAP_EXP Parameters
|
|||||||
RTABMAP_PARAM(OdomF2M, ScanMaxSize, int, 2000, "[Geometry] Maximum local scan map size.");
|
RTABMAP_PARAM(OdomF2M, ScanMaxSize, int, 2000, "[Geometry] Maximum local scan map size.");
|
||||||
RTABMAP_PARAM(OdomF2M, ScanSubtractRadius, float, 0.05, "[Geometry] Radius used to filter points of a new added scan to local map. This could match the voxel size of the scans.");
|
RTABMAP_PARAM(OdomF2M, ScanSubtractRadius, float, 0.05, "[Geometry] Radius used to filter points of a new added scan to local map. This could match the voxel size of the scans.");
|
||||||
RTABMAP_PARAM(OdomF2M, ScanSubtractAngle, float, 45, uFormat("[Geometry] Max angle (degrees) used to filter points of a new added scan to local map (when \"%s\">0). 0 means any angle.", kOdomF2MScanSubtractRadius().c_str()).c_str());
|
RTABMAP_PARAM(OdomF2M, ScanSubtractAngle, float, 45, uFormat("[Geometry] Max angle (degrees) used to filter points of a new added scan to local map (when \"%s\">0). 0 means any angle.", kOdomF2MScanSubtractRadius().c_str()).c_str());
|
||||||
|
RTABMAP_PARAM(OdomF2M, ValidDepthRatio, float, 0.75, "If a new frame has points without valid depth, they are added to local feature map only if points with valid depth on total points is over this ratio. Setting to 1 means no points without valid depth are added to local feature map.");
|
||||||
#if defined(RTABMAP_G2O) || defined(RTABMAP_ORB_SLAM2)
|
#if defined(RTABMAP_G2O) || defined(RTABMAP_ORB_SLAM2)
|
||||||
RTABMAP_PARAM(OdomF2M, BundleAdjustment, int, 1, "Local bundle adjustment: 0=disabled, 1=g2o, 2=cvsba.");
|
RTABMAP_PARAM(OdomF2M, BundleAdjustment, int, 1, "Local bundle adjustment: 0=disabled, 1=g2o, 2=cvsba.");
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ private:
|
|||||||
float scanSubtractAngle_;
|
float scanSubtractAngle_;
|
||||||
int bundleAdjustment_;
|
int bundleAdjustment_;
|
||||||
int bundleMaxFrames_;
|
int bundleMaxFrames_;
|
||||||
|
float validDepthRatio_;
|
||||||
|
|
||||||
Registration * regPipeline_;
|
Registration * regPipeline_;
|
||||||
Signature * map_;
|
Signature * map_;
|
||||||
|
|||||||
@@ -790,6 +790,7 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
// For each projected feature guess of "from" in "to", find its matching feature in
|
// For each projected feature guess of "from" in "to", find its matching feature in
|
||||||
// the radius around the projected guess.
|
// the radius around the projected guess.
|
||||||
// TODO: do cross-check?
|
// TODO: do cross-check?
|
||||||
|
UDEBUG("guessMatchToProjection=%d, cornersProjected=%d", _guessMatchToProjection?1:0, (int)cornersProjected.size());
|
||||||
if(cornersProjected.size())
|
if(cornersProjected.size())
|
||||||
{
|
{
|
||||||
if(_guessMatchToProjection)
|
if(_guessMatchToProjection)
|
||||||
@@ -823,100 +824,97 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
cv::Mat descriptors(10, descriptorsTo.cols, descriptorsTo.type());
|
cv::Mat descriptors(10, descriptorsTo.cols, descriptorsTo.type());
|
||||||
for(unsigned int i = 0; i < pointsToMat.rows; ++i)
|
for(unsigned int i = 0; i < pointsToMat.rows; ++i)
|
||||||
{
|
{
|
||||||
if(kptsTo3D.empty() || util3d::isFinite(kptsTo3D[i]))
|
// Make octave compatible with SIFT packed octave (https://github.com/opencv/opencv/issues/4554)
|
||||||
|
int octave = kptsTo[i].octave & 255;
|
||||||
|
octave = octave < 128 ? octave : (-128 | octave);
|
||||||
|
int matchedIndex = -1;
|
||||||
|
if(indices[i].size() >= 2)
|
||||||
{
|
{
|
||||||
// Make octave compatible with SIFT packed octave (https://github.com/opencv/opencv/issues/4554)
|
std::vector<int> descriptorsIndices(indices[i].size());
|
||||||
int octave = kptsTo[i].octave & 255;
|
int oi=0;
|
||||||
octave = octave < 128 ? octave : (-128 | octave);
|
if((int)indices[i].size() > descriptors.rows)
|
||||||
int matchedIndex = -1;
|
|
||||||
if(indices[i].size() >= 2)
|
|
||||||
{
|
{
|
||||||
std::vector<int> descriptorsIndices(indices[i].size());
|
descriptors.resize(indices[i].size());
|
||||||
int oi=0;
|
|
||||||
if((int)indices[i].size() > descriptors.rows)
|
|
||||||
{
|
|
||||||
descriptors.resize(indices[i].size());
|
|
||||||
}
|
|
||||||
for(unsigned int j=0; j<indices[i].size(); ++j)
|
|
||||||
{
|
|
||||||
int octaveFrom = kptsFrom.at(projectedIndexToDescIndex[indices[i].at(j)]).octave & 255;
|
|
||||||
octaveFrom = octaveFrom < 128 ? octaveFrom : (-128 | octaveFrom);
|
|
||||||
if(octaveFrom==octave)
|
|
||||||
{
|
|
||||||
descriptorsFrom.row(projectedIndexToDescIndex[indices[i].at(j)]).copyTo(descriptors.row(oi));
|
|
||||||
descriptorsIndices[oi++] = indices[i].at(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
descriptorsIndices.resize(oi);
|
|
||||||
if(oi >=2)
|
|
||||||
{
|
|
||||||
std::vector<std::vector<cv::DMatch> > matches;
|
|
||||||
cv::BFMatcher matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR);
|
|
||||||
matcher.knnMatch(descriptorsTo.row(i), cv::Mat(descriptors, cv::Range(0, oi)), matches, 2);
|
|
||||||
UASSERT(matches.size() == 1);
|
|
||||||
UASSERT(matches[0].size() == 2);
|
|
||||||
if(matches[0].at(0).distance < _nndr * matches[0].at(1).distance)
|
|
||||||
{
|
|
||||||
matchedIndex = descriptorsIndices.at(matches[0].at(0).trainIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(oi == 1)
|
|
||||||
{
|
|
||||||
matchedIndex = descriptorsIndices[0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(indices[i].size() == 1)
|
for(unsigned int j=0; j<indices[i].size(); ++j)
|
||||||
{
|
{
|
||||||
int octaveFrom = kptsFrom.at(projectedIndexToDescIndex[indices[i].at(0)]).octave & 255;
|
int octaveFrom = kptsFrom.at(projectedIndexToDescIndex[indices[i].at(j)]).octave & 255;
|
||||||
octaveFrom = octaveFrom < 128 ? octaveFrom : (-128 | octaveFrom);
|
octaveFrom = octaveFrom < 128 ? octaveFrom : (-128 | octaveFrom);
|
||||||
if(octaveFrom == octave)
|
if(octaveFrom==octave)
|
||||||
{
|
{
|
||||||
matchedIndex = indices[i].at(0);
|
descriptorsFrom.row(projectedIndexToDescIndex[indices[i].at(j)]).copyTo(descriptors.row(oi));
|
||||||
|
descriptorsIndices[oi++] = indices[i].at(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
descriptorsIndices.resize(oi);
|
||||||
if(matchedIndex >= 0)
|
if(oi >=2)
|
||||||
{
|
{
|
||||||
matchedIndex = projectedIndexToDescIndex[matchedIndex];
|
std::vector<std::vector<cv::DMatch> > matches;
|
||||||
int id = orignalWordsFromIds.size()?orignalWordsFromIds[matchedIndex]:matchedIndex;
|
cv::BFMatcher matcher(descriptors.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR);
|
||||||
|
matcher.knnMatch(descriptorsTo.row(i), cv::Mat(descriptors, cv::Range(0, oi)), matches, 2);
|
||||||
if(addedWordsFrom.find(matchedIndex) != addedWordsFrom.end())
|
UASSERT(matches.size() == 1);
|
||||||
|
UASSERT(matches[0].size() == 2);
|
||||||
|
if(matches[0].at(0).distance < _nndr * matches[0].at(1).distance)
|
||||||
{
|
{
|
||||||
id = addedWordsFrom.at(matchedIndex);
|
matchedIndex = descriptorsIndices.at(matches[0].at(0).trainIdx);
|
||||||
duplicates.insert(std::make_pair(matchedIndex, id));
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
else if(oi == 1)
|
||||||
addedWordsFrom.insert(std::make_pair(matchedIndex, id));
|
{
|
||||||
|
matchedIndex = descriptorsIndices[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(indices[i].size() == 1)
|
||||||
|
{
|
||||||
|
int octaveFrom = kptsFrom.at(projectedIndexToDescIndex[indices[i].at(0)]).octave & 255;
|
||||||
|
octaveFrom = octaveFrom < 128 ? octaveFrom : (-128 | octaveFrom);
|
||||||
|
if(octaveFrom == octave)
|
||||||
|
{
|
||||||
|
matchedIndex = indices[i].at(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(kptsFrom.size())
|
if(matchedIndex >= 0)
|
||||||
{
|
{
|
||||||
wordsFrom.insert(std::make_pair(id, kptsFrom[matchedIndex]));
|
matchedIndex = projectedIndexToDescIndex[matchedIndex];
|
||||||
}
|
int id = orignalWordsFromIds.size()?orignalWordsFromIds[matchedIndex]:matchedIndex;
|
||||||
words3From.insert(std::make_pair(id, kptsFrom3D[matchedIndex]));
|
|
||||||
wordsDescFrom.insert(std::make_pair(id, descriptorsFrom.row(matchedIndex)));
|
|
||||||
}
|
|
||||||
|
|
||||||
wordsTo.insert(std::make_pair(id, kptsTo[i]));
|
if(addedWordsFrom.find(matchedIndex) != addedWordsFrom.end())
|
||||||
wordsDescTo.insert(std::make_pair(id, descriptorsTo.row(i)));
|
{
|
||||||
if(kptsTo3D.size())
|
id = addedWordsFrom.at(matchedIndex);
|
||||||
{
|
duplicates.insert(std::make_pair(matchedIndex, id));
|
||||||
words3To.insert(std::make_pair(id, kptsTo3D[i]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// gen fake ids
|
addedWordsFrom.insert(std::make_pair(matchedIndex, id));
|
||||||
wordsTo.insert(wordsTo.end(), std::make_pair(newToId, kptsTo[i]));
|
|
||||||
wordsDescTo.insert(wordsDescTo.end(), std::make_pair(newToId, descriptorsTo.row(i)));
|
|
||||||
if(kptsTo3D.size())
|
|
||||||
{
|
|
||||||
words3To.insert(words3To.end(), std::make_pair(newToId, kptsTo3D[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
++newToId;
|
if(kptsFrom.size())
|
||||||
++newWords;
|
{
|
||||||
|
wordsFrom.insert(std::make_pair(id, kptsFrom[matchedIndex]));
|
||||||
|
}
|
||||||
|
words3From.insert(std::make_pair(id, kptsFrom3D[matchedIndex]));
|
||||||
|
wordsDescFrom.insert(std::make_pair(id, descriptorsFrom.row(matchedIndex)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wordsTo.insert(std::make_pair(id, kptsTo[i]));
|
||||||
|
wordsDescTo.insert(std::make_pair(id, descriptorsTo.row(i)));
|
||||||
|
if(kptsTo3D.size())
|
||||||
|
{
|
||||||
|
words3To.insert(std::make_pair(id, kptsTo3D[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// gen fake ids
|
||||||
|
wordsTo.insert(wordsTo.end(), std::make_pair(newToId, kptsTo[i]));
|
||||||
|
wordsDescTo.insert(wordsDescTo.end(), std::make_pair(newToId, descriptorsTo.row(i)));
|
||||||
|
if(kptsTo3D.size())
|
||||||
|
{
|
||||||
|
words3To.insert(words3To.end(), std::make_pair(newToId, kptsTo3D[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
++newToId;
|
||||||
|
++newWords;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UDEBUG("addedWordsFrom=%d/%d (duplicates=%d, newWords=%d), kptsTo=%d, wordsTo=%d, words3From=%d",
|
UDEBUG("addedWordsFrom=%d/%d (duplicates=%d, newWords=%d), kptsTo=%d, wordsTo=%d, words3From=%d",
|
||||||
@@ -1048,8 +1046,7 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
words3From.insert(words3From.end(), std::make_pair(id, kptsFrom3D[matchedIndexFrom]));
|
words3From.insert(words3From.end(), std::make_pair(id, kptsFrom3D[matchedIndexFrom]));
|
||||||
wordsDescFrom.insert(wordsDescFrom.end(), std::make_pair(id, descriptorsFrom.row(matchedIndexFrom)));
|
wordsDescFrom.insert(wordsDescFrom.end(), std::make_pair(id, descriptorsFrom.row(matchedIndexFrom)));
|
||||||
|
|
||||||
if((kptsTo3D.empty() || util3d::isFinite(kptsTo3D[matchedIndexTo])) &&
|
if( matchedIndexTo >= 0 &&
|
||||||
matchedIndexTo >= 0 &&
|
|
||||||
addedWordsTo.find(matchedIndexTo) == addedWordsTo.end())
|
addedWordsTo.find(matchedIndexTo) == addedWordsTo.end())
|
||||||
{
|
{
|
||||||
addedWordsTo.insert(matchedIndexTo);
|
addedWordsTo.insert(matchedIndexTo);
|
||||||
@@ -1353,6 +1350,7 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
&inliersV);
|
&inliersV);
|
||||||
inliers[dir] = inliersV;
|
inliers[dir] = inliersV;
|
||||||
matches[dir] = matchesV;
|
matches[dir] = matchesV;
|
||||||
|
UDEBUG("inliers: %d/%d", (int)inliersV.size(), (int)matchesV.size());
|
||||||
if(transforms[dir].isNull())
|
if(transforms[dir].isNull())
|
||||||
{
|
{
|
||||||
msg = uFormat("Not enough inliers %d/%d (matches=%d) between %d and %d",
|
msg = uFormat("Not enough inliers %d/%d (matches=%d) between %d and %d",
|
||||||
@@ -1394,6 +1392,7 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
&inliersV);
|
&inliersV);
|
||||||
inliers[dir] = inliersV;
|
inliers[dir] = inliersV;
|
||||||
matches[dir] = matchesV;
|
matches[dir] = matchesV;
|
||||||
|
UDEBUG("inliers: %d/%d", (int)inliersV.size(), (int)matchesV.size());
|
||||||
if(transforms[dir].isNull())
|
if(transforms[dir].isNull())
|
||||||
{
|
{
|
||||||
msg = uFormat("Not enough inliers %d/%d (matches=%d) between %d and %d",
|
msg = uFormat("Not enough inliers %d/%d (matches=%d) between %d and %d",
|
||||||
@@ -1460,6 +1459,7 @@ Transform RegistrationVis::computeTransformationImpl(
|
|||||||
fromSignature.sensorData().cameraModels().size() <= 1 &&
|
fromSignature.sensorData().cameraModels().size() <= 1 &&
|
||||||
toSignature.sensorData().cameraModels().size() <= 1)
|
toSignature.sensorData().cameraModels().size() <= 1)
|
||||||
{
|
{
|
||||||
|
UDEBUG("Refine with bundle adjustment");
|
||||||
Optimizer * sba = Optimizer::create(_bundleAdjustment==2?Optimizer::kTypeCVSBA:Optimizer::kTypeG2O, _bundleParameters);
|
Optimizer * sba = Optimizer::create(_bundleAdjustment==2?Optimizer::kTypeCVSBA:Optimizer::kTypeG2O, _bundleParameters);
|
||||||
|
|
||||||
std::map<int, Transform> poses;
|
std::map<int, Transform> poses;
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ OdometryF2M::OdometryF2M(const ParametersMap & parameters) :
|
|||||||
scanSubtractAngle_(Parameters::defaultOdomF2MScanSubtractAngle()),
|
scanSubtractAngle_(Parameters::defaultOdomF2MScanSubtractAngle()),
|
||||||
bundleAdjustment_(Parameters::defaultOdomF2MBundleAdjustment()),
|
bundleAdjustment_(Parameters::defaultOdomF2MBundleAdjustment()),
|
||||||
bundleMaxFrames_(Parameters::defaultOdomF2MBundleAdjustmentMaxFrames()),
|
bundleMaxFrames_(Parameters::defaultOdomF2MBundleAdjustmentMaxFrames()),
|
||||||
|
validDepthRatio_(Parameters::defaultOdomF2MValidDepthRatio()),
|
||||||
map_(new Signature(-1)),
|
map_(new Signature(-1)),
|
||||||
lastFrame_(new Signature(1)),
|
lastFrame_(new Signature(1)),
|
||||||
lastFrameOldestNewId_(0),
|
lastFrameOldestNewId_(0),
|
||||||
@@ -88,6 +89,8 @@ OdometryF2M::OdometryF2M(const ParametersMap & parameters) :
|
|||||||
}
|
}
|
||||||
Parameters::parse(parameters, Parameters::kOdomF2MBundleAdjustment(), bundleAdjustment_);
|
Parameters::parse(parameters, Parameters::kOdomF2MBundleAdjustment(), bundleAdjustment_);
|
||||||
Parameters::parse(parameters, Parameters::kOdomF2MBundleAdjustmentMaxFrames(), bundleMaxFrames_);
|
Parameters::parse(parameters, Parameters::kOdomF2MBundleAdjustmentMaxFrames(), bundleMaxFrames_);
|
||||||
|
Parameters::parse(parameters, Parameters::kOdomF2MValidDepthRatio(), validDepthRatio_);
|
||||||
|
|
||||||
UASSERT(bundleMaxFrames_ >= 0);
|
UASSERT(bundleMaxFrames_ >= 0);
|
||||||
ParametersMap bundleParameters = parameters;
|
ParametersMap bundleParameters = parameters;
|
||||||
if(bundleAdjustment_ > 0)
|
if(bundleAdjustment_ > 0)
|
||||||
@@ -201,6 +204,8 @@ Transform OdometryF2M::computeTransform(
|
|||||||
int totalBundleWordReferencesUsed = 0;
|
int totalBundleWordReferencesUsed = 0;
|
||||||
int totalBundleOutliers = 0;
|
int totalBundleOutliers = 0;
|
||||||
float bundleTime = 0.0f;
|
float bundleTime = 0.0f;
|
||||||
|
bool visDepthAsMask = Parameters::defaultVisDepthAsMask();
|
||||||
|
Parameters::parse(parameters_, Parameters::kVisDepthAsMask(), visDepthAsMask);
|
||||||
|
|
||||||
// Generate keypoints from the new data
|
// Generate keypoints from the new data
|
||||||
if(lastFrame_->sensorData().isValid())
|
if(lastFrame_->sensorData().isValid())
|
||||||
@@ -567,11 +572,35 @@ Transform OdometryF2M::computeTransform(
|
|||||||
UFATAL("no valid camera model!");
|
UFATAL("no valid camera model!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add points without depth only if the local map has reached its maximum size
|
||||||
|
bool addPointsWithoutDepth = false;
|
||||||
|
if(!visDepthAsMask && validDepthRatio_ < 1.0f)
|
||||||
|
{
|
||||||
|
int ptsWithDepth = 0;
|
||||||
|
for (std::multimap<int, cv::Point3f>::const_iterator iter = lastFrame_->getWords3().begin();
|
||||||
|
iter != lastFrame_->getWords3().end();
|
||||||
|
++iter)
|
||||||
|
{
|
||||||
|
if(util3d::isFinite(iter->second))
|
||||||
|
{
|
||||||
|
++ptsWithDepth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float r = float(ptsWithDepth) / float(lastFrame_->getWords3().size());
|
||||||
|
addPointsWithoutDepth = r > validDepthRatio_;
|
||||||
|
if(!addPointsWithoutDepth)
|
||||||
|
{
|
||||||
|
UWARN("Not enough points with valid depth in current frame (%d/%d=%f < %s=%f), points without depth are not added to map.",
|
||||||
|
ptsWithDepth, (int)lastFrame_->getWords3().size(), r, Parameters::kOdomF2MValidDepthRatio().c_str(), validDepthRatio_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(std::multimap<int, cv::Point3f>::const_iterator iter = lastFrame_->getWords3().begin(); iter!=lastFrame_->getWords3().end(); ++iter, ++iter2D, ++iterDesc)
|
for(std::multimap<int, cv::Point3f>::const_iterator iter = lastFrame_->getWords3().begin(); iter!=lastFrame_->getWords3().end(); ++iter, ++iter2D, ++iterDesc)
|
||||||
{
|
{
|
||||||
if(util3d::isFinite(iter->second))
|
if(mapPoints.find(iter->first) == mapPoints.end()) // Point not in map
|
||||||
{
|
{
|
||||||
if(mapPoints.find(iter->first) == mapPoints.end()) // Point not in map
|
if(util3d::isFinite(iter->second) || addPointsWithoutDepth)
|
||||||
{
|
{
|
||||||
newIds.insert(
|
newIds.insert(
|
||||||
std::make_pair(iter2D->second.response>0?1.0f/iter2D->second.response:0.0f,
|
std::make_pair(iter2D->second.response>0?1.0f/iter2D->second.response:0.0f,
|
||||||
@@ -579,31 +608,35 @@ Transform OdometryF2M::computeTransform(
|
|||||||
std::make_pair(iter2D->second,
|
std::make_pair(iter2D->second,
|
||||||
std::make_pair(iter->second, iterDesc->second)))));
|
std::make_pair(iter->second, iterDesc->second)))));
|
||||||
}
|
}
|
||||||
else if(bundleAdjustment_>0)
|
}
|
||||||
|
else if(bundleAdjustment_>0)
|
||||||
|
{
|
||||||
|
if(lastFrame_->getWords().count(iter->first) == 1)
|
||||||
{
|
{
|
||||||
if(lastFrame_->getWords().count(iter->first) == 1)
|
std::multimap<int, cv::KeyPoint>::iterator iterKpts = mapWords.find(iter->first);
|
||||||
|
if(iterKpts!=mapWords.end())
|
||||||
{
|
{
|
||||||
std::multimap<int, cv::KeyPoint>::iterator iterKpts = mapWords.find(iter->first);
|
iterKpts->second.octave = iter2D->second.octave;
|
||||||
if(iterKpts!=mapWords.end())
|
}
|
||||||
{
|
|
||||||
iterKpts->second.octave = iter2D->second.octave;
|
|
||||||
}
|
|
||||||
|
|
||||||
UASSERT(iterBundlePosesRef!=bundlePoseReferences_.end());
|
UASSERT(iterBundlePosesRef!=bundlePoseReferences_.end());
|
||||||
iterBundlePosesRef->second += 1;
|
iterBundlePosesRef->second += 1;
|
||||||
|
|
||||||
//move back point in camera frame (to get depth along z)
|
//move back point in camera frame (to get depth along z)
|
||||||
cv::Point3f pt3d = util3d::transformPoint(iter->second, invLocalTransform);
|
float depth = 0.0f;
|
||||||
if(bundleWordReferences_.find(iter->first) == bundleWordReferences_.end())
|
if(util3d::isFinite(iter->second))
|
||||||
{
|
{
|
||||||
std::map<int, FeatureBA> framePt;
|
depth = util3d::transformPoint(iter->second, invLocalTransform).z;
|
||||||
framePt.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter2D->second, pt3d.z)));
|
}
|
||||||
bundleWordReferences_.insert(std::make_pair(iter->first, framePt));
|
if(bundleWordReferences_.find(iter->first) == bundleWordReferences_.end())
|
||||||
}
|
{
|
||||||
else
|
std::map<int, FeatureBA> framePt;
|
||||||
{
|
framePt.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter2D->second, depth)));
|
||||||
bundleWordReferences_.find(iter->first)->second.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter2D->second, pt3d.z)));
|
bundleWordReferences_.insert(std::make_pair(iter->first, framePt));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bundleWordReferences_.find(iter->first)->second.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter2D->second, depth)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -626,22 +659,61 @@ Transform OdometryF2M::computeTransform(
|
|||||||
iterBundlePosesRef->second += 1;
|
iterBundlePosesRef->second += 1;
|
||||||
|
|
||||||
//move back point in camera frame (to get depth along z)
|
//move back point in camera frame (to get depth along z)
|
||||||
cv::Point3f pt3d = util3d::transformPoint(iter->second.second.second.first, invLocalTransform);
|
float depth = 0.0f;
|
||||||
|
if(util3d::isFinite(iter->second.second.second.first))
|
||||||
|
{
|
||||||
|
depth = util3d::transformPoint(iter->second.second.second.first, invLocalTransform).z;
|
||||||
|
}
|
||||||
if(bundleWordReferences_.find(iter->second.first) == bundleWordReferences_.end())
|
if(bundleWordReferences_.find(iter->second.first) == bundleWordReferences_.end())
|
||||||
{
|
{
|
||||||
std::map<int, FeatureBA> framePt;
|
std::map<int, FeatureBA> framePt;
|
||||||
framePt.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter->second.second.first, pt3d.z)));
|
framePt.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter->second.second.first, depth)));
|
||||||
bundleWordReferences_.insert(std::make_pair(iter->second.first, framePt));
|
bundleWordReferences_.insert(std::make_pair(iter->second.first, framePt));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bundleWordReferences_.find(iter->second.first)->second.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter->second.second.first, pt3d.z)));
|
bundleWordReferences_.find(iter->second.first)->second.insert(std::make_pair(lastFrame_->id(), FeatureBA(iter->second.second.first, depth)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mapWords.insert(std::make_pair(iter->second.first, iter->second.second.first));
|
mapWords.insert(std::make_pair(iter->second.first, iter->second.second.first));
|
||||||
mapPoints.insert(std::make_pair(iter->second.first, util3d::transformPoint(iter->second.second.second.first, newFramePose)));
|
cv::Point3f pt = iter->second.second.second.first;
|
||||||
|
if(!util3d::isFinite(pt))
|
||||||
|
{
|
||||||
|
// get the ray instead
|
||||||
|
float x = iter->second.second.first.pt.x;
|
||||||
|
float y = iter->second.second.first.pt.y;
|
||||||
|
float subImageWidth = lastFrame_->sensorData().imageRaw().cols;
|
||||||
|
CameraModel model;
|
||||||
|
if(lastFrame_->sensorData().cameraModels().size() > 1)
|
||||||
|
{
|
||||||
|
subImageWidth = lastFrame_->sensorData().imageRaw().cols/lastFrame_->sensorData().cameraModels().size();
|
||||||
|
int cameraIndex = int(x / subImageWidth);
|
||||||
|
model = lastFrame_->sensorData().cameraModels()[cameraIndex];
|
||||||
|
x = x-subImageWidth*cameraIndex;
|
||||||
|
}
|
||||||
|
else if(lastFrame_->sensorData().cameraModels().size() == 1)
|
||||||
|
{
|
||||||
|
model = lastFrame_->sensorData().cameraModels()[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
model = lastFrame_->sensorData().stereoCameraModel().left();
|
||||||
|
}
|
||||||
|
|
||||||
|
Eigen::Vector3f ray = util3d::projectDepthTo3DRay(
|
||||||
|
model.imageSize(),
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
model.cx(),
|
||||||
|
model.cy(),
|
||||||
|
model.fx(),
|
||||||
|
model.fy());
|
||||||
|
float scaleInf = (0.05 * model.fx()) / 0.01;
|
||||||
|
pt = util3d::transformPoint(cv::Point3f(ray[0]*scaleInf, ray[1]*scaleInf, ray[2]*scaleInf), model.localTransform()); // in base_link frame
|
||||||
|
}
|
||||||
|
mapPoints.insert(std::make_pair(iter->second.first, util3d::transformPoint(pt, newFramePose)));
|
||||||
mapDescriptors.insert(std::make_pair(iter->second.first, iter->second.second.second.second));
|
mapDescriptors.insert(std::make_pair(iter->second.first, iter->second.second.second.second));
|
||||||
if(lastFrameOldestNewId_ > iter->second.first)
|
if(lastFrameOldestNewId_ > iter->second.first)
|
||||||
{
|
{
|
||||||
@@ -941,7 +1013,18 @@ Transform OdometryF2M::computeTransform(
|
|||||||
Transform newFramePose = this->getPose(); // initial pose may be not identity...
|
Transform newFramePose = this->getPose(); // initial pose may be not identity...
|
||||||
if(regPipeline_->isImageRequired())
|
if(regPipeline_->isImageRequired())
|
||||||
{
|
{
|
||||||
if ((int)lastFrame_->getWords3().size() >= regPipeline_->getMinVisualCorrespondences())
|
int ptsWithDepth = 0;
|
||||||
|
for (std::multimap<int, cv::Point3f>::const_iterator iter = lastFrame_->getWords3().begin();
|
||||||
|
iter != lastFrame_->getWords3().end();
|
||||||
|
++iter)
|
||||||
|
{
|
||||||
|
if(util3d::isFinite(iter->second))
|
||||||
|
{
|
||||||
|
++ptsWithDepth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptsWithDepth >= regPipeline_->getMinVisualCorrespondences())
|
||||||
{
|
{
|
||||||
frameValid = true;
|
frameValid = true;
|
||||||
// update local map
|
// update local map
|
||||||
@@ -994,11 +1077,11 @@ Transform OdometryF2M::computeTransform(
|
|||||||
|
|
||||||
//get depth
|
//get depth
|
||||||
float d = 0.0f;
|
float d = 0.0f;
|
||||||
if(lastFrame_->getWords3().count(iter->first) == 1)
|
if(lastFrame_->getWords3().count(iter->first) == 1 &&
|
||||||
|
util3d::isFinite(lastFrame_->getWords3().find(iter->first)->second))
|
||||||
{
|
{
|
||||||
//move back point in camera frame (to get depth along z)
|
//move back point in camera frame (to get depth along z)
|
||||||
cv::Point3f pt3d = util3d::transformPoint(lastFrame_->getWords3().find(iter->first)->second, invLocalTransform);
|
d = util3d::transformPoint(lastFrame_->getWords3().find(iter->first)->second, invLocalTransform).z;
|
||||||
d = pt3d.z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -176,6 +176,11 @@ Transform estimateMotion3DTo2D(
|
|||||||
{
|
{
|
||||||
UWARN("Not enough close points to compute covariance!");
|
UWARN("Not enough close points to compute covariance!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(float(oi) / float(inliers.size()) < 0.2f)
|
||||||
|
{
|
||||||
|
UWARN("A very low number of inliers have valid depth (%d/%d), the transform returned may be wrong!", oi, (int)inliers.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(covariance)
|
else if(covariance)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1196,7 +1196,7 @@ void MainWindow::processOdometry(const rtabmap::OdometryEvent & odom, bool dataI
|
|||||||
for(std::map<int, cv::Point3f>::const_iterator iter=odom.info().localMap.begin(); iter!=odom.info().localMap.end(); ++iter)
|
for(std::map<int, cv::Point3f>::const_iterator iter=odom.info().localMap.begin(); iter!=odom.info().localMap.end(); ++iter)
|
||||||
{
|
{
|
||||||
// filter very far features from current location
|
// filter very far features from current location
|
||||||
if(uNormSquared(iter->second.x-odom.pose().x(), iter->second.y-odom.pose().y(), iter->second.z-odom.pose().z()) < 50*50)
|
if(uNormSquared(iter->second.x-odom.pose().x(), iter->second.y-odom.pose().y(), iter->second.z-odom.pose().z()) < 100*100)
|
||||||
{
|
{
|
||||||
(*cloud)[i].x = iter->second.x;
|
(*cloud)[i].x = iter->second.x;
|
||||||
(*cloud)[i].y = iter->second.y;
|
(*cloud)[i].y = iter->second.y;
|
||||||
|
|||||||
@@ -1050,6 +1050,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
|
|||||||
_ui->spinBox_odom_f2m_scanMaxSize->setObjectName(Parameters::kOdomF2MScanMaxSize().c_str());
|
_ui->spinBox_odom_f2m_scanMaxSize->setObjectName(Parameters::kOdomF2MScanMaxSize().c_str());
|
||||||
_ui->doubleSpinBox_odom_f2m_scanRadius->setObjectName(Parameters::kOdomF2MScanSubtractRadius().c_str());
|
_ui->doubleSpinBox_odom_f2m_scanRadius->setObjectName(Parameters::kOdomF2MScanSubtractRadius().c_str());
|
||||||
_ui->doubleSpinBox_odom_f2m_scanAngle->setObjectName(Parameters::kOdomF2MScanSubtractAngle().c_str());
|
_ui->doubleSpinBox_odom_f2m_scanAngle->setObjectName(Parameters::kOdomF2MScanSubtractAngle().c_str());
|
||||||
|
_ui->odom_f2m_validDepthRatio->setObjectName(Parameters::kOdomF2MValidDepthRatio().c_str());
|
||||||
_ui->odom_f2m_bundleStrategy->setObjectName(Parameters::kOdomF2MBundleAdjustment().c_str());
|
_ui->odom_f2m_bundleStrategy->setObjectName(Parameters::kOdomF2MBundleAdjustment().c_str());
|
||||||
_ui->odom_f2m_bundleMaxFrames->setObjectName(Parameters::kOdomF2MBundleAdjustmentMaxFrames().c_str());
|
_ui->odom_f2m_bundleMaxFrames->setObjectName(Parameters::kOdomF2MBundleAdjustmentMaxFrames().c_str());
|
||||||
|
|
||||||
|
|||||||
@@ -94,16 +94,25 @@
|
|||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>-516</y>
|
||||||
<width>673</width>
|
<width>680</width>
|
||||||
<height>3038</height>
|
<height>3082</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="margin">
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
@@ -117,7 +126,7 @@
|
|||||||
<enum>QFrame::Raised</enum>
|
<enum>QFrame::Raised</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>18</number>
|
<number>19</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="page_22">
|
<widget class="QWidget" name="page_22">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1">
|
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1">
|
||||||
@@ -5164,7 +5173,16 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
|
|||||||
<string>Directory of images (optional settings)</string>
|
<string>Directory of images (optional settings)</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_93">
|
<layout class="QVBoxLayout" name="verticalLayout_93">
|
||||||
<property name="margin">
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
@@ -11888,7 +11906,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QStackedWidget" name="stackedWidget_odometryType">
|
<widget class="QStackedWidget" name="stackedWidget_odometryType">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>8</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="page_52">
|
<widget class="QWidget" name="page_52">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_77">
|
<layout class="QVBoxLayout" name="verticalLayout_77">
|
||||||
@@ -12017,7 +12035,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="QLabel" name="label_357">
|
<widget class="QLabel" name="label_357">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>[Visual] Local bundle adjustment. See Optimizer panel. This will not work if Optical Flow correspondences strategy is selected in Visual Registration panel.</string>
|
<string>[Visual] Local bundle adjustment. See Optimizer panel. This will not work if Optical Flow correspondences strategy is selected in Visual Registration panel.</string>
|
||||||
@@ -12030,14 +12048,14 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="7" column="0">
|
||||||
<widget class="QSpinBox" name="odom_f2m_bundleMaxFrames">
|
<widget class="QSpinBox" name="odom_f2m_bundleMaxFrames">
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>999999</number>
|
<number>999999</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="1">
|
<item row="7" column="1">
|
||||||
<widget class="QLabel" name="label_358">
|
<widget class="QLabel" name="label_358">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>[Visual] Maximum frames used for bundle adjustment (0=inf or all current frames in the local map).</string>
|
<string>[Visual] Maximum frames used for bundle adjustment (0=inf or all current frames in the local map).</string>
|
||||||
@@ -12050,7 +12068,7 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="6" column="0">
|
||||||
<widget class="QComboBox" name="odom_f2m_bundleStrategy">
|
<widget class="QComboBox" name="odom_f2m_bundleStrategy">
|
||||||
<property name="sizeAdjustPolicy">
|
<property name="sizeAdjustPolicy">
|
||||||
<enum>QComboBox::AdjustToContents</enum>
|
<enum>QComboBox::AdjustToContents</enum>
|
||||||
@@ -12101,6 +12119,38 @@ If set to false, classic RTAB-Map loop closure detection is done using only imag
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLabel" name="label_524">
|
||||||
|
<property name="text">
|
||||||
|
<string>[Visual] If a new frame has points without valid depth, they are added to local feature map only if points with valid depth on total points is over this ratio. Setting to 1 means no points without valid depth are added to local feature map.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QDoubleSpinBox" name="odom_f2m_validDepthRatio">
|
||||||
|
<property name="suffix">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.050000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.750000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@@ -15833,7 +15883,16 @@ Lower the ratio -> higher the precision.</string>
|
|||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="margin">
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
@@ -15913,7 +15972,16 @@ Lower the ratio -> higher the precision.</string>
|
|||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="margin">
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
@@ -16025,7 +16093,16 @@ Lower the ratio -> higher the precision.</string>
|
|||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="margin">
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
Reference in New Issue
Block a user