Go to the documentation of this file.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
00038 #include <pose_graph/pose_graph_message.h>
00039 #include <pose_graph/exception.h>
00040 #include <pose_graph/utils.h>
00041 #include <rosbag/view.h>
00042 #include <ros/time.h>
00043 #include <boost/foreach.hpp>
00044 #include <boost/tuple/tuple.hpp>
00045 #include <boost/thread.hpp>
00046
00047 #define foreach BOOST_FOREACH
00048
00049 namespace pose_graph
00050 {
00051
00052 using boost::tie;
00053 using std::string;
00054 using boost::mutex;
00055 using Eigen3::Quaterniond;
00056 using Eigen3::Vector3d;
00057 using occupancy_grid_utils::LocalizedCloud;
00058 using std::map;
00059 using std::vector;
00060 using sensor_msgs::LaserScan;
00061
00062 const string DUMMY_TOPIC("dummy");
00063
00064
00065
00066
00067
00068
00069
00070 PoseWithPrecision constraintToRos (const PoseConstraint& constraint)
00071 {
00072 PoseWithPrecision m;
00073 m.pose.position.x = constraint.translation.x();
00074 m.pose.position.y = constraint.translation.y();
00075 m.pose.position.z = constraint.translation.z();
00076
00077 const Quaterniond::Coefficients& coeffs = constraint.rotation.coeffs();
00078 m.pose.orientation.x = coeffs.x();
00079 m.pose.orientation.y = coeffs.y();
00080 m.pose.orientation.z = coeffs.z();
00081 m.pose.orientation.w = coeffs.w();
00082
00083 unsigned ind=0;
00084 for (unsigned r=0; r<6; r++)
00085 for (unsigned c=0; c<6; c++)
00086 m.precision[ind++] = constraint.precision(r,c);
00087
00088 return m;
00089 }
00090
00091
00092 PoseGraphMessage poseGraphToRos (const PoseGraph& g)
00093 {
00094 PoseGraphMessage m;
00095
00096 foreach (const NodeId n, g.allNodes()) {
00097 Node node;
00098 node.id = n.getId();
00099 node.initial_pose_estimate = g.getInitialPoseEstimate(n);
00100 m.nodes.push_back(node);
00101 if (g.hasCloud(n)) {
00102 m.cloud_ids.push_back(n.getId());
00103 m.clouds.push_back(*g.getCloud(n));
00104 }
00105 if (g.hasScan(n)) {
00106 m.scan_ids.push_back(n.getId());
00107 m.scans.push_back(*g.getScan(n));
00108 }
00109 }
00110
00111 foreach (const EdgeId e, g.allEdges()) {
00112 Edge edge;
00113 edge.id = e.getId();
00114 std::pair<NodeId, NodeId> nodes = g.incidentNodes(e);
00115 edge.src = nodes.first.getId();
00116 edge.dest = nodes.second.getId();
00117 edge.constraint = constraintToRos(g.getConstraint(e));
00118 m.edges.push_back(edge);
00119 }
00120
00121 return m;
00122 }
00123
00124
00125 PoseConstraint constraintFromRos (const PoseWithPrecision& m)
00126 {
00127 PoseConstraint constraint;
00128 constraint.translation = Vector3d(m.pose.position.x, m.pose.position.y, m.pose.position.z);
00129 constraint.rotation = Quaterniond(m.pose.orientation.w, m.pose.orientation.x, m.pose.orientation.y,
00130 m.pose.orientation.z);
00131 unsigned ind=0;
00132 for (unsigned r=0; r<6; r++)
00133 for (unsigned c=0; c<6; c++)
00134 constraint.precision(r,c) = m.precision[ind++];
00135 return constraint;
00136 }
00137
00138
00139 PoseGraph poseGraphFromRos (const PoseGraphMessage& m)
00140 {
00141 PoseGraph g;
00142
00143 foreach (const Node& n, m.nodes) {
00144 g.addNode(NodeId(n.id));
00145 g.setInitialPoseEstimate(NodeId(n.id), n.initial_pose_estimate);
00146 }
00147
00148 foreach (const Edge& e, m.edges)
00149 g.addEdge(NodeId(e.src), NodeId(e.dest), constraintFromRos(e.constraint), EdgeId(e.id));
00150
00151 for (unsigned i=0; i<m.cloud_ids.size(); i++) {
00152 LocalizedCloud::ConstPtr cloud(new LocalizedCloud(m.clouds[i]));
00153 g.attachCloud(NodeId(m.cloud_ids[i]), cloud);
00154 }
00155
00156 for (unsigned i=0; i<m.scan_ids.size(); i++) {
00157 LaserScan::ConstPtr scan(new LaserScan(m.scans[i]));
00158 g.attachScan(NodeId(m.scan_ids[i]), scan);
00159 }
00160
00161 return g;
00162 }
00163
00164
00165
00166
00167
00168 void applyDiff (PoseGraph* graph, const PoseGraphDiff& msg)
00169 {
00170 std::set<NodeId> new_nodes;
00171 BOOST_FOREACH (const Node n, msg.new_nodes) {
00172 graph->addNode(NodeId(n.id));
00173 new_nodes.insert(NodeId(n.id));
00174 graph->setInitialPoseEstimate(NodeId(n.id), n.initial_pose_estimate);
00175 }
00176 BOOST_FOREACH (const Edge& e, msg.new_edges)
00177 graph->addEdge(NodeId(e.src), NodeId(e.dest), constraintFromRos(e.constraint), EdgeId(e.id));
00178 const unsigned num_clouds = msg.cloud_ids.size();
00179 ROS_ASSERT (msg.clouds.size()==num_clouds);
00180 for (unsigned i=0; i<num_clouds; i++) {
00181 LocalizedCloud::ConstPtr cloud(new LocalizedCloud(msg.clouds[i]));
00182 graph->attachCloud(NodeId(msg.cloud_ids[i]), cloud);
00183 }
00184 }
00185
00186
00187 PoseGraphDiff composeDiffs (const vector<PoseGraphDiff::ConstPtr>& diffs)
00188 {
00189 PoseGraphDiff d;
00190 typedef map<unsigned, const Node*> NodeMap;
00191 typedef map<unsigned, const Edge*> EdgeMap;
00192 typedef map<unsigned, const LocalizedCloud*> CloudMap;
00193
00194 NodeMap nodes;
00195 EdgeMap edges;
00196 CloudMap clouds;
00197
00198 BOOST_FOREACH (PoseGraphDiff::ConstPtr diff, diffs) {
00199 BOOST_FOREACH (const Node& node, diff->new_nodes)
00200 nodes[node.id] = &node;
00201 BOOST_FOREACH (const Edge& edge, diff->new_edges)
00202 edges[edge.id] = &edge;
00203 unsigned i=0;
00204 BOOST_FOREACH (const LocalizedCloud& cloud, diff->clouds)
00205 clouds[diff->cloud_ids[i++]] = &cloud;
00206 }
00207
00208 BOOST_FOREACH (const NodeMap::value_type& n, nodes)
00209 d.new_nodes.push_back(*n.second);
00210 BOOST_FOREACH (const EdgeMap::value_type& e, edges)
00211 d.new_edges.push_back(*e.second);
00212 BOOST_FOREACH (const CloudMap::value_type& c, clouds) {
00213 d.cloud_ids.push_back(c.first);
00214 d.clouds.push_back(*c.second);
00215 }
00216
00217 return d;
00218 }
00219
00220
00221
00222
00223
00224 PoseGraph readFromFile (const string& fname)
00225 {
00226 rosbag::Bag bag(fname, rosbag::bagmode::Read);
00227 rosbag::View view(bag);
00228 unsigned num_entries = std::distance(view.begin(), view.end());
00229 ROS_ASSERT_MSG (num_entries == 1, "Input file must contain exactly one message; it had %u", num_entries);
00230 PoseGraphMessage::ConstPtr m = view.begin()->instantiate<PoseGraphMessage>();
00231 return poseGraphFromRos(*m);
00232 }
00233
00234 }