mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 01:20:25 +08:00
Updated rehearsal behavior when there are intermediate nodes and RGBD/LinearUpdate,RGBD/AngularUpdate are set.
This commit is contained in:
@@ -118,25 +118,29 @@ public:
|
|||||||
infMatrix_.at<double>(5,5) = 1.0/rotVariance;
|
infMatrix_.at<double>(5,5) = 1.0/rotVariance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Link merge(const Link & link) const
|
Link merge(const Link & link, Type outputType) const
|
||||||
{
|
{
|
||||||
UASSERT(to_ == link.from());
|
UASSERT(to_ == link.from());
|
||||||
UASSERT(type_ == link.type());
|
UASSERT(outputType != Link::kUndef);
|
||||||
UASSERT(!transform_.isNull());
|
UASSERT((link.transform().isNull() && transform_.isNull()) || (!link.transform().isNull() && !transform_.isNull()));
|
||||||
UASSERT(!link.transform().isNull());
|
|
||||||
UASSERT(infMatrix_.cols == 6 && infMatrix_.rows == 6 && infMatrix_.type() == CV_64FC1);
|
UASSERT(infMatrix_.cols == 6 && infMatrix_.rows == 6 && infMatrix_.type() == CV_64FC1);
|
||||||
UASSERT(link.infMatrix().cols == 6 && link.infMatrix().rows == 6 && link.infMatrix().type() == CV_64FC1);
|
UASSERT(link.infMatrix().cols == 6 && link.infMatrix().rows == 6 && link.infMatrix().type() == CV_64FC1);
|
||||||
return Link(
|
return Link(
|
||||||
from_,
|
from_,
|
||||||
link.to(),
|
link.to(),
|
||||||
type_,
|
outputType,
|
||||||
transform_ * link.transform(), // FIXME, should be inf1^-1(inf1*t1 + inf2*t2)
|
transform_.isNull()?Transform():transform_ * link.transform(), // FIXME, should be inf1^-1(inf1*t1 + inf2*t2)
|
||||||
infMatrix_ + link.infMatrix());
|
transform_.isNull()?cv::Mat::eye(6,6,CV_64FC1):infMatrix_ + link.infMatrix());
|
||||||
}
|
}
|
||||||
|
|
||||||
Link inverse() const
|
Link inverse() const
|
||||||
{
|
{
|
||||||
return Link(to_, from_, type_, transform_.inverse(), infMatrix_);
|
return Link(
|
||||||
|
to_,
|
||||||
|
from_,
|
||||||
|
type_,
|
||||||
|
transform_.isNull()?Transform():transform_.inverse(),
|
||||||
|
transform_.isNull()?cv::Mat::eye(6,6,CV_64FC1):infMatrix_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -286,8 +286,8 @@ class RTABMAP_EXP Parameters
|
|||||||
// RGB-D SLAM
|
// RGB-D SLAM
|
||||||
RTABMAP_PARAM(RGBD, Enabled, bool, true, "");
|
RTABMAP_PARAM(RGBD, Enabled, bool, true, "");
|
||||||
RTABMAP_PARAM(RGBD, PoseScanMatching, bool, false, "Laser scan matching for odometry pose correction (laser scans are required).");
|
RTABMAP_PARAM(RGBD, PoseScanMatching, bool, false, "Laser scan matching for odometry pose correction (laser scans are required).");
|
||||||
RTABMAP_PARAM(RGBD, LinearUpdate, float, 0.0, "Min linear displacement to update the map. Rehearsal is done prior to this, so weights are still updated.");
|
RTABMAP_PARAM(RGBD, LinearUpdate, float, 0.0, "Minimum linear displacement to update the map. Rehearsal is done prior to this, so weights are still updated.");
|
||||||
RTABMAP_PARAM(RGBD, AngularUpdate, float, 0.0, "Min angular displacement to update the map. Rehearsal is done prior to this, so weights are still updated.");
|
RTABMAP_PARAM(RGBD, AngularUpdate, float, 0.0, "Minimum angular displacement to update the map. Rehearsal is done prior to this, so weights are still updated.");
|
||||||
RTABMAP_PARAM(RGBD, NewMapOdomChangeDistance, float, 0, "A new map is created if a change of odometry translation greater than X m is detected (0 m = disabled).");
|
RTABMAP_PARAM(RGBD, NewMapOdomChangeDistance, float, 0, "A new map is created if a change of odometry translation greater than X m is detected (0 m = disabled).");
|
||||||
RTABMAP_PARAM(RGBD, OptimizeFromGraphEnd, bool, false, "Optimize graph from the newest node. If false, the graph is optimized from the oldest node of the current graph (this adds an overhead computation to detect to oldest mode of the current graph, but it can be useful to preserve the map referential from the oldest node). Warning when set to false: when some nodes are transferred, the first referential of the local map may change, resulting in momentary changes in robot/map position (which are annoying in teleoperation).");
|
RTABMAP_PARAM(RGBD, OptimizeFromGraphEnd, bool, false, "Optimize graph from the newest node. If false, the graph is optimized from the oldest node of the current graph (this adds an overhead computation to detect to oldest mode of the current graph, but it can be useful to preserve the map referential from the oldest node). Warning when set to false: when some nodes are transferred, the first referential of the local map may change, resulting in momentary changes in robot/map position (which are annoying in teleoperation).");
|
||||||
RTABMAP_PARAM(RGBD, GoalReachedRadius, float, 0.5, "Goal reached radius (m).");
|
RTABMAP_PARAM(RGBD, GoalReachedRadius, float, 0.5, "Goal reached radius (m).");
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ class RTABMAP_EXP Statistics
|
|||||||
RTABMAP_STATS(Memory, Signatures_retrieved,);
|
RTABMAP_STATS(Memory, Signatures_retrieved,);
|
||||||
RTABMAP_STATS(Memory, Images_buffered,);
|
RTABMAP_STATS(Memory, Images_buffered,);
|
||||||
RTABMAP_STATS(Memory, Rehearsal_sim,);
|
RTABMAP_STATS(Memory, Rehearsal_sim,);
|
||||||
|
RTABMAP_STATS(Memory, Rehearsal_id,);
|
||||||
RTABMAP_STATS(Memory, Rehearsal_merged,);
|
RTABMAP_STATS(Memory, Rehearsal_merged,);
|
||||||
RTABMAP_STATS(Memory, Local_graph_size,);
|
RTABMAP_STATS(Memory, Local_graph_size,);
|
||||||
|
|
||||||
|
|||||||
@@ -420,6 +420,8 @@ void Memory::parseParameters(const ParametersMap & parameters)
|
|||||||
UASSERT_MSG(_similarityThreshold >= 0.0f && _similarityThreshold <= 1.0f, uFormat("value=%f", _similarityThreshold).c_str());
|
UASSERT_MSG(_similarityThreshold >= 0.0f && _similarityThreshold <= 1.0f, uFormat("value=%f", _similarityThreshold).c_str());
|
||||||
UASSERT_MSG(_recentWmRatio >= 0.0f && _recentWmRatio <= 1.0f, uFormat("value=%f", _recentWmRatio).c_str());
|
UASSERT_MSG(_recentWmRatio >= 0.0f && _recentWmRatio <= 1.0f, uFormat("value=%f", _recentWmRatio).c_str());
|
||||||
UASSERT(_imageDecimation >= 1);
|
UASSERT(_imageDecimation >= 1);
|
||||||
|
UASSERT(_rehearsalMaxDistance >= 0.0f);
|
||||||
|
UASSERT(_rehearsalMaxAngle >= 0.0f);
|
||||||
|
|
||||||
// SLAM mode vs Localization mode
|
// SLAM mode vs Localization mode
|
||||||
iter = parameters.find(Parameters::kMemIncrementalMemory());
|
iter = parameters.find(Parameters::kMemIncrementalMemory());
|
||||||
@@ -3091,7 +3093,7 @@ void Memory::rehearsal(Signature * signature, Statistics * stats)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// Compare with the last (not null)
|
// Compare with the last (not intermediate node)
|
||||||
//============================================================
|
//============================================================
|
||||||
Signature * sB = 0;
|
Signature * sB = 0;
|
||||||
for(std::set<int>::reverse_iterator iter=_stMem.rbegin(); iter!=_stMem.rend(); ++iter)
|
for(std::set<int>::reverse_iterator iter=_stMem.rbegin(); iter!=_stMem.rend(); ++iter)
|
||||||
@@ -3116,55 +3118,9 @@ void Memory::rehearsal(Signature * signature, Statistics * stats)
|
|||||||
{
|
{
|
||||||
if(_incrementalMemory)
|
if(_incrementalMemory)
|
||||||
{
|
{
|
||||||
if(signature->hasLink(id))
|
if(this->rehearsalMerge(id, signature->id()))
|
||||||
{
|
{
|
||||||
if(signature->getLinks().begin()->second.transform().isNull())
|
merged = id;
|
||||||
{
|
|
||||||
if(this->rehearsalMerge(id, signature->id()))
|
|
||||||
{
|
|
||||||
merged = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float x,y,z, roll,pitch,yaw;
|
|
||||||
signature->getLinks().begin()->second.transform().getTranslationAndEulerAngles(x,y,z, roll,pitch,yaw);
|
|
||||||
if((_rehearsalMaxDistance>0.0f && (
|
|
||||||
fabs(x) > _rehearsalMaxDistance ||
|
|
||||||
fabs(y) > _rehearsalMaxDistance ||
|
|
||||||
fabs(z) > _rehearsalMaxDistance)) ||
|
|
||||||
(_rehearsalMaxAngle>0.0f && (
|
|
||||||
fabs(roll) > _rehearsalMaxAngle ||
|
|
||||||
fabs(pitch) > _rehearsalMaxAngle ||
|
|
||||||
fabs(yaw) > _rehearsalMaxAngle)))
|
|
||||||
{
|
|
||||||
if(_rehearsalWeightIgnoredWhileMoving)
|
|
||||||
{
|
|
||||||
UINFO("Rehearsal ignored because the robot has moved more than %f m or %f rad",
|
|
||||||
_rehearsalMaxDistance, _rehearsalMaxAngle);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// if the robot has moved, increase only weight of the new one
|
|
||||||
signature->setWeight(sB->getWeight() + signature->getWeight() + 1);
|
|
||||||
sB->setWeight(0);
|
|
||||||
UINFO("Only updated weight to %d of %d (old=%d) because the robot has moved. (d=%f a=%f)",
|
|
||||||
signature->getWeight(), signature->id(), sB->id(), _rehearsalMaxDistance, _rehearsalMaxAngle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(this->rehearsalMerge(id, signature->id()))
|
|
||||||
{
|
|
||||||
merged = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// cannot merge not neighbor signatures, just update weight
|
|
||||||
signature->setWeight(sB->getWeight() + signature->getWeight() + 1);
|
|
||||||
sB->setWeight(0);
|
|
||||||
UINFO("Only updated weight to %d of %d (old=%d) because the signatures are not neighbors.",
|
|
||||||
signature->getWeight(), signature->id(), sB->id());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -3175,6 +3131,7 @@ void Memory::rehearsal(Signature * signature, Statistics * stats)
|
|||||||
|
|
||||||
if(stats) stats->addStatistic(Statistics::kMemoryRehearsal_merged(), merged);
|
if(stats) stats->addStatistic(Statistics::kMemoryRehearsal_merged(), merged);
|
||||||
if(stats) stats->addStatistic(Statistics::kMemoryRehearsal_sim(), sim);
|
if(stats) stats->addStatistic(Statistics::kMemoryRehearsal_sim(), sim);
|
||||||
|
if(stats) stats->addStatistic(Statistics::kMemoryRehearsal_id(), sim >= _similarityThreshold?id:0);
|
||||||
UDEBUG("merged=%d, sim=%f t=%fs", merged, sim, timer.ticks());
|
UDEBUG("merged=%d, sim=%f t=%fs", merged, sim, timer.ticks());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -3202,65 +3159,122 @@ bool Memory::rehearsalMerge(int oldId, int newId)
|
|||||||
|
|
||||||
UINFO("Rehearsal merging %d and %d", oldS->id(), newS->id());
|
UINFO("Rehearsal merging %d and %d", oldS->id(), newS->id());
|
||||||
|
|
||||||
//remove mutual links
|
bool fullMerge;
|
||||||
oldS->removeLink(newId);
|
bool intermediateMerge = false;
|
||||||
newS->removeLink(oldId);
|
if(!newS->getLinks().begin()->second.transform().isNull())
|
||||||
|
|
||||||
if(_idUpdatedToNewOneRehearsal)
|
|
||||||
{
|
{
|
||||||
// redirect neighbor links
|
// we are in metric SLAM mode:
|
||||||
const std::map<int, Link> & links = oldS->getLinks();
|
// 1) Normal merge if not moving AND has direct link
|
||||||
for(std::map<int, Link>::const_iterator iter = links.begin(); iter!=links.end(); ++iter)
|
// 2) Transform to intermediate node (weight = -1) if not moving AND hasn't direct link.
|
||||||
|
float x,y,z, roll,pitch,yaw;
|
||||||
|
newS->getLinks().begin()->second.transform().getTranslationAndEulerAngles(x,y,z, roll,pitch,yaw);
|
||||||
|
bool isMoving = fabs(x) > _rehearsalMaxDistance ||
|
||||||
|
fabs(y) > _rehearsalMaxDistance ||
|
||||||
|
fabs(z) > _rehearsalMaxDistance ||
|
||||||
|
fabs(roll) > _rehearsalMaxAngle ||
|
||||||
|
fabs(pitch) > _rehearsalMaxAngle ||
|
||||||
|
fabs(yaw) > _rehearsalMaxAngle;
|
||||||
|
if(isMoving && _rehearsalWeightIgnoredWhileMoving)
|
||||||
{
|
{
|
||||||
Link link = iter->second;
|
UINFO("Rehearsal ignored because the robot has moved more than %f m or %f rad (\"Mem/RehearsalWeightIgnoredWhileMoving\"=true)",
|
||||||
link.setFrom(newS->id());
|
_rehearsalMaxDistance, _rehearsalMaxAngle);
|
||||||
|
return false;
|
||||||
Signature * s = this->_getSignature(link.to());
|
|
||||||
if(s)
|
|
||||||
{
|
|
||||||
// modify neighbor "from"
|
|
||||||
s->changeLinkIds(oldS->id(), newS->id());
|
|
||||||
|
|
||||||
newS->addLink(link);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UERROR("Didn't find neighbor %d of %d in RAM...", link.to(), oldS->id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newS->setLabel(oldS->getLabel());
|
|
||||||
oldS->setLabel("");
|
|
||||||
oldS->removeLinks(); // remove all links
|
|
||||||
oldS->addLink(Link(oldS->id(), newS->id(), Link::kGlobalClosure, Transform(), 1, 1)); // to keep track of the merged location
|
|
||||||
|
|
||||||
// Set old image to new signature
|
|
||||||
this->copyData(oldS, newS);
|
|
||||||
|
|
||||||
// update weight
|
|
||||||
newS->setWeight(newS->getWeight() + 1 + oldS->getWeight());
|
|
||||||
|
|
||||||
if(_lastGlobalLoopClosureId == oldS->id())
|
|
||||||
{
|
|
||||||
_lastGlobalLoopClosureId = newS->id();
|
|
||||||
}
|
}
|
||||||
|
fullMerge = !isMoving && newS->hasLink(oldS->id());
|
||||||
|
intermediateMerge = !isMoving && !newS->hasLink(oldS->id());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newS->addLink(Link(newS->id(), oldS->id(), Link::kGlobalClosure, Transform() , 1, 1)); // to keep track of the merged location
|
fullMerge = newS->hasLink(oldS->id()) && newS->getLinks().begin()->second.transform().isNull();
|
||||||
|
|
||||||
// update weight
|
|
||||||
oldS->setWeight(newS->getWeight() + 1 + oldS->getWeight());
|
|
||||||
|
|
||||||
if(_lastSignature == newS)
|
|
||||||
{
|
|
||||||
_lastSignature = oldS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove location
|
if(fullMerge)
|
||||||
moveToTrash(_idUpdatedToNewOneRehearsal?oldS:newS, _notLinkedNodesKeptInDb);
|
{
|
||||||
|
//remove mutual links
|
||||||
|
Link newToOldLink = newS->getLinks().at(oldS->id());
|
||||||
|
oldS->removeLink(newId);
|
||||||
|
newS->removeLink(oldId);
|
||||||
|
|
||||||
return true;
|
if(_idUpdatedToNewOneRehearsal)
|
||||||
|
{
|
||||||
|
// redirect neighbor links
|
||||||
|
const std::map<int, Link> & links = oldS->getLinks();
|
||||||
|
for(std::map<int, Link>::const_iterator iter = links.begin(); iter!=links.end(); ++iter)
|
||||||
|
{
|
||||||
|
Link link = iter->second;
|
||||||
|
Link mergedLink = newToOldLink.merge(link, link.type());
|
||||||
|
UASSERT(mergedLink.from() == newS->id() && mergedLink.to() == link.to());
|
||||||
|
|
||||||
|
Signature * s = this->_getSignature(link.to());
|
||||||
|
if(s)
|
||||||
|
{
|
||||||
|
// modify neighbor "from"
|
||||||
|
s->removeLink(oldS->id());
|
||||||
|
s->addLink(mergedLink.inverse());
|
||||||
|
|
||||||
|
newS->addLink(mergedLink);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UERROR("Didn't find neighbor %d of %d in RAM...", link.to(), oldS->id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newS->setLabel(oldS->getLabel());
|
||||||
|
oldS->setLabel("");
|
||||||
|
oldS->removeLinks(); // remove all links
|
||||||
|
oldS->addLink(Link(oldS->id(), newS->id(), Link::kGlobalClosure, Transform(), 1, 1)); // to keep track of the merged location
|
||||||
|
|
||||||
|
// Set old image to new signature
|
||||||
|
this->copyData(oldS, newS);
|
||||||
|
|
||||||
|
// update weight
|
||||||
|
newS->setWeight(newS->getWeight() + 1 + oldS->getWeight());
|
||||||
|
|
||||||
|
if(_lastGlobalLoopClosureId == oldS->id())
|
||||||
|
{
|
||||||
|
_lastGlobalLoopClosureId = newS->id();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newS->addLink(Link(newS->id(), oldS->id(), Link::kGlobalClosure, Transform() , 1, 1)); // to keep track of the merged location
|
||||||
|
|
||||||
|
// update weight
|
||||||
|
oldS->setWeight(newS->getWeight() + 1 + oldS->getWeight());
|
||||||
|
|
||||||
|
if(_lastSignature == newS)
|
||||||
|
{
|
||||||
|
_lastSignature = oldS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove location
|
||||||
|
moveToTrash(_idUpdatedToNewOneRehearsal?oldS:newS, _notLinkedNodesKeptInDb);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// update only weights
|
||||||
|
if(_idUpdatedToNewOneRehearsal)
|
||||||
|
{
|
||||||
|
// just update weight
|
||||||
|
int w = oldS->getWeight()>=0?oldS->getWeight():0;
|
||||||
|
newS->setWeight(w + newS->getWeight() + 1);
|
||||||
|
oldS->setWeight(intermediateMerge?-1:0); // convert to intermediate node
|
||||||
|
|
||||||
|
if(_lastGlobalLoopClosureId == oldS->id())
|
||||||
|
{
|
||||||
|
_lastGlobalLoopClosureId = newS->id();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // !_idUpdatedToNewOneRehearsal
|
||||||
|
{
|
||||||
|
int w = newS->getWeight()>=0?newS->getWeight():0;
|
||||||
|
oldS->setWeight(w + oldS->getWeight() + 1);
|
||||||
|
newS->setWeight(intermediateMerge?-1:0); // convert to intermediate node
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -3273,7 +3287,7 @@ bool Memory::rehearsalMerge(int oldId, int newId)
|
|||||||
UERROR("newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, oldId);
|
UERROR("newId=%d, oldId=%d, Signature %d not found in working/st memories", newId, oldId, oldId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false; // means that the newS can be removed without problem
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform Memory::getOdomPose(int signatureId, bool lookInDatabase) const
|
Transform Memory::getOdomPose(int signatureId, bool lookInDatabase) const
|
||||||
@@ -4599,7 +4613,7 @@ void Memory::getMetricConstraints(
|
|||||||
const Signature * s2 = this->getSignature(uter->first);
|
const Signature * s2 = this->getSignature(uter->first);
|
||||||
if(s2)
|
if(s2)
|
||||||
{
|
{
|
||||||
link = link.merge(uter->second);
|
link = link.merge(uter->second, uter->second.type());
|
||||||
poses.erase(s->id());
|
poses.erase(s->id());
|
||||||
s = s2;
|
s = s2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,6 +409,9 @@ void Rtabmap::parseParameters(const ParametersMap & parameters)
|
|||||||
Parameters::parse(parameters, Parameters::kRGBDPlanVirtualLinks(), _planVirtualLinks);
|
Parameters::parse(parameters, Parameters::kRGBDPlanVirtualLinks(), _planVirtualLinks);
|
||||||
Parameters::parse(parameters, Parameters::kRGBDGoalsSavedInUserData(), _goalsSavedInUserData);
|
Parameters::parse(parameters, Parameters::kRGBDGoalsSavedInUserData(), _goalsSavedInUserData);
|
||||||
|
|
||||||
|
UASSERT(_rgbdLinearUpdate >= 0.0f);
|
||||||
|
UASSERT(_rgbdAngularUpdate >= 0.0f);
|
||||||
|
|
||||||
// RGB-D SLAM stuff
|
// RGB-D SLAM stuff
|
||||||
if((iter=parameters.find(Parameters::kLccIcpType())) != parameters.end())
|
if((iter=parameters.find(Parameters::kLccIcpType())) != parameters.end())
|
||||||
{
|
{
|
||||||
@@ -986,7 +989,7 @@ bool Rtabmap::process(
|
|||||||
UFATAL("Not supposed to be here...last signature is null?!?");
|
UFATAL("Not supposed to be here...last signature is null?!?");
|
||||||
}
|
}
|
||||||
|
|
||||||
ULOGGER_INFO("Processing signature %d", signature->id());
|
ULOGGER_INFO("Processing signature %d w=%d", signature->id(), signature->getWeight());
|
||||||
timeMemoryUpdate = timer.ticks();
|
timeMemoryUpdate = timer.ticks();
|
||||||
ULOGGER_INFO("timeMemoryUpdate=%fs", timeMemoryUpdate);
|
ULOGGER_INFO("timeMemoryUpdate=%fs", timeMemoryUpdate);
|
||||||
|
|
||||||
@@ -1002,7 +1005,7 @@ bool Rtabmap::process(
|
|||||||
{
|
{
|
||||||
_optimizedPoses.erase(rehearsedId);
|
_optimizedPoses.erase(rehearsedId);
|
||||||
}
|
}
|
||||||
else if(_rgbdLinearUpdate > 0.0f && _rgbdAngularUpdate > 0.0f)
|
else if(signature->getWeight() >= 0 && _rgbdLinearUpdate > 0.0f && _rgbdAngularUpdate > 0.0f)
|
||||||
{
|
{
|
||||||
//============================================================
|
//============================================================
|
||||||
// Minimum displacement required to add to Memory
|
// Minimum displacement required to add to Memory
|
||||||
@@ -1010,20 +1013,25 @@ bool Rtabmap::process(
|
|||||||
const std::map<int, Link> & links = signature->getLinks();
|
const std::map<int, Link> & links = signature->getLinks();
|
||||||
if(links.size() == 1)
|
if(links.size() == 1)
|
||||||
{
|
{
|
||||||
float x,y,z, roll,pitch,yaw;
|
// don't do this if there are intermediate nodes
|
||||||
links.begin()->second.transform().getTranslationAndEulerAngles(x,y,z, roll,pitch,yaw);
|
const Signature * s = _memory->getSignature(links.begin()->second.to());
|
||||||
if((_rgbdLinearUpdate==0.0f || (
|
UASSERT(s!=0);
|
||||||
fabs(x) < _rgbdLinearUpdate &&
|
if(s->getWeight() >= 0)
|
||||||
fabs(y) < _rgbdLinearUpdate &&
|
|
||||||
fabs(z) < _rgbdLinearUpdate)) &&
|
|
||||||
(_rgbdAngularUpdate==0.0f || (
|
|
||||||
fabs(roll) < _rgbdAngularUpdate &&
|
|
||||||
fabs(pitch) < _rgbdAngularUpdate &&
|
|
||||||
fabs(yaw) < _rgbdAngularUpdate)))
|
|
||||||
{
|
{
|
||||||
// This will disable global loop closure detection, only retrieval will be done.
|
float x,y,z, roll,pitch,yaw;
|
||||||
// The location will also be deleted at the end.
|
links.begin()->second.transform().getTranslationAndEulerAngles(x,y,z, roll,pitch,yaw);
|
||||||
smallDisplacement = true;
|
bool isMoving = fabs(x) > _rgbdLinearUpdate ||
|
||||||
|
fabs(y) > _rgbdLinearUpdate ||
|
||||||
|
fabs(z) > _rgbdLinearUpdate ||
|
||||||
|
fabs(roll) > _rgbdAngularUpdate ||
|
||||||
|
fabs(pitch) > _rgbdAngularUpdate ||
|
||||||
|
fabs(yaw) > _rgbdAngularUpdate;
|
||||||
|
if(!isMoving)
|
||||||
|
{
|
||||||
|
// This will disable global loop closure detection, only retrieval will be done.
|
||||||
|
// The location will also be deleted at the end.
|
||||||
|
smallDisplacement = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1088,7 +1096,7 @@ bool Rtabmap::process(
|
|||||||
UASSERT(s!=0);
|
UASSERT(s!=0);
|
||||||
if(s->getWeight() == -1)
|
if(s->getWeight() == -1)
|
||||||
{
|
{
|
||||||
tmp = _constraints.rbegin()->second.merge(tmp);
|
tmp = _constraints.rbegin()->second.merge(tmp, tmp.type());
|
||||||
_optimizedPoses.erase(s->id());
|
_optimizedPoses.erase(s->id());
|
||||||
_constraints.erase(--_constraints.end());
|
_constraints.erase(--_constraints.end());
|
||||||
}
|
}
|
||||||
@@ -1156,7 +1164,7 @@ bool Rtabmap::process(
|
|||||||
// Bayes filter update
|
// Bayes filter update
|
||||||
//============================================================
|
//============================================================
|
||||||
int previousId = signature->getLinks().size() == 1?signature->getLinks().begin()->first:0;
|
int previousId = signature->getLinks().size() == 1?signature->getLinks().begin()->first:0;
|
||||||
// Not a bad signature, not a small displacemnt unless the previous signature didn't have a loop closure
|
// Not a bad signature, not a small displacement unless the previous signature didn't have a loop closure
|
||||||
if(!signature->isBadSignature() && (!smallDisplacement || _memory->getLoopClosureLinks(previousId, false).size() == 0))
|
if(!signature->isBadSignature() && (!smallDisplacement || _memory->getLoopClosureLinks(previousId, false).size() == 0))
|
||||||
{
|
{
|
||||||
// If the working memory is empty, don't do the detection. It happens when it
|
// If the working memory is empty, don't do the detection. It happens when it
|
||||||
|
|||||||
@@ -205,6 +205,7 @@ public:
|
|||||||
bool isStatisticsPublished() const;
|
bool isStatisticsPublished() const;
|
||||||
double getLoopThr() const;
|
double getLoopThr() const;
|
||||||
double getVpThr() const;
|
double getVpThr() const;
|
||||||
|
double getSimThr() const;
|
||||||
int getOdomStrategy() const;
|
int getOdomStrategy() const;
|
||||||
int getOdomBufferSize() const;
|
int getOdomBufferSize() const;
|
||||||
QString getCameraInfoDir() const; // "workinfDir/camera_info"
|
QString getCameraInfoDir() const; // "workinfDir/camera_info"
|
||||||
|
|||||||
@@ -1075,23 +1075,28 @@ void MainWindow::processStats(const rtabmap::Statistics & stat)
|
|||||||
_ui->label_matchId->clear();
|
_ui->label_matchId->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int rehearsed = (int)uValue(stat.data(), Statistics::kMemoryRehearsal_merged(), 0.0f);
|
int rehearsalMerged = (int)uValue(stat.data(), Statistics::kMemoryRehearsal_merged(), 0.0f);
|
||||||
|
bool rehearsedSimilarity = (float)uValue(stat.data(), Statistics::kMemoryRehearsal_id(), 0.0f) != 0.0f;
|
||||||
int localTimeClosures = (int)uValue(stat.data(), Statistics::kLocalLoopTime_closures(), 0.0f);
|
int localTimeClosures = (int)uValue(stat.data(), Statistics::kLocalLoopTime_closures(), 0.0f);
|
||||||
bool scanMatchingSuccess = (bool)uValue(stat.data(), Statistics::kOdomCorrectionAccepted(), 0.0f);
|
bool scanMatchingSuccess = (bool)uValue(stat.data(), Statistics::kOdomCorrectionAccepted(), 0.0f);
|
||||||
_ui->label_stats_imageNumber->setText(QString("%1 [%2]").arg(stat.refImageId()).arg(refMapId));
|
_ui->label_stats_imageNumber->setText(QString("%1 [%2]").arg(stat.refImageId()).arg(refMapId));
|
||||||
|
|
||||||
if(rehearsed > 0)
|
if(rehearsalMerged > 0)
|
||||||
{
|
{
|
||||||
_ui->imageView_source->setBackgroundColor(Qt::blue);
|
_ui->imageView_source->setBackgroundColor(Qt::blue);
|
||||||
}
|
}
|
||||||
else if(localTimeClosures > 0)
|
else if(localTimeClosures > 0)
|
||||||
{
|
{
|
||||||
_ui->imageView_source->setBackgroundColor(Qt::darkCyan);
|
_ui->imageView_source->setBackgroundColor(Qt::darkYellow);
|
||||||
}
|
}
|
||||||
else if(scanMatchingSuccess)
|
else if(scanMatchingSuccess)
|
||||||
{
|
{
|
||||||
_ui->imageView_source->setBackgroundColor(Qt::gray);
|
_ui->imageView_source->setBackgroundColor(Qt::gray);
|
||||||
}
|
}
|
||||||
|
else if(rehearsedSimilarity)
|
||||||
|
{
|
||||||
|
_ui->imageView_source->setBackgroundColor(Qt::darkBlue);
|
||||||
|
}
|
||||||
|
|
||||||
UDEBUG("time= %d ms", time.restart());
|
UDEBUG("time= %d ms", time.restart());
|
||||||
|
|
||||||
|
|||||||
@@ -3670,6 +3670,10 @@ double PreferencesDialog::getVpThr() const
|
|||||||
{
|
{
|
||||||
return _ui->general_doubleSpinBox_vp->value();
|
return _ui->general_doubleSpinBox_vp->value();
|
||||||
}
|
}
|
||||||
|
double PreferencesDialog::getSimThr() const
|
||||||
|
{
|
||||||
|
return _ui->doubleSpinBox_similarityThreshold->value();
|
||||||
|
}
|
||||||
int PreferencesDialog::getOdomStrategy() const
|
int PreferencesDialog::getOdomStrategy() const
|
||||||
{
|
{
|
||||||
return _ui->odom_strategy->currentIndex();
|
return _ui->odom_strategy->currentIndex();
|
||||||
|
|||||||
Reference in New Issue
Block a user