pose_graph.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
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  * Internal utilities
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 // Get the key from a map entry
00118 template <class K, class V>
00119 K getKey (const pair<K, V> entry)
00120 {
00121   return entry.first;
00122 }
00123   
00124 
00125 // Return the other node incident to a given edge
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); // Never happens
00137 }
00138 
00139 
00140 /************************************************************
00141  * Creation
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  * Basic graph ops
00202  ************************************************************/
00203 
00204 /****************************************
00205  * Nodes
00206  ****************************************/
00207 
00208 
00209 // Uses next_node_id_ to generate an id, and adds node
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 // Adds a node with fixed id
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 // Sets node initial pose estimate
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  * Edges
00239  ****************************************/
00240 
00241 // Uses next_edge_id_ to generate an id, and adds edge
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 // Adds an edge with fixed id
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 // Only used temporarily by boost graph operations
00272 EdgeInfo::EdgeInfo() : id(-1), from(-1), to(-1), length(-1.0)
00273 {} 
00274 
00275 
00276 /****************************************
00277  * const ops
00278  ****************************************/
00279 
00280 
00281 // Gets set of node ids
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 // Gets set of edge ids
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 // Gets pair of node ids incident to an edge
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 // Gets set of edge ids incident to this node
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 // Get the pose constraint attached to an edge
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 // Initial pose estimate for a node
00342 const Pose& PoseGraphImpl::getInitialPoseEstimate (const NodeId n) const
00343 {
00344   return graph_[idVertex(n)].initial_pose_estimate;
00345 }
00346   
00347 
00348 // Length of an edge
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  * Path planning
00393  ************************************************************/
00394 
00395 
00396 // Internal function that wraps the actual BGL call
00397 PoseGraphImpl::DijkstraResult PoseGraphImpl::dijkstra (const PoseGraphVertex& src) const
00398 {
00399   // Define some additional map types to store the weights and indices used within Dijkstra's algorithm
00400   typedef map<PoseGraphEdge, double> WeightMap;
00401   typedef map<PoseGraphVertex, unsigned> IndexMap;
00402 
00403   // dijkstra_shortest_paths further requires std::map to be wrapped in a "Property Map"
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   // OK, step 1: set the indices arbitrarily, because bgl won't do this for you
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   // Step 2: set the weights, using the edge lengths
00419   WeightMap wmap;
00420   WeightPMap weight_pmap(wmap);
00421   BOOST_FOREACH (const EdgeId id, allEdges())
00422     wmap[idEdge(id)] = edgeLength(id);
00423 
00424   // Step 3: set up output maps
00425   DistanceMap dmap;
00426   DistancePMap distance_pmap(dmap);
00427   PredecessorMap pmap;
00428   PredecessorPMap predecessor_pmap(pmap);
00429 
00430   // Step 4: make the call
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   // Step 5: Return
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 // Finds shortest path using Dijkstra's algorithm
00457 ShortestPathResult PoseGraphImpl::shortestPath(const NodeId src, const NodeId dest) const
00458 {
00459   // Make the call
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   // Extract the path
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     // Fill in the return value; for now we don't fill in the edges field
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 // Uses Dijkstra propagation (over the entire graph, which is inefficient), and selects the nodes within a given radius
00500 NodeIdSet PoseGraphImpl::nearbyNodes (const NodeId src, const double radius) const
00501 {
00502   // Set up the call to Dijkstra's algorithm
00503   const PoseGraphVertex v = idVertex(src);
00504   const DijkstraResult result = dijkstra(v);
00505 
00506   // Get the nodes that are within the radius
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  * Point clouds 
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   // Add the nodes
00547   PoseGraph g;
00548   BOOST_FOREACH (const NodeId n, nodes) 
00549     g.addNode(n);
00550 
00551   // Add the edges
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  * Laser Scans
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  * The interface class just forwards all operations
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 } // namespace pose_graph


pose_graph
Author(s): Bhaskara Marthi
autogenerated on Tue Jan 7 2014 11:17:15