pose_graph_message.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 
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  * Converting between PoseGraph and PoseGraphMessage
00066  ************************************************************/
00067 
00068 // Uses the assumption that tf::Pose and tf::Transform are the same type
00069 // (will not compile otherwise)
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  * Diffs
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 // Compose diffs. Later changes overwrite earlier ones.
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  * File read/write using bags
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 } // namespace pose_graph


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