Added parameter RGBD/GoalMaxDistance, fixed graph:computePath() warnings

This commit is contained in:
Mathieu Labbe
2015-02-18 16:57:16 -05:00
parent 9dfbe8d233
commit cead1e00d4
7 changed files with 123 additions and 40 deletions
+3 -1
View File
@@ -101,13 +101,15 @@ std::multimap<int, int> RTABMAP_EXP radiusPosesClustering(
* @param links The graph's links (from node id -> to node id) * @param links The graph's links (from node id -> to node id)
* @param from initial node * @param from initial node
* @param to final node * @param to final node
* @param updateNewCosts Keep up-to-date costs while traversing the graph.
* @return the path ids from id "from" to id "to" including initial and final nodes. * @return the path ids from id "from" to id "to" including initial and final nodes.
*/ */
std::list<std::pair<int, Transform> > RTABMAP_EXP computePath( std::list<std::pair<int, Transform> > RTABMAP_EXP computePath(
const std::map<int, rtabmap::Transform> & poses, const std::map<int, rtabmap::Transform> & poses,
const std::multimap<int, int> & links, const std::multimap<int, int> & links,
int from, int from,
int to); int to,
bool updateNewCosts = false);
int RTABMAP_EXP findNearestNode( int RTABMAP_EXP findNearestNode(
const std::map<int, rtabmap::Transform> & nodes, const std::map<int, rtabmap::Transform> & nodes,
@@ -292,6 +292,7 @@ class RTABMAP_EXP Parameters
RTABMAP_PARAM(RGBD, GoalReachedRadius, float, 0.5, "Goal reached radius (m)."); RTABMAP_PARAM(RGBD, GoalReachedRadius, float, 0.5, "Goal reached radius (m).");
RTABMAP_PARAM(RGBD, MaxAnticipatedNodes, unsigned int, 10, "Maximum anticipated nodes on the computed path that can be retrieved (the number of nodes actually retrieved at each iteration is limited by \"Rtabmap/MaxRetrieved\")."); RTABMAP_PARAM(RGBD, MaxAnticipatedNodes, unsigned int, 10, "Maximum anticipated nodes on the computed path that can be retrieved (the number of nodes actually retrieved at each iteration is limited by \"Rtabmap/MaxRetrieved\").");
RTABMAP_PARAM(RGBD, PlanWithNearNodesLinked, bool, true, "Before planning in the graph, near nodes are linked together (even if they don't belong to same map). Radius is defined by \"RGBD/GoalReachedRadius\" parameter."); RTABMAP_PARAM(RGBD, PlanWithNearNodesLinked, bool, true, "Before planning in the graph, near nodes are linked together (even if they don't belong to same map). Radius is defined by \"RGBD/GoalReachedRadius\" parameter.");
RTABMAP_PARAM(RGBD, GoalMaxDistance, float, 0, "Maximum distance (m) of the target goal from the graph (0 means infinity). If the goal is too far from the graph, the plan is aborted. Also when set, the next goal in the graph can't be farther than this distance from the current position.");
// Local loop closure detection // Local loop closure detection
RTABMAP_PARAM(RGBD, LocalLoopDetectionTime, bool, false, "Detection over all locations in STM."); RTABMAP_PARAM(RGBD, LocalLoopDetectionTime, bool, false, "Detection over all locations in STM.");
+2
View File
@@ -93,6 +93,7 @@ public:
Transform getMapCorrection() const {return _mapCorrection;} Transform getMapCorrection() const {return _mapCorrection;}
const Memory * getMemory() const {return _memory;} const Memory * getMemory() const {return _memory;}
float getGoalReachedRadius() const {return _goalReachedRadius;} float getGoalReachedRadius() const {return _goalReachedRadius;}
float getGoalMaxDistance() const {return _goalMaxDistance;}
float getTimeThreshold() const {return _maxTimeAllowed;} // in ms float getTimeThreshold() const {return _maxTimeAllowed;} // in ms
void setTimeThreshold(float maxTimeAllowed); // in ms void setTimeThreshold(float maxTimeAllowed); // in ms
@@ -183,6 +184,7 @@ private:
float _goalReachedRadius; // meters float _goalReachedRadius; // meters
unsigned int _maxAnticipatedNodes; unsigned int _maxAnticipatedNodes;
bool _planWithNearNodesLinked; bool _planWithNearNodesLinked;
float _goalMaxDistance;
std::pair<int, float> _loopClosureHypothesis; std::pair<int, float> _loopClosureHypothesis;
std::pair<int, float> _highestHypothesis; std::pair<int, float> _highestHypothesis;
+56 -20
View File
@@ -673,7 +673,7 @@ public:
rtabmap::Transform pose() const {return pose_;} rtabmap::Transform pose() const {return pose_;}
float distFrom(const rtabmap::Transform & pose) const float distFrom(const rtabmap::Transform & pose) const
{ {
return pose_.getDistance(pose); return pose_.getDistanceSquared(pose); // use sqrt distance
} }
void setClosed(bool closed) {closed_ = closed;} void setClosed(bool closed) {closed_ = closed;}
@@ -703,7 +703,8 @@ std::list<std::pair<int, Transform> > computePath(
const std::map<int, rtabmap::Transform> & poses, const std::map<int, rtabmap::Transform> & poses,
const std::multimap<int, int> & links, const std::multimap<int, int> & links,
int from, int from,
int to) int to,
bool updateNewCosts)
{ {
std::list<std::pair<int, Transform> > path; std::list<std::pair<int, Transform> > path;
@@ -714,28 +715,46 @@ std::list<std::pair<int, Transform> > computePath(
std::map<int, Node> nodes; std::map<int, Node> nodes;
nodes.insert(std::make_pair(startNode, Node(startNode, 0, poses.at(startNode)))); nodes.insert(std::make_pair(startNode, Node(startNode, 0, poses.at(startNode))));
std::priority_queue<Pair, std::vector<Pair>, Order> pq; std::priority_queue<Pair, std::vector<Pair>, Order> pq;
pq.push(Pair(startNode, 0)); std::multimap<float, int> pqmap;
if(updateNewCosts)
while(pq.size())
{ {
Node & currentNode = nodes.find(pq.top().first)->second; pqmap.insert(std::make_pair(0, startNode));
pq.pop(); }
currentNode.setClosed(true); else
{
pq.push(Pair(startNode, 0));
}
if(currentNode.id() == endNode) while((updateNewCosts && pqmap.size()) || (!updateNewCosts && pq.size()))
{
Node * currentNode;
if(updateNewCosts)
{ {
while(currentNode.id()!=startNode) currentNode = &nodes.find(pqmap.begin()->second)->second;
pqmap.erase(pqmap.begin());
}
else
{
currentNode = &nodes.find(pq.top().first)->second;
pq.pop();
}
currentNode->setClosed(true);
if(currentNode->id() == endNode)
{
while(currentNode->id()!=startNode)
{ {
path.push_front(std::make_pair(currentNode.id(), currentNode.pose())); path.push_front(std::make_pair(currentNode->id(), currentNode->pose()));
currentNode = nodes.find(currentNode.fromId())->second; currentNode = &nodes.find(currentNode->fromId())->second;
} }
path.push_front(std::make_pair(startNode, poses.at(startNode))); path.push_front(std::make_pair(startNode, poses.at(startNode)));
break; break;
} }
// lookup neighbors // lookup neighbors
for(std::multimap<int, int>::const_iterator iter = links.find(currentNode.id()); for(std::multimap<int, int>::const_iterator iter = links.find(currentNode->id());
iter!=links.end() && iter->first == currentNode.id(); iter!=links.end() && iter->first == currentNode->id();
++iter) ++iter)
{ {
std::map<int, Node>::iterator nodeIter = nodes.find(iter->second); std::map<int, Node>::iterator nodeIter = nodes.find(iter->second);
@@ -743,18 +762,35 @@ std::list<std::pair<int, Transform> > computePath(
{ {
std::map<int, rtabmap::Transform>::const_iterator poseIter = poses.find(iter->second); std::map<int, rtabmap::Transform>::const_iterator poseIter = poses.find(iter->second);
UASSERT(poseIter != poses.end()); UASSERT(poseIter != poses.end());
Node n(iter->second, currentNode.id(), poseIter->second); Node n(iter->second, currentNode->id(), poseIter->second);
n.setCostSoFar(currentNode.costSoFar() + currentNode.distFrom(poseIter->second)); n.setCostSoFar(currentNode->costSoFar() + currentNode->distFrom(poseIter->second));
n.setDistToEnd(n.distFrom(endPose)); n.setDistToEnd(n.distFrom(endPose));
nodes.insert(std::make_pair(iter->second, n)); nodes.insert(std::make_pair(iter->second, n));
pq.push(Pair(n.id(), n.totalCost())); if(updateNewCosts)
{
pqmap.insert(std::make_pair(n.totalCost(), n.id()));
}
else
{
pq.push(Pair(n.id(), n.totalCost()));
}
} }
else if(nodeIter->second.isOpened()) else if(updateNewCosts && nodeIter->second.isOpened())
{ {
float newCostSoFar = currentNode.costSoFar() + currentNode.distFrom(nodeIter->second.pose()); float newCostSoFar = currentNode->costSoFar() + currentNode->distFrom(nodeIter->second.pose());
if(nodeIter->second.costSoFar() > newCostSoFar) if(nodeIter->second.costSoFar() > newCostSoFar)
{ {
UWARN("newCostSoFar > previous cost (%f vs %f)", newCostSoFar, nodeIter->second.costSoFar()); // update the cost in the priority queue
for(std::map<float, int>::iterator mapIter=pqmap.begin(); mapIter!=pqmap.end(); ++mapIter)
{
if(mapIter->second == nodeIter->first)
{
pqmap.erase(mapIter);
nodeIter->second.setCostSoFar(newCostSoFar);
pqmap.insert(std::make_pair(nodeIter->second.totalCost(), nodeIter->first));
break;
}
}
} }
} }
} }
+32 -14
View File
@@ -110,6 +110,7 @@ Rtabmap::Rtabmap() :
_goalReachedRadius(Parameters::defaultRGBDGoalReachedRadius()), _goalReachedRadius(Parameters::defaultRGBDGoalReachedRadius()),
_maxAnticipatedNodes(Parameters::defaultRGBDMaxAnticipatedNodes()), _maxAnticipatedNodes(Parameters::defaultRGBDMaxAnticipatedNodes()),
_planWithNearNodesLinked(Parameters::defaultRGBDPlanWithNearNodesLinked()), _planWithNearNodesLinked(Parameters::defaultRGBDPlanWithNearNodesLinked()),
_goalMaxDistance(Parameters::defaultRGBDGoalMaxDistance()),
_loopClosureHypothesis(0,0.0f), _loopClosureHypothesis(0,0.0f),
_highestHypothesis(0,0.0f), _highestHypothesis(0,0.0f),
_lastProcessTime(0.0), _lastProcessTime(0.0),
@@ -376,7 +377,7 @@ void Rtabmap::parseParameters(const ParametersMap & parameters)
Parameters::parse(parameters, Parameters::kRGBDGoalReachedRadius(), _goalReachedRadius); Parameters::parse(parameters, Parameters::kRGBDGoalReachedRadius(), _goalReachedRadius);
Parameters::parse(parameters, Parameters::kRGBDMaxAnticipatedNodes(), _maxAnticipatedNodes); Parameters::parse(parameters, Parameters::kRGBDMaxAnticipatedNodes(), _maxAnticipatedNodes);
Parameters::parse(parameters, Parameters::kRGBDPlanWithNearNodesLinked(), _planWithNearNodesLinked); Parameters::parse(parameters, Parameters::kRGBDPlanWithNearNodesLinked(), _planWithNearNodesLinked);
Parameters::parse(parameters, Parameters::kRGBDGoalMaxDistance(), _goalMaxDistance);
// RGB-D SLAM stuff // RGB-D SLAM stuff
if((iter=parameters.find(Parameters::kLccIcpType())) != parameters.end()) if((iter=parameters.find(Parameters::kLccIcpType())) != parameters.end())
@@ -1518,7 +1519,10 @@ bool Rtabmap::process(const SensorData & data)
uContains(_optimizedPoses, _path[_pathCurrentIndex].first)) uContains(_optimizedPoses, _path[_pathCurrentIndex].first))
{ {
Transform virtualLoop = _optimizedPoses.at(signature->id()).inverse() * _optimizedPoses.at(_path[_pathCurrentIndex].first); Transform virtualLoop = _optimizedPoses.at(signature->id()).inverse() * _optimizedPoses.at(_path[_pathCurrentIndex].first);
_memory->addLink(_path[_pathCurrentIndex].first, signature->id(), virtualLoop, Link::kVirtualClosure, 99999); if(_localDetectRadius > 0.0f && virtualLoop.getNorm() < _localDetectRadius)
{
_memory->addLink(_path[_pathCurrentIndex].first, signature->id(), virtualLoop, Link::kVirtualClosure, 99999);
}
} }
// Make sure the next signatures on the path are linked together // Make sure the next signatures on the path are linked together
@@ -2047,9 +2051,9 @@ void Rtabmap::optimizeCurrentMap(
UDEBUG("Optimize map: around location %d", id); UDEBUG("Optimize map: around location %d", id);
if(_memory && id > 0) if(_memory && id > 0)
{ {
UTimer timer;
std::map<int, int> ids = _memory->getNeighborsId(id, 0, lookInDatabase?-1:0, true); std::map<int, int> ids = _memory->getNeighborsId(id, 0, lookInDatabase?-1:0, true);
UDEBUG("ids=%d", (int)ids.size()); UDEBUG("get ids=%d", (int)ids.size());
if(!_optimizeFromGraphEnd && ids.size() > 1) if(!_optimizeFromGraphEnd && ids.size() > 1)
{ {
UTimer timer; UTimer timer;
@@ -2063,11 +2067,13 @@ void Rtabmap::optimizeCurrentMap(
id, id,
timer.ticks()); timer.ticks());
} }
UINFO("get ids time %f s", timer.ticks());
std::map<int, Transform> poses; std::map<int, Transform> poses;
std::multimap<int, Link> edgeConstraints; std::multimap<int, Link> edgeConstraints;
_memory->getMetricConstraints(uKeys(ids), poses, edgeConstraints, lookInDatabase); _memory->getMetricConstraints(uKeys(ids), poses, edgeConstraints, lookInDatabase);
UDEBUG("poses=%d, edgeConstraints=%d", (int)poses.size(), (int)edgeConstraints.size()); UDEBUG("poses=%d, edgeConstraints=%d", (int)poses.size(), (int)edgeConstraints.size());
UINFO("get constraints time %f s", timer.ticks());
if(constraints) if(constraints)
{ {
@@ -2083,6 +2089,7 @@ void Rtabmap::optimizeCurrentMap(
{ {
rtabmap::graph::optimizeTOROGraph(ids, poses, edgeConstraints, optimizedPoses, _toroIterations, true, _toroIgnoreVariance); rtabmap::graph::optimizeTOROGraph(ids, poses, edgeConstraints, optimizedPoses, _toroIterations, true, _toroIgnoreVariance);
} }
UINFO("optimize time %f s", timer.ticks());
} }
} }
@@ -2350,7 +2357,9 @@ bool Rtabmap::computePath(
} }
UINFO("Computing path from location %d to %d", currentNode, targetNode); UINFO("Computing path from location %d to %d", currentNode, targetNode);
UTimer timer;
_path = uListToVector(rtabmap::graph::computePath(nodes, links, currentNode, targetNode)); _path = uListToVector(rtabmap::graph::computePath(nodes, links, currentNode, targetNode));
UINFO("A* time = %fs", timer.ticks());
if(_path.size() == 0) if(_path.size() == 0)
{ {
@@ -2428,15 +2437,23 @@ bool Rtabmap::computePath(const Transform & targetPose, bool global)
UINFO("Nearest node found=%d ,%fs", nearestId, timer.ticks()); UINFO("Nearest node found=%d ,%fs", nearestId, timer.ticks());
if(nearestId > 0) if(nearestId > 0)
{ {
if(computePath(nearestId, nodes, constraints)) if(_goalMaxDistance != 0.0f && targetPose.getDistance(nodes.at(nearestId)) > _goalMaxDistance)
{ {
UASSERT(_path.size() > 0); UWARN("Cannot plan farther than %f m from the graph! (distance=%f m from node %d)",
UASSERT(uContains(nodes, _path.back().first)); _goalMaxDistance, targetPose.getDistance(nodes.at(nearestId)), nearestId);
_pathTransformToGoal = nodes.at(_path.back().first).inverse() * targetPose; }
else
{
if(computePath(nearestId, nodes, constraints))
{
UASSERT(_path.size() > 0);
UASSERT(uContains(nodes, _path.back().first));
_pathTransformToGoal = nodes.at(_path.back().first).inverse() * targetPose;
updateGoalIndex(); updateGoalIndex();
}
UINFO("Time computing path = %fs", timer.ticks());
} }
UINFO("Time computing path = %fs", timer.ticks());
} }
else else
{ {
@@ -2538,11 +2555,12 @@ void Rtabmap::updateGoalIndex()
if(_path.size()) if(_path.size())
{ {
//Always check if the farthest node is accessible in local map //Always check if the farthest node is accessible in local map (max to local space radius if set)
int goalIndex = 0; int goalIndex = _pathGoalIndex;
for(int i=(int)_path.size()-1; i>=0; --i) for(int i=(int)_path.size()-1; i>=goalIndex; --i)
{ {
if(uContains(_optimizedPoses, _path[i].first)) if(uContains(_optimizedPoses, _path[i].first) &&
(_goalMaxDistance == 0.0f || _optimizedPoses.at(_memory->getLastWorkingSignature()->id()).getDistance(_optimizedPoses.at(_path[i].first)) < _goalMaxDistance))
{ {
goalIndex = i; goalIndex = i;
break; break;
+1
View File
@@ -453,6 +453,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
_ui->graphPlan_goalReachedRadius->setObjectName(Parameters::kRGBDGoalReachedRadius().c_str()); _ui->graphPlan_goalReachedRadius->setObjectName(Parameters::kRGBDGoalReachedRadius().c_str());
_ui->graphPlan_maxAnticipatedNodes->setObjectName(Parameters::kRGBDMaxAnticipatedNodes().c_str()); _ui->graphPlan_maxAnticipatedNodes->setObjectName(Parameters::kRGBDMaxAnticipatedNodes().c_str());
_ui->graphPlan_planWithNearNodesLinked->setObjectName(Parameters::kRGBDPlanWithNearNodesLinked().c_str()); _ui->graphPlan_planWithNearNodesLinked->setObjectName(Parameters::kRGBDPlanWithNearNodesLinked().c_str());
_ui->graphPlan_goalMaxDistance->setObjectName(Parameters::kRGBDGoalMaxDistance().c_str());
_ui->groupBox_localDetection_time->setObjectName(Parameters::kRGBDLocalLoopDetectionTime().c_str()); _ui->groupBox_localDetection_time->setObjectName(Parameters::kRGBDLocalLoopDetectionTime().c_str());
_ui->groupBox_localDetection_space->setObjectName(Parameters::kRGBDLocalLoopDetectionSpace().c_str()); _ui->groupBox_localDetection_space->setObjectName(Parameters::kRGBDLocalLoopDetectionSpace().c_str());
+28 -5
View File
@@ -63,9 +63,9 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>-733</y>
<width>744</width> <width>744</width>
<height>1056</height> <height>1475</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_16"> <layout class="QVBoxLayout" name="verticalLayout_16">
@@ -86,7 +86,7 @@
<enum>QFrame::Raised</enum> <enum>QFrame::Raised</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>7</number> <number>19</number>
</property> </property>
<widget class="QWidget" name="page_22"> <widget class="QWidget" name="page_22">
<layout class="QVBoxLayout" name="verticalLayout_29"> <layout class="QVBoxLayout" name="verticalLayout_29">
@@ -5332,14 +5332,14 @@ Warning when set to false: when some nodes are transferred, the first referentia
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="3" column="0">
<widget class="QCheckBox" name="graphPlan_planWithNearNodesLinked"> <widget class="QCheckBox" name="graphPlan_planWithNearNodesLinked">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="3" column="1">
<widget class="QLabel" name="label_space3_4"> <widget class="QLabel" name="label_space3_4">
<property name="text"> <property name="text">
<string>Before planning in the graph, near nodes are linked together (even if they don't belong to same map). Radius is defined by &quot;Goal reached radius&quot; above.</string> <string>Before planning in the graph, near nodes are linked together (even if they don't belong to same map). Radius is defined by &quot;Goal reached radius&quot; above.</string>
@@ -5349,6 +5349,29 @@ Warning when set to false: when some nodes are transferred, the first referentia
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1">
<widget class="QLabel" name="label_space3_5">
<property name="text">
<string>Maximum distance (m) of the target goal from the graph (0 means infinity). If the goal is too far from the graph, the plan is aborted. Also when set, the next goal in the graph can't be farther than this distance from the current position.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QDoubleSpinBox" name="graphPlan_goalMaxDistance">
<property name="suffix">
<string> m</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>