00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <pose_graph/pose_graph_impl.h>
00034 #include <pose_graph/exception.h>
00035 #include <pose_graph/utils.h>
00036 #include <pose_graph/transforms.h>
00037 #include <boost/tuple/tuple.hpp>
00038 #include <boost/foreach.hpp>
00039 #include <boost/bind.hpp>
00040 #include <boost/ref.hpp>
00041 #include <boost/property_map/property_map.hpp>
00042 #include <boost/graph/dijkstra_shortest_paths.hpp>
00043 #include <boost/lexical_cast.hpp>
00044 #include <ros/assert.h>
00045 #include <ros/console.h>
00046 #include <list>
00047 #include <boost/optional.hpp>
00048
00049 namespace pose_graph
00050 {
00051
00052 using boost::tie;
00053 using boost::bind;
00054 using boost::ref;
00055 using boost::optional;
00056 using boost::associative_property_map;
00057 using std::pair;
00058 using std::map;
00059 using std::list;
00060 using std::string;
00061 using geometry_msgs::Pose;
00062 using sensor_msgs::LaserScan;
00063
00064 typedef set<EdgeId> EdgeIdSet;
00065 typedef set<NodeId> NodeIdSet;
00066 typedef PoseGraphAdjacencyList::out_edge_iterator OutEdgeIter;
00067 typedef PoseGraphAdjacencyList::in_edge_iterator InEdgeIter;
00068 typedef PoseGraphAdjacencyList::vertex_iterator VertexIter;
00069 typedef pair<NodeId, NodeId> IncidentNodes;
00070 using occupancy_grid_utils::LocalizedCloud;
00071
00072
00073
00074
00075
00076
00077
00078
00079 bool PoseGraphImpl::nodeIdExists (const NodeId id) const
00080 {
00081 return contains(vertex_map_, id);
00082 }
00083
00084 bool PoseGraphImpl::edgeIdExists (const EdgeId id) const
00085 {
00086 return contains(edge_map_, id);
00087 }
00088
00089 PoseGraphVertex PoseGraphImpl::idVertex (const NodeId id) const
00090 {
00091 if (!nodeIdExists(id))
00092 throw UnknownNodeIdException(id);
00093 else
00094 return vertex_map_.find(id)->second;
00095 }
00096
00097 PoseGraphEdge PoseGraphImpl::idEdge (const EdgeId id) const
00098 {
00099 if (!edgeIdExists(id))
00100 throw UnknownEdgeIdException(id);
00101 else
00102 return edge_map_.find(id)->second;
00103 }
00104
00105
00106 NodeId vertexId (const PoseGraphAdjacencyList& graph, const PoseGraphVertex& v)
00107 {
00108 return graph[v].id;
00109 }
00110
00111 EdgeId edgeId (const PoseGraphAdjacencyList& graph, const PoseGraphEdge& e)
00112 {
00113 return graph[e].id;
00114 }
00115
00116
00117
00118 template <class K, class V>
00119 K getKey (const pair<K, V> entry)
00120 {
00121 return entry.first;
00122 }
00123
00124
00125
00126 NodeId PoseGraphImpl::otherNode (const NodeId n, const EdgeId e) const
00127 {
00128 IncidentNodes nodes = incidentNodes(e);
00129 if (nodes.first == n)
00130 return nodes.second;
00131 else if (nodes.second == n)
00132 return nodes.first;
00133 else
00134 ROS_ASSERT_MSG(false, "Code assumption violated: neither node %lu or %lu of %lu equals %lu",
00135 nodes.first.getId(), nodes.second.getId(), e.getId(), n.getId());
00136 return NodeId(-1);
00137 }
00138
00139
00140
00141
00142
00143
00144 PoseGraphImpl::PoseGraphImpl () : next_node_id_(1), next_edge_id_(1)
00145 {
00146 }
00147
00148
00149 PoseGraphImpl::PoseGraphImpl (const PoseGraphImpl& g) : next_node_id_(1), next_edge_id_(1)
00150 {
00151 initializeFrom(g);
00152 }
00153
00154 PoseGraphImpl& PoseGraphImpl::operator= (const PoseGraphImpl& g)
00155 {
00156 if (this!=&g)
00157 initializeFrom(g);
00158 return *this;
00159 }
00160
00161
00162 void PoseGraphImpl::initializeFrom (const PoseGraphImpl& g)
00163 {
00165 graph_.clear();
00166 next_node_id_ = NodeId(1);
00167 next_edge_id_ = EdgeId(1);
00168 vertex_map_.clear();
00169 edge_map_.clear();
00170 constraints_.clear();
00171 clouds_.clear();
00172 scans_.clear();
00173
00174 ROS_ASSERT_MSG (allNodes().empty() && allEdges().empty(),
00175 "Can't assign to a nonempty PoseGraph");
00176
00177 const NodeIdSet nodes = g.allNodes();
00178 BOOST_FOREACH (const NodeId n, nodes) {
00179 addNode(n);
00180 setInitialPoseEstimate(n, g.getInitialPoseEstimate(n));
00181 }
00182
00183 BOOST_FOREACH (const NodeId n, nodes) {
00184 BOOST_FOREACH (const EdgeId e, g.incidentEdges(n)) {
00185 IncidentNodes incident_nodes = g.incidentNodes(e);
00186 if (n==incident_nodes.first)
00187 addEdge(n, incident_nodes.second, g.getConstraint(e), e);
00188 }
00189
00190 if (g.hasCloud(n))
00191 attachCloud(n, g.getCloud(n));
00192 if (g.hasScan(n))
00193 attachScan(n, g.getScan(n));
00194 }
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 NodeId PoseGraphImpl::addNode ()
00211 {
00212 while (nodeIdExists(next_node_id_))
00213 next_node_id_++;
00214
00215 addNode(next_node_id_);
00216 return next_node_id_;
00217 }
00218
00219
00220 void PoseGraphImpl::addNode (const NodeId id)
00221 {
00222 ROS_DEBUG_STREAM_NAMED ("add_node", "Adding node " << id);
00223 if (nodeIdExists(id))
00224 throw DuplicateNodeIdException(id);
00225 else
00226 vertex_map_[id] = add_vertex(NodeInfo(id), graph_);
00227 }
00228
00229
00230 void PoseGraphImpl::setInitialPoseEstimate (const NodeId n, const Pose& pose)
00231 {
00232 graph_[idVertex(n)].initial_pose_estimate = pose;
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242 EdgeId PoseGraphImpl::addEdge (const NodeId from, const NodeId to, const PoseConstraint& constraint)
00243 {
00244 while (edgeIdExists(next_edge_id_))
00245 next_edge_id_++;
00246 addEdge(from, to, constraint, next_edge_id_);
00247 return next_edge_id_;
00248 }
00249
00250
00251
00252 void PoseGraphImpl::addEdge (const NodeId from, const NodeId to, const PoseConstraint& constraint, const EdgeId id)
00253 {
00254 ROS_DEBUG_STREAM_NAMED ("add_edge", "Adding edge " << id << " from " << from << " to " << to);
00255
00256 const PoseGraphVertex from_vertex = idVertex(from);
00257 const PoseGraphVertex to_vertex = idVertex(to);
00258
00259 pair<PoseGraphEdge, bool> result = add_edge(from_vertex, to_vertex,
00260 EdgeInfo(id, from, to, length(constraint)), graph_);
00261 ROS_ASSERT(result.second);
00262 edge_map_[id] = result.first;
00263 constraints_[id] = constraint;
00264 }
00265
00266 EdgeInfo::EdgeInfo(const EdgeId id, const NodeId from, const NodeId to, const double length) :
00267 id(id), from(from), to(to), length(length)
00268 {
00269 }
00270
00271
00272 EdgeInfo::EdgeInfo() : id(-1), from(-1), to(-1), length(-1.0)
00273 {}
00274
00275
00276
00277
00278
00279
00280
00281
00282 NodeIdSet PoseGraphImpl::allNodes () const
00283 {
00284 NodeIdSet nodes;
00285 transform (vertex_map_.begin(), vertex_map_.end(), inserter(nodes, nodes.begin()), &getKey<NodeId, PoseGraphVertex>);
00286 return nodes;
00287 }
00288
00289
00290
00291 EdgeIdSet PoseGraphImpl::allEdges () const
00292 {
00293 EdgeIdSet edges;
00294 transform (edge_map_.begin(), edge_map_.end(), inserter(edges, edges.begin()), &getKey<EdgeId, PoseGraphEdge>);
00295 return edges;
00296 }
00297
00298
00299
00300 IncidentNodes PoseGraphImpl::incidentNodes (const EdgeId e) const
00301 {
00302 PoseGraphEdge edge = idEdge(e);
00303 return IncidentNodes(graph_[source(edge, graph_)].id, graph_[target(edge, graph_)].id);
00304 }
00305
00306
00307
00308 EdgeIdSet PoseGraphImpl::incidentEdges (const NodeId n) const
00309 {
00310 EdgeIdSet ids;
00311 PoseGraphVertex v = idVertex(n);
00312
00313 OutEdgeIter out_iter, out_end;
00314 tie(out_iter, out_end) = out_edges(v, graph_);
00315 transform(out_iter, out_end, inserter(ids, ids.begin()), bind(edgeId, ref(graph_), _1));
00316
00317 return ids;
00318 }
00319
00321 NodeIdSet PoseGraphImpl::neighbors (const NodeId n) const
00322 {
00323 NodeIdSet neighbors;
00324 BOOST_FOREACH (const EdgeId e, incidentEdges(n))
00325 neighbors.insert(otherNode(n, e));
00326 return neighbors;
00327 }
00328
00329
00330
00331 const PoseConstraint& PoseGraphImpl::getConstraint (const EdgeId e) const
00332 {
00333 if (edgeIdExists(e)) {
00334 return keyValue(constraints_, e);
00335 }
00336 else
00337 throw UnknownEdgeIdException(e);
00338 }
00339
00340
00341
00342 const Pose& PoseGraphImpl::getInitialPoseEstimate (const NodeId n) const
00343 {
00344 return graph_[idVertex(n)].initial_pose_estimate;
00345 }
00346
00347
00348
00349 double PoseGraphImpl::edgeLength (const EdgeId id) const
00350 {
00351 return graph_[idEdge(id)].length;
00352 }
00353
00354 Pose addRelativePose (const PoseGraphImpl* g, const Pose& pose, const EdgeId e)
00355 {
00356
00357 return Pose();
00358 }
00359
00360
00361 Pose PoseGraphImpl::relativePose (const NodeId n, const NodeId ref) const
00362 {
00363 ShortestPathResult path = shortestPath(ref, n);
00364 if (!path.path_found)
00365 throw DisconnectedNodesException(ref, n);
00366
00367 Eigen3::Affine3d trans;
00368 trans = Eigen3::AngleAxis<double>(0, Eigen3::Vector3d(0, 0, 1));
00369
00370 for (unsigned i=0; i<path.edges.size(); i++) {
00371 const EdgeId e = path.edges[i];
00372 const Eigen3::Affine3d rel_trans = poseToWorldTransform(getPose(getConstraint(e)));
00373 const NodeId from = incidentNodes(e).first;
00374 const NodeId to = incidentNodes(e).second;
00375 if (from == path.nodes[i]) {
00376 ROS_ASSERT (to == path.nodes[i+1]);
00377 trans = trans*rel_trans;
00378 }
00379 else {
00380 ROS_ASSERT (to == path.nodes[i]);
00381 trans = trans*rel_trans.inverse();
00382 }
00383 }
00384 return convertToPose(trans);
00385
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 PoseGraphImpl::DijkstraResult PoseGraphImpl::dijkstra (const PoseGraphVertex& src) const
00398 {
00399
00400 typedef map<PoseGraphEdge, double> WeightMap;
00401 typedef map<PoseGraphVertex, unsigned> IndexMap;
00402
00403
00404 typedef associative_property_map<DistanceMap> DistancePMap;
00405 typedef associative_property_map<PredecessorMap> PredecessorPMap;
00406 typedef associative_property_map<WeightMap> WeightPMap;
00407 typedef associative_property_map<IndexMap> IndexPMap;
00408
00409
00410 IndexMap imap;
00411 IndexPMap index_pmap(imap);
00412 {
00413 unsigned ind=0;
00414 BOOST_FOREACH (const NodeId id, allNodes())
00415 imap[idVertex(id)] = ind++;
00416 }
00417
00418
00419 WeightMap wmap;
00420 WeightPMap weight_pmap(wmap);
00421 BOOST_FOREACH (const EdgeId id, allEdges())
00422 wmap[idEdge(id)] = edgeLength(id);
00423
00424
00425 DistanceMap dmap;
00426 DistancePMap distance_pmap(dmap);
00427 PredecessorMap pmap;
00428 PredecessorPMap predecessor_pmap(pmap);
00429
00430
00431 boost::dijkstra_shortest_paths(graph_, src, weight_map(weight_pmap).vertex_index_map(index_pmap).
00432 distance_map(distance_pmap).predecessor_map(predecessor_pmap));
00433
00434
00435 return DijkstraResult(dmap, pmap);
00436 }
00437
00438
00439 EdgeId PoseGraphImpl::shortestEdgeBetween (const NodeId n1, const NodeId n2) const
00440 {
00441 optional<EdgeId> shortest;
00442 optional<double> length;
00443 const PoseGraphVertex node = idVertex(n1);
00444 BOOST_FOREACH (const PoseGraphEdge& e, out_edges(node, graph_)) {
00445 const EdgeId id = graph_[e].id;
00446 if (otherNode(n1, id) == n2 &&
00447 (!length || *length > edgeLength(id))) {
00448 shortest = id;
00449 length = edgeLength(id);
00450 }
00451 }
00452 ROS_ASSERT (shortest && length);
00453 return *shortest;
00454 }
00455
00456
00457 ShortestPathResult PoseGraphImpl::shortestPath(const NodeId src, const NodeId dest) const
00458 {
00459
00460 const PoseGraphVertex v = idVertex(src);
00461 const PoseGraphVertex w = idVertex(dest);
00462 DijkstraResult result = dijkstra(v);
00463 ROS_ASSERT_MSG (contains(result.first, w), "%lu not found in shortest path distances from %lu",
00464 dest.getId(), src.getId());
00465
00466
00467 if (dest==src || result.second[w] !=w) {
00468
00469 list<NodeId> path;
00470 for (PoseGraphVertex x = w; x!=result.second[x]; x=result.second[x])
00471 path.push_front(vertexId(graph_, x));
00472 path.push_front(src);
00473
00474
00475 ShortestPathResult ret_val;
00476 copy(path.begin(), path.end(), back_inserter(ret_val.nodes));
00477 ROS_ASSERT (path.begin()!=path.end());
00478 transform(path.begin(), --path.end(), ++path.begin(), back_inserter(ret_val.edges),
00479 bind(&PoseGraphImpl::shortestEdgeBetween, this, _1, _2));
00480 ret_val.path_found = true;
00481 ret_val.cost = result.first[w];
00482 return ret_val;
00483 }
00484
00485 else {
00486 ShortestPathResult ret_val;
00487 ret_val.path_found = false;
00488 return ret_val;
00489 }
00490 }
00491
00492
00493 bool PoseGraphImpl::outsideRadius (NodeId n, double r, const PoseGraphImpl::DistanceMap& distances) const
00494 {
00495 return keyValue(distances, idVertex(n)) > r;
00496 }
00497
00498
00499
00500 NodeIdSet PoseGraphImpl::nearbyNodes (const NodeId src, const double radius) const
00501 {
00502
00503 const PoseGraphVertex v = idVertex(src);
00504 const DijkstraResult result = dijkstra(v);
00505
00506
00507 const NodeIdSet nodes = allNodes();
00508 NodeIdSet nearby_nodes;
00509 remove_copy_if(nodes.begin(), nodes.end(), inserter(nearby_nodes, nearby_nodes.begin()), bind(&PoseGraphImpl::outsideRadius, this, _1, radius, ref(result.first)));
00510 return nearby_nodes;
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 void PoseGraphImpl::attachCloud (const NodeId id, LocalizedCloud::ConstPtr cloud)
00522 {
00523 const PoseGraphVertex v = idVertex(id);
00524 clouds_[v] = cloud;
00525 }
00526
00527
00528 LocalizedCloud::ConstPtr PoseGraphImpl::getCloud (const NodeId id) const
00529 {
00530
00531 const PoseGraphVertex v = idVertex(id);
00532 if (contains(clouds_, v))
00533 return keyValue(clouds_, v);
00534 else
00535 throw PoseGraphException (boost::format("No cloud found for node %1%") % id );
00536 }
00537
00538 bool PoseGraphImpl::hasCloud (const NodeId id) const
00539 {
00540 const PoseGraphVertex v = idVertex(id);
00541 return contains(clouds_, v);
00542 }
00543
00544 PoseGraph PoseGraphImpl::subgraph (const set<NodeId>& nodes) const
00545 {
00546
00547 PoseGraph g;
00548 BOOST_FOREACH (const NodeId n, nodes)
00549 g.addNode(n);
00550
00551
00552 BOOST_FOREACH (const NodeId n, nodes) {
00553 BOOST_FOREACH (const EdgeId e, incidentEdges(n)) {
00554 if (g.nodeIdExists(otherNode(n, e)) &&
00555 !g.edgeIdExists(e)) {
00556 const IncidentNodes nodes=incidentNodes(e);
00557 g.addEdge(nodes.first, nodes.second, getConstraint(e), e);
00558 }
00559 }
00560 }
00561 return g;
00562 }
00563
00564
00565
00566
00567
00568
00569 void PoseGraphImpl::attachScan (const NodeId id, LaserScan::ConstPtr scan)
00570 {
00571 const PoseGraphVertex v = idVertex(id);
00572 scans_[v] = scan;
00573 }
00574
00575
00576 LaserScan::ConstPtr PoseGraphImpl::getScan (const NodeId id) const
00577 {
00578 const PoseGraphVertex v = idVertex(id);
00579 if (contains(scans_, v))
00580 return keyValue(scans_, v);
00581 else
00582 throw PoseGraphException (boost::format("No scan found for node %1%") % id );
00583 }
00584
00585 bool PoseGraphImpl::hasScan (const NodeId id) const
00586 {
00587 const PoseGraphVertex v = idVertex(id);
00588 return contains(scans_, v);
00589 }
00590
00591
00592
00593
00594
00595
00596
00597 PoseGraph::~PoseGraph() {}
00598
00599 PoseGraph::PoseGraph () : impl_(new PoseGraphImpl()) {}
00600
00601 PoseGraph::PoseGraph (const PoseGraph& g) : impl_(new PoseGraphImpl(*g.impl_)) {}
00602
00603 PoseGraph& PoseGraph::operator= (const PoseGraph& g)
00604 {
00605 if (this!=&g)
00606 *impl_ = *(g.impl_);
00607 return *this;
00608 }
00609
00610 NodeId PoseGraph::addNode () { return impl_->addNode(); }
00611
00612 void PoseGraph::addNode (const NodeId id) { impl_->addNode(id); }
00613
00614 EdgeId PoseGraph::addEdge (const NodeId from, const NodeId to, const PoseConstraint& c)
00615 {
00616 return impl_->addEdge (from, to, c);
00617 }
00618
00619 void PoseGraph::addEdge (const NodeId from, const NodeId to, const PoseConstraint& c, const EdgeId e)
00620 {
00621 impl_->addEdge (from, to, c, e);
00622 }
00623
00624
00625 void PoseGraph::setInitialPoseEstimate (const NodeId n, const Pose& pose)
00626 {
00627 impl_->setInitialPoseEstimate(n, pose);
00628 }
00629
00630 const Pose& PoseGraph::getInitialPoseEstimate (const NodeId n) const
00631 {
00632 return impl_->getInitialPoseEstimate(n);
00633 }
00634
00635 set<NodeId> PoseGraph::allNodes () const { return impl_->allNodes(); }
00636
00637 set<EdgeId> PoseGraph::allEdges () const { return impl_->allEdges(); }
00638
00639 const PoseConstraint& PoseGraph::getConstraint (const EdgeId id) const
00640 {
00641 return impl_->getConstraint(id);
00642 }
00643
00644 double PoseGraph::edgeLength (const EdgeId id) const { return impl_->edgeLength(id); }
00645
00646 set<EdgeId> PoseGraph::incidentEdges (const NodeId n) const { return impl_->incidentEdges(n); }
00647
00648 NodeIdSet PoseGraph::neighbors (const NodeId n) const { return impl_->neighbors(n); }
00649
00650 pair<NodeId, NodeId> PoseGraph::incidentNodes (const EdgeId e) const { return impl_->incidentNodes(e); }
00651
00652 bool PoseGraph::nodeIdExists (const NodeId id) const { return impl_->nodeIdExists(id); }
00653
00654 bool PoseGraph::edgeIdExists (const EdgeId id) const { return impl_->edgeIdExists(id); }
00655
00656 PoseGraph PoseGraph::subgraph (const set<NodeId>& nodes) const
00657 { return impl_->subgraph(nodes); }
00658
00659 ShortestPathResult PoseGraph::shortestPath (const NodeId src, const NodeId dest) const
00660 {
00661 return impl_->shortestPath (src, dest);
00662 }
00663
00664 set<NodeId> PoseGraph::nearbyNodes (const NodeId src, const double radius) const
00665 {
00666 return impl_->nearbyNodes (src, radius);
00667 }
00668
00669 void PoseGraph::attachCloud (const NodeId id, LocalizedCloud::ConstPtr cloud)
00670 {
00671 impl_->attachCloud(id, cloud);
00672 }
00673
00674 LocalizedCloud::ConstPtr PoseGraph::getCloud (const NodeId id) const
00675 {
00676 return impl_->getCloud(id);
00677 }
00678
00679 bool PoseGraph::hasCloud (const NodeId id) const
00680 {
00681 return impl_->hasCloud (id);
00682 }
00683
00684 void PoseGraph::attachScan (const NodeId id, LaserScan::ConstPtr scan)
00685 {
00686 impl_->attachScan(id, scan);
00687 }
00688
00689 LaserScan::ConstPtr PoseGraph::getScan (const NodeId id) const
00690 {
00691 return impl_->getScan(id);
00692 }
00693
00694 bool PoseGraph::hasScan (const NodeId id) const
00695 {
00696 return impl_->hasScan(id);
00697 }
00698
00699 string PoseGraph::nodeFrameName (const NodeId id)
00700 {
00701 return string("node") + boost::lexical_cast<string>(id);
00702 }
00703
00704 Pose PoseGraph::relativePose (const NodeId n, const NodeId ref) const
00705 {
00706 return impl_->relativePose(n, ref);
00707 }
00708
00709 NodeId PoseGraph::otherNode (const NodeId n, const EdgeId e) const
00710 {
00711 return impl_->otherNode(n, e);
00712 }
00713
00714 }