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
00039 #include <pose_graph/exception.h>
00040 #include <graph_mapping_utils/utils.h>
00041 #include <graph_mapping_msgs/msg_utils.h>
00042 #include <boost/foreach.hpp>
00043 #include <pose_graph/constraint_graph.h>
00044
00045 namespace pose_graph
00046 {
00047
00048 namespace util=graph_mapping_utils;
00049 namespace msg=graph_mapping_msgs;
00050
00051 using std::pair;
00052 using std::map;
00053
00054 typedef pair<unsigned, unsigned> IncidentNodes;
00055 typedef map<unsigned, GraphVertex> NodeMap;
00056 typedef map<unsigned, GraphEdge> EdgeMap;
00057
00058
00059
00060
00061
00062 ConstraintGraph::ConstraintGraph () :
00063 next_node_id_(1), next_edge_id_(1)
00064 {}
00065
00066 ConstraintGraph::~ConstraintGraph ()
00067 {}
00068
00069 ConstraintGraph::ConstraintGraph (const ConstraintGraph& other)
00070 {
00071 ROS_DEBUG_STREAM_NAMED ("copy", "Copy constructing constraint graph");
00072 initializeFrom(other);
00073 }
00074
00075 ConstraintGraph& ConstraintGraph::operator= (const ConstraintGraph& other)
00076 {
00077 ROS_DEBUG_STREAM_NAMED ("copy", "Assigning constraint graph");
00078 if (this != &other)
00079 initializeFrom(other);
00080 return *this;
00081 }
00082
00083 void ConstraintGraph::initializeFrom (const ConstraintGraph& g)
00084 {
00086 graph_.clear();
00087 next_node_id_ = 1;
00088 next_edge_id_ = 1;
00089 vertex_map_.clear();
00090 edge_map_.clear();
00091
00092 NodeSet nodes = g.allNodes();
00093
00094 BOOST_FOREACH (const unsigned n, nodes) {
00095 addNode(n);
00096 if (g.hasOptimizedPose(n)) {
00097 setOptimizedPose(n, g.getOptimizedPose(n));
00098 }
00099 }
00100
00101 BOOST_FOREACH (const unsigned n, nodes) {
00102 BOOST_FOREACH (const unsigned e, g.incidentEdges(n)) {
00103 IncidentNodes incident_nodes = g.incidentNodes(e);
00104 if (n == incident_nodes.first)
00105 addEdge(e, n, incident_nodes.second, g.getConstraint(e));
00106 }
00107 }
00108 }
00109
00110
00111
00112
00113
00114
00115 unsigned ConstraintGraph::addNode ()
00116 {
00117 while (nodeIdExists(next_node_id_))
00118 next_node_id_++;
00119 addNode(next_node_id_);
00120 return next_node_id_;
00121 }
00122
00123 void ConstraintGraph::addNode (const unsigned id)
00124 {
00125 if (nodeIdExists(id))
00126 throw DuplicateNodeIdException(id);
00127 ROS_ASSERT(id>0);
00128 vertex_map_[id] = add_vertex(util::makeNode(id), graph_);
00129 ROS_DEBUG_STREAM_NAMED ("graph_add_node", "Added node " << id);
00130 }
00131
00132 unsigned ConstraintGraph::addEdge (const unsigned from, const unsigned to, const PoseWithPrecision& constraint)
00133 {
00134 while (edgeIdExists(next_edge_id_))
00135 next_edge_id_++;
00136 addEdge(next_edge_id_, from, to, constraint);
00137 return next_edge_id_;
00138 }
00139
00140
00141 void ConstraintGraph::addEdge (const unsigned id, const unsigned from, const unsigned to,
00142 const PoseWithPrecision& constraint)
00143 {
00144 const GraphVertex from_vertex = idVertex(from);
00145 const GraphVertex to_vertex = idVertex(to);
00146 if (edgeIdExists(id))
00147 throw DuplicateEdgeIdException(id);
00148 pair<GraphEdge, bool> result =
00149 add_edge(from_vertex, to_vertex, util::makeEdge(id, from, to, constraint), graph_);
00150 ROS_ASSERT(result.second);
00151 edge_map_[id] = result.first;
00152 ROS_DEBUG_STREAM_NAMED ("graph_add_edge", "Added edge " << id << " from " << from << " to " << to);
00153 }
00154
00155
00156
00157
00158
00159 NodeSet ConstraintGraph::allNodes () const
00160 {
00161 NodeSet nodes;
00162 BOOST_FOREACH (const NodeMap::value_type& e, vertex_map_)
00163 nodes.insert(e.first);
00164 return nodes;
00165 }
00166
00167 EdgeSet ConstraintGraph::allEdges () const
00168 {
00169 EdgeSet edges;
00170 BOOST_FOREACH (const EdgeMap::value_type& e, edge_map_) {
00171 edges.insert(e.first);
00172 }
00173 return edges;
00174 }
00175
00176 EdgeSet ConstraintGraph::incidentEdges (const unsigned n) const
00177 {
00178 EdgeSet edges;
00179 GraphVertex v = idVertex(n);
00180 BOOST_FOREACH (const GraphEdge& e, out_edges(v, graph_))
00181 edges.insert(graph_[e].id);
00182 return edges;
00183 }
00184
00185 IncidentNodes ConstraintGraph::incidentNodes (const unsigned e) const
00186 {
00187 GraphEdge edge = idEdge(e);
00188 const unsigned n1 = graph_[source(edge, graph_)].id;
00189 const unsigned n2 = graph_[target(edge, graph_)].id;
00190 const msg::Edge& info = graph_[edge];
00191
00192 if (info.constraint.src == n1) {
00193 ROS_ASSERT(info.constraint.dest == n2);
00194 return IncidentNodes(n1, n2);
00195 }
00196 else {
00197 ROS_ASSERT(info.constraint.dest == n1 && info.constraint.src == n2);
00198 return IncidentNodes(n2, n1);
00199 }
00200 }
00201
00202 const PoseWithPrecision& ConstraintGraph::getConstraint (const unsigned e) const
00203 {
00204 return graph_[idEdge(e)].constraint.constraint;
00205 }
00206
00207
00208
00209
00210
00211 const Graph& ConstraintGraph::graph () const
00212 {
00213 return graph_;
00214 }
00215
00216 GraphEdge ConstraintGraph::idEdge (const unsigned e) const
00217 {
00218 EdgeMap::const_iterator pos = edge_map_.find(e);
00219 if (pos == edge_map_.end())
00220 throw UnknownEdgeIdException(e);
00221 return pos->second;
00222 }
00223
00224 GraphVertex ConstraintGraph::idVertex (const unsigned e) const
00225 {
00226 NodeMap::const_iterator pos = vertex_map_.find(e);
00227 if (pos == vertex_map_.end())
00228 throw UnknownNodeIdException(e);
00229 return pos->second;
00230 }
00231
00232
00233
00234
00235
00236 tf::Pose ConstraintGraph::getOptimizedPose (unsigned n) const
00237 {
00238 const msg::Node& node_info = graph_[idVertex(n)];
00239 if (node_info.optimized_pose.size()==1) {
00240 return util::toPose(node_info.optimized_pose[0]);
00241 }
00242 ROS_ASSERT (node_info.optimized_pose.size()==0);
00243 throw NoOptimizedPoseException(n);
00244 }
00245
00246 void ConstraintGraph::setOptimizedPose (const unsigned n, const tf::Pose& pose)
00247 {
00248 msg::Node& info = graph_[idVertex(n)];
00249 info.optimized_pose.resize(1);
00250 info.optimized_pose[0] = util::toPose(pose);
00251 }
00252
00253 void ConstraintGraph::setOptimizedPoses (const NodePoseMap& poses)
00254 {
00255 typedef map<unsigned, GraphVertex> VertexMap;
00256 BOOST_FOREACH (const VertexMap::value_type& e, vertex_map_) {
00257 NodePoseMap::const_iterator pos = poses.find(e.first);
00258 if (pos==poses.end())
00259 graph_[e.second].optimized_pose.resize(0);
00260 else {
00261 graph_[e.second].optimized_pose.resize(1);
00262 graph_[e.second].optimized_pose[0] = util::toPose(pos->second);
00263 }
00264 }
00265 }
00266
00267 bool ConstraintGraph::hasOptimizedPose (unsigned n) const
00268 {
00269 return (graph_[idVertex(n)].optimized_pose.size()==1);
00270 }
00271
00272
00273
00274
00275
00276 bool ConstraintGraph::nodeIdExists (const unsigned n) const
00277 {
00278 return util::contains(vertex_map_, n);
00279 }
00280
00281 bool ConstraintGraph::edgeIdExists (const unsigned e) const
00282 {
00283 return util::contains(edge_map_, e);
00284 }
00285
00286
00287 }
00288
00289