Refactored OdometryBOW class

git-svn-id: http://rtabmap.googlecode.com/svn/trunk/rtabmap@1846 f169173b-cf89-36c8-b27e-44dbe73f0c83
This commit is contained in:
matlabbe
2014-10-08 00:32:43 +00:00
parent ae57ea6ae5
commit a3f7415821
4 changed files with 74 additions and 107 deletions

View File

@@ -69,7 +69,7 @@ public:
float getMaxDepth() const {return _maxDepth;} float getMaxDepth() const {return _maxDepth;}
float geLinearUpdate() const {return _linearUpdate;} float geLinearUpdate() const {return _linearUpdate;}
float getAngularUpdate() const {return _angularUpdate;} float getAngularUpdate() const {return _angularUpdate;}
int getLocalHistory() const {return _localHistory;} int getLocalHistoryMaxSize() const {return _localHistoryMaxSize;}
private: private:
virtual Transform computeTransform(const SensorData & image, int * quality = 0, int * features = 0, int * localMapSize = 0) = 0; virtual Transform computeTransform(const SensorData & image, int * quality = 0, int * features = 0, int * localMapSize = 0) = 0;
@@ -84,7 +84,7 @@ private:
float _linearUpdate; float _linearUpdate;
float _angularUpdate; float _angularUpdate;
int _resetCountdown; int _resetCountdown;
int _localHistory; int _localHistoryMaxSize;
Transform _pose; Transform _pose;
int _resetCurrentCount; int _resetCurrentCount;
@@ -101,8 +101,7 @@ public:
virtual ~OdometryBOW(); virtual ~OdometryBOW();
virtual void reset(); virtual void reset();
const std::multimap<int, std::pair<int, pcl::PointXYZ> > & getLocalMap() const {return localMap_;} const std::multimap<int, pcl::PointXYZ> & getLocalMap() const {return localMap_;}
std::multimap<int,pcl::PointXYZ> getLocalMeansMap() const;
const Memory * getMemory() const {return _memory;} const Memory * getMemory() const {return _memory;}
private: private:
@@ -110,7 +109,7 @@ private:
private: private:
Memory * _memory; Memory * _memory;
std::multimap<int, std::pair<int, pcl::PointXYZ> > localMap_; std::multimap<int, pcl::PointXYZ> localMap_;
}; };
class RTABMAP_EXP OdometryICP : public Odometry class RTABMAP_EXP OdometryICP : public Odometry

View File

@@ -64,7 +64,7 @@ Odometry::Odometry(const rtabmap::ParametersMap & parameters) :
_linearUpdate(Parameters::defaultOdomLinearUpdate()), _linearUpdate(Parameters::defaultOdomLinearUpdate()),
_angularUpdate(Parameters::defaultOdomAngularUpdate()), _angularUpdate(Parameters::defaultOdomAngularUpdate()),
_resetCountdown(Parameters::defaultOdomResetCountdown()), _resetCountdown(Parameters::defaultOdomResetCountdown()),
_localHistory(Parameters::defaultOdomLocalHistory()), _localHistoryMaxSize(Parameters::defaultOdomLocalHistory()),
_pose(Transform::getIdentity()), _pose(Transform::getIdentity()),
_resetCurrentCount(0) _resetCurrentCount(0)
{ {
@@ -77,7 +77,7 @@ Odometry::Odometry(const rtabmap::ParametersMap & parameters) :
Parameters::parse(parameters, Parameters::kOdomWordsRatio(), _wordsRatio); Parameters::parse(parameters, Parameters::kOdomWordsRatio(), _wordsRatio);
Parameters::parse(parameters, Parameters::kOdomMaxDepth(), _maxDepth); Parameters::parse(parameters, Parameters::kOdomMaxDepth(), _maxDepth);
Parameters::parse(parameters, Parameters::kOdomMaxWords(), _maxFeatures); Parameters::parse(parameters, Parameters::kOdomMaxWords(), _maxFeatures);
Parameters::parse(parameters, Parameters::kOdomLocalHistory(), _localHistory); Parameters::parse(parameters, Parameters::kOdomLocalHistory(), _localHistoryMaxSize);
} }
void Odometry::reset() void Odometry::reset()
@@ -181,35 +181,6 @@ void OdometryBOW::reset()
localMap_.clear(); localMap_.clear();
} }
std::multimap<int,pcl::PointXYZ> OdometryBOW::getLocalMeansMap() const
{
std::multimap<int,pcl::PointXYZ> localMeansMap;
for(std::multimap<int, std::pair<int, pcl::PointXYZ> >::const_iterator iter=localMap_.begin();
iter!= localMap_.end();)
{
int id = iter->first;
pcl::PointXYZ sumPt = iter->second.second;
int count = 1;
++iter;
std::multimap<int, std::pair<int, pcl::PointXYZ> >::const_iterator jter=iter;
while(jter->first == id && jter!= localMap_.end())
{
sumPt.x += jter->second.second.x;
sumPt.y += jter->second.second.y;
sumPt.z += jter->second.second.z;
++count;
++jter;
}
iter = jter;
sumPt.x /= float(count);
sumPt.y /= float(count);
sumPt.z /= float(count);
localMeansMap.insert(std::make_pair(id, sumPt));
}
return localMeansMap;
}
// return not null transform if odometry is correctly computed // return not null transform if odometry is correctly computed
Transform OdometryBOW::computeTransform(const SensorData & data, int * quality, int * features, int * localMapSize) Transform OdometryBOW::computeTransform(const SensorData & data, int * quality, int * features, int * localMapSize)
{ {
@@ -243,26 +214,24 @@ Transform OdometryBOW::computeTransform(const SensorData & data, int * quality,
pcl::PointCloud<pcl::PointXYZ>::Ptr inliers1(new pcl::PointCloud<pcl::PointXYZ>); // previous pcl::PointCloud<pcl::PointXYZ>::Ptr inliers1(new pcl::PointCloud<pcl::PointXYZ>); // previous
pcl::PointCloud<pcl::PointXYZ>::Ptr inliers2(new pcl::PointCloud<pcl::PointXYZ>); // new pcl::PointCloud<pcl::PointXYZ>::Ptr inliers2(new pcl::PointCloud<pcl::PointXYZ>); // new
//Create the local map with mean of all features
std::multimap<int, pcl::PointXYZ> localMeansMap = getLocalMeansMap();
// No need to set max depth here, it is already applied in extractKeypointsAndDescriptors() above. // No need to set max depth here, it is already applied in extractKeypointsAndDescriptors() above.
// Also! the localMap_ have points not in camera frame anymore (in local map frame), so filtering // Also! the localMap_ have points not in camera frame anymore (in local map frame), so filtering
// by depth here is wrong! // by depth here is wrong!
util3d::findCorrespondences( util3d::findCorrespondences(
localMeansMap, localMap_,
newSignature->getWords3(), newSignature->getWords3(),
*inliers1, *inliers1,
*inliers2, *inliers2,
0, 0,
&uniqueCorrespondences); &uniqueCorrespondences);
UDEBUG("localMap=%d, new=%d, unique correspondences=%d", (int)localMeansMap.size(), (int)newSignature->getWords3().size(), (int)uniqueCorrespondences.size()); UDEBUG("localMap=%d, new=%d, unique correspondences=%d", (int)localMap_.size(), (int)newSignature->getWords3().size(), (int)uniqueCorrespondences.size());
if((int)inliers1->size() >= this->getMinInliers()) if((int)inliers1->size() >= this->getMinInliers())
{ {
correspondences = inliers1->size(); correspondences = inliers1->size();
// the transform returned is global odometry pose, not incremental one
transform = util3d::transformFromXYZCorrespondences( transform = util3d::transformFromXYZCorrespondences(
inliers2, inliers2,
inliers1, inliers1,
@@ -270,13 +239,34 @@ Transform OdometryBOW::computeTransform(const SensorData & data, int * quality,
this->getIterations(), this->getIterations(),
&inliers); &inliers);
if(!transform.isNull())
{
// make it incremental
transform = this->getPose().inverse() * transform;
UDEBUG("Odom transform = %s", transform.prettyPrint().c_str());
}
else
{
UDEBUG("Odom transform null");
//pcl::io::savePCDFile("from.pcd", *inliers1);
//inliers2 = util3d::transformPointCloud(inliers2, this->getPose());
//pcl::io::savePCDFile("to.pcd", *inliers2);
//inliers2 = util3d::transformPointCloud(inliers2, transform);
//pcl::io::savePCDFile("to_t.pcd", *inliers2);
}
/*pcl::io::savePCDFile("from.pcd", *inliers1);
inliers2 = util3d::transformPointCloud(inliers2, this->getPose());
pcl::io::savePCDFile("to.pcd", *inliers2);
inliers2 = util3d::transformPointCloud(inliers2, transform);
pcl::io::savePCDFile("to_t.pcd", *inliers2);*/
/* /*
//refine ICP test //refine ICP test
bool hasConverged; bool hasConverged;
double fitness; double fitness;
inliers2 = util3d::transformPointCloud(inliers2, transform); inliers2 = util3d::transformPointCloud(inliers2, transform);
Transform icpT = util3d::icp(inliers1, Transform icpT = util3d::icp(inliers1, <-- must be all correspondences, not only unique
inliers2, inliers2,
0.02, 0.02,
100, 100,
@@ -309,9 +299,7 @@ Transform OdometryBOW::computeTransform(const SensorData & data, int * quality,
} }
else else
{ {
if(this->getLocalHistory()<=0) output = transform;
{
output = this->getPose().inverse() * transform; // make it incremental
if(!isLargeEnoughTransform(transform)) if(!isLargeEnoughTransform(transform))
{ {
// Transform not large enough, keep the old signature // Transform not large enough, keep the old signature
@@ -319,68 +307,47 @@ Transform OdometryBOW::computeTransform(const SensorData & data, int * quality,
} }
else else
{ {
_memory->deleteLocation(previousSignature->id()); // remove words if history max size is reached
localMap_.clear(); while(localMap_.size() && (int)localMap_.size() > this->getLocalHistoryMaxSize() && _memory->getStMem().size()>1)
// update local map
std::list<int> uniques = uUniqueKeys(newSignature->getWords3());
for(std::list<int>::iterator iter = uniques.begin(); iter!=uniques.end(); ++iter)
{
if(newSignature->getWords3().count(*iter) == 1)
{
const pcl::PointXYZ & pt = newSignature->getWords3().find(*iter)->second;
if(pcl::isFinite(pt))
{
pcl::PointXYZ pt2 = util3d::transformPoint(pt, transform);
localMap_.insert(std::make_pair(*iter, std::make_pair(newSignature->id(), pt2)));
}
}
}
}
}
else
{
output = this->getPose().inverse() * transform; // make it incremental
if(isLargeEnoughTransform(transform))
{
// update local map only if transform is large enough
std::list<int> uniques = uUniqueKeys(newSignature->getWords3());
for(std::list<int>::iterator iter = uniques.begin(); iter!=uniques.end(); ++iter)
{
if(newSignature->getWords3().count(*iter) == 1)
{
const pcl::PointXYZ & pt = newSignature->getWords3().find(*iter)->second;
if(pcl::isFinite(pt))
{
pcl::PointXYZ pt2 = util3d::transformPoint(pt, transform);
localMap_.insert(std::make_pair(*iter, std::make_pair(newSignature->id(), pt2)));
}
}
}
while(localMap_.size() && (int)uUniqueKeys(localMap_).size() > this->getLocalHistory() && _memory->getStMem().size()>1)
{ {
int nodeId = *_memory->getStMem().begin(); int nodeId = *_memory->getStMem().begin();
std::list<int> removedPts = uUniqueKeys(_memory->getSignature(nodeId)->getWords3()); std::list<int> removedPts;
_memory->deleteLocation(nodeId, &removedPts);
for(std::list<int>::iterator iter = removedPts.begin(); iter!=removedPts.end(); ++iter) for(std::list<int>::iterator iter = removedPts.begin(); iter!=removedPts.end(); ++iter)
{ {
bool removed = false; localMap_.erase(*iter);
for(std::multimap<int, std::pair<int, pcl::PointXYZ> >::iterator jter=localMap_.lower_bound(*iter); }
jter->first == *iter && !removed; }
++jter)
if(this->getLocalHistoryMaxSize() == 0 && localMap_.size() > 0 && localMap_.size() > newSignature->getWords3().size())
{ {
if(jter->second.first == nodeId) UERROR("Local map should have only words of the last added signature here! (size=%d, max history size=%d, newWords=%d)",
(int)localMap_.size(), this->getLocalHistoryMaxSize(), (int)newSignature->getWords3().size());
}
// update local map
std::list<int> uniques = uUniqueKeys(newSignature->getWords3());
Transform t = this->getPose()*output;
for(std::list<int>::iterator iter = uniques.begin(); iter!=uniques.end(); ++iter)
{ {
localMap_.erase(jter); // Only add unique words not in local map
removed = true; if(newSignature->getWords3().count(*iter) == 1)
{
// keep old word
if(localMap_.find(*iter) == localMap_.end())
{
const pcl::PointXYZ & pt = newSignature->getWords3().find(*iter)->second;
if(pcl::isFinite(pt))
{
pcl::PointXYZ pt2 = util3d::transformPoint(pt, t);
localMap_.insert(std::make_pair(*iter, pt2));
} }
} }
} }
_memory->deleteLocation(*_memory->getStMem().begin());
}
}
else else
{ {
_memory->deleteLocation(newSignature->id()); localMap_.erase(*iter);
}
} }
} }
} }
@@ -394,12 +361,13 @@ Transform OdometryBOW::computeTransform(const SensorData & data, int * quality,
std::list<int> uniques = uUniqueKeys(newSignature->getWords3()); std::list<int> uniques = uUniqueKeys(newSignature->getWords3());
for(std::list<int>::iterator iter = uniques.begin(); iter!=uniques.end(); ++iter) for(std::list<int>::iterator iter = uniques.begin(); iter!=uniques.end(); ++iter)
{ {
// Only add unique words
if(newSignature->getWords3().count(*iter) == 1) if(newSignature->getWords3().count(*iter) == 1)
{ {
const pcl::PointXYZ & pt = newSignature->getWords3().find(*iter)->second; const pcl::PointXYZ & pt = newSignature->getWords3().find(*iter)->second;
if(pcl::isFinite(pt)) if(pcl::isFinite(pt))
{ {
localMap_.insert(std::make_pair(*iter, std::make_pair(newSignature->id(), pt))); localMap_.insert(std::make_pair(*iter, pt));
} }
else else
{ {

View File

@@ -1291,10 +1291,10 @@ bool Rtabmap::process(const SensorData & data)
uInsert(customParameters, ParametersPair(Parameters::kKpDetectorStrategy(), uNumber2Str(_reextractFeatureType))); // FAST/BRIEF uInsert(customParameters, ParametersPair(Parameters::kKpDetectorStrategy(), uNumber2Str(_reextractFeatureType))); // FAST/BRIEF
uInsert(customParameters, ParametersPair(Parameters::kKpWordsPerImage(), uNumber2Str(_reextractMaxWords))); uInsert(customParameters, ParametersPair(Parameters::kKpWordsPerImage(), uNumber2Str(_reextractMaxWords)));
for(ParametersMap::iterator iter = customParameters.begin(); iter!=customParameters.end(); ++iter) //for(ParametersMap::iterator iter = customParameters.begin(); iter!=customParameters.end(); ++iter)
{ //{
UINFO("%s=%s", iter->first.c_str(), iter->second.c_str()); // UDEBUG("%s=%s", iter->first.c_str(), iter->second.c_str());
} //}
Memory memory(customParameters); Memory memory(customParameters);

View File

@@ -1149,9 +1149,9 @@ Transform transformFromXYZCorrespondences(
crsc.setInputTarget(cloud1); crsc.setInputTarget(cloud1);
crsc.setMaximumIterations(iterations); crsc.setMaximumIterations(iterations);
crsc.setInlierThreshold(inlierThreshold); crsc.setInlierThreshold(inlierThreshold);
crsc.setRefineModel(true);
pcl::Correspondences correspondencesInliers; pcl::Correspondences correspondencesInliers;
crsc.getCorrespondences(correspondencesInliers); crsc.getCorrespondences(correspondencesInliers);
UDEBUG("RANSAC inliers=%d outliers=%d", (int)correspondencesInliers.size(), (int)correspondences->size()-(int)correspondencesInliers.size()); UDEBUG("RANSAC inliers=%d outliers=%d", (int)correspondencesInliers.size(), (int)correspondences->size()-(int)correspondencesInliers.size());
transform = util3d::transformFromEigen4f(crsc.getBestTransformation()); transform = util3d::transformFromEigen4f(crsc.getBestTransformation());