builder.cpp
Go to the documentation of this file.
00001 #include "robot_markers/builder.h"
00002 
00003 #include <map>
00004 #include <set>
00005 #include <string>
00006 #include <vector>
00007 
00008 #include "boost/shared_ptr.hpp"
00009 #include "geometry_msgs/Pose.h"
00010 #include "geometry_msgs/TransformStamped.h"
00011 #include "ros/ros.h"
00012 #include "transform_graph/transform_graph.h"
00013 #include "urdf/model.h"
00014 #include "visualization_msgs/Marker.h"
00015 #include "visualization_msgs/MarkerArray.h"
00016 
00017 #include "Eigen/Eigen"
00018 
00019 using transform_graph::RefFrame;
00020 using transform_graph::Source;
00021 using transform_graph::Target;
00022 using transform_graph::Transform;
00023 using visualization_msgs::Marker;
00024 using visualization_msgs::MarkerArray;
00025 
00026 typedef std::map<std::string, urdf::LinkSharedPtr> LinkMap;
00027 
00028 namespace {
00029 geometry_msgs::Pose ToGeometryPose(const urdf::Pose& urdf_pose) {
00030   geometry_msgs::Pose pose;
00031   pose.position.x = urdf_pose.position.x;
00032   pose.position.y = urdf_pose.position.y;
00033   pose.position.z = urdf_pose.position.z;
00034   pose.orientation.w = urdf_pose.rotation.w;
00035   pose.orientation.x = urdf_pose.rotation.x;
00036   pose.orientation.y = urdf_pose.rotation.y;
00037   pose.orientation.z = urdf_pose.rotation.z;
00038   return pose;
00039 }
00040 
00041 geometry_msgs::Pose ToGeometryPose(
00042     const transform_graph::Transform& transform) {
00043   Eigen::Matrix3d rot(transform.matrix().topLeftCorner(3, 3));
00044   Eigen::Quaterniond q(rot);
00045   geometry_msgs::Pose pose;
00046   pose.position.x = transform.matrix()(0, 3);
00047   pose.position.y = transform.matrix()(1, 3);
00048   pose.position.z = transform.matrix()(2, 3);
00049   pose.orientation.w = q.w();
00050   pose.orientation.x = q.x();
00051   pose.orientation.y = q.y();
00052   pose.orientation.z = q.z();
00053   return pose;
00054 }
00055 }  // namespace
00056 
00057 namespace robot_markers {
00058 Builder::Builder(const urdf::Model& model)
00059     : model_(model),
00060       fk_(model),
00061       tf_graph_(),
00062       frame_id_(""),
00063       stamp_(0),
00064       ns_(""),
00065       pose_(),
00066       color_(),
00067       lifetime_(0),
00068       frame_locked_(false),
00069       has_initialized_(false) {
00070   pose_.orientation.w = 1;
00071 }
00072 
00073 void Builder::Init() {
00074   fk_.Init();
00075 
00076   // Build initial transform graph
00077   std::vector<urdf::JointSharedPtr> joints;
00078   std::vector<urdf::LinkSharedPtr> links;
00079   model_.getLinks(links);
00080   for (size_t i = 0; i < links.size(); ++i) {
00081     const urdf::LinkSharedPtr& link_p = links[i];
00082     const std::string& name = link_p->name;
00083 
00084     if (link_p->parent_joint) {
00085       geometry_msgs::Pose pose = ToGeometryPose(
00086           link_p->parent_joint->parent_to_joint_origin_transform);
00087       const std::string& parent_name = link_p->getParent()->name;
00088       tf_graph_.Add(NodeName(name), RefFrame(NodeName(parent_name)),
00089                     Transform(pose));
00090     }
00091   }
00092   has_initialized_ = true;
00093 }
00094 
00095 void Builder::SetJointPositions(
00096     const std::map<std::string, double> joint_positions) {
00097   if (!has_initialized_) {
00098     ROS_ERROR(
00099         "You must call Init() before calling any other methods of "
00100         "robot_markers::Builder.");
00101     return;
00102   }
00103 
00104   std::vector<geometry_msgs::TransformStamped> transforms;
00105   fk_.GetTransforms(joint_positions, &transforms);
00106   for (size_t i = 0; i < transforms.size(); ++i) {
00107     const geometry_msgs::TransformStamped& tf = transforms[i];
00108     transform_graph::Transform transform(tf.transform.translation,
00109                                          tf.transform.rotation);
00110     tf_graph_.Add(NodeName(tf.child_frame_id),
00111                   RefFrame(NodeName(tf.header.frame_id)), transform);
00112   }
00113 }
00114 
00115 void Builder::SetFrameId(const std::string& frame_id) {
00116   if (!has_initialized_) {
00117     ROS_ERROR(
00118         "You must call Init() before calling any other methods of "
00119         "robot_markers::Builder.");
00120     return;
00121   }
00122 
00123   frame_id_ = frame_id;
00124 }
00125 void Builder::SetTime(const ros::Time& stamp) {
00126   if (!has_initialized_) {
00127     ROS_ERROR(
00128         "You must call Init() before calling any other methods of "
00129         "robot_markers::Builder.");
00130     return;
00131   }
00132 
00133   stamp_ = stamp;
00134 }
00135 void Builder::SetNamespace(const std::string& ns) {
00136   if (!has_initialized_) {
00137     ROS_ERROR(
00138         "You must call Init() before calling any other methods of "
00139         "robot_markers::Builder.");
00140     return;
00141   }
00142   ns_ = ns;
00143 }
00144 void Builder::SetPose(const geometry_msgs::Pose& pose) {
00145   if (!has_initialized_) {
00146     ROS_ERROR(
00147         "You must call Init() before calling any other methods of "
00148         "robot_markers::Builder.");
00149     return;
00150   }
00151   pose_ = pose;
00152 }
00153 void Builder::SetColor(float r, float g, float b, float a) {
00154   if (!has_initialized_) {
00155     ROS_ERROR(
00156         "You must call Init() before calling any other methods of "
00157         "robot_markers::Builder.");
00158     return;
00159   }
00160 
00161   color_.r = r;
00162   color_.g = g;
00163   color_.b = b;
00164   color_.a = a;
00165 }
00166 
00167 void Builder::Build(MarkerArray* marker_array) {
00168   std::set<std::string> link_names;
00169   Build(link_names, marker_array);
00170 }
00171 
00172 void Builder::Build(const std::set<std::string>& link_names,
00173                     MarkerArray* marker_array) {
00174   if (!has_initialized_) {
00175     ROS_ERROR(
00176         "You must call Init() before calling any other methods of "
00177         "robot_markers::Builder.");
00178     return;
00179   }
00180 
00181   const std::string& root_name = model_.getRoot()->name;
00182 
00183   tf_graph_.Add(NodeName(root_name), RefFrame(frame_id_), pose_);
00184 
00185   std::vector<urdf::LinkSharedPtr> links;
00186   model_.getLinks(links);
00187   for (size_t i = 0; i < links.size(); ++i) {
00188     const urdf::LinkSharedPtr& link_p = links[i];
00189     const std::string& name = link_p->name;
00190     if (!link_names.empty() && link_names.find(name) == link_names.end()) {
00191       continue;
00192     }
00193 
00194     if (!link_p->visual) {
00195       continue;
00196     }
00197 
00198     Marker marker;
00199     BuildMarker(*link_p, i, &marker);
00200     transform_graph::Transform transform_out;
00201     geometry_msgs::Pose visual_transform =
00202         ToGeometryPose(link_p->visual->origin);
00203     bool success =
00204         tf_graph_.DescribePose(visual_transform, Source(NodeName(name)),
00205                                Target(frame_id_), &transform_out);
00206     if (!success) {
00207       ROS_ERROR("No transform from %s to %s!", frame_id_.c_str(), name.c_str());
00208       continue;
00209     }
00210     marker.pose = ToGeometryPose(transform_out);
00211     marker_array->markers.push_back(marker);
00212   }
00213 }
00214 
00215 void Builder::BuildMarker(const urdf::Link& link, int id, Marker* output) {
00216   output->header.frame_id = frame_id_;
00217   output->header.stamp = stamp_;
00218   output->ns = ns_;
00219   output->id = id;
00220   output->color = color_;
00221   output->lifetime = lifetime_;
00222   output->frame_locked = frame_locked_;
00223 
00224   if (link.visual->geometry->type == urdf::Geometry::BOX) {
00225     output->type = Marker::CUBE;
00226     const urdf::Box& box = dynamic_cast<urdf::Box&>(*link.visual->geometry);
00227     output->scale.x = box.dim.x;
00228     output->scale.y = box.dim.y;
00229     output->scale.z = box.dim.z;
00230   } else if (link.visual->geometry->type == urdf::Geometry::CYLINDER) {
00231     output->type = Marker::CYLINDER;
00232     const urdf::Cylinder& cylinder =
00233         dynamic_cast<urdf::Cylinder&>(*link.visual->geometry);
00234     output->scale.x = 2 * cylinder.radius;
00235     output->scale.y = 2 * cylinder.radius;
00236     output->scale.z = cylinder.length;
00237   } else if (link.visual->geometry->type == urdf::Geometry::MESH) {
00238     output->type = Marker::MESH_RESOURCE;
00239     const urdf::Mesh& mesh = dynamic_cast<urdf::Mesh&>(*link.visual->geometry);
00240     output->mesh_use_embedded_materials = true;
00241     if (mesh.scale.x == 0 && mesh.scale.y == 0 && mesh.scale.z == 0) {
00242       output->scale.x = 1;
00243       output->scale.y = 1;
00244       output->scale.z = 1;
00245     } else {
00246       output->scale.x = mesh.scale.x;
00247       output->scale.y = mesh.scale.y;
00248       output->scale.z = mesh.scale.z;
00249     }
00250     output->mesh_resource = mesh.filename;
00251   } else if (link.visual->geometry->type == urdf::Geometry::SPHERE) {
00252     output->type = Marker::SPHERE;
00253     const urdf::Sphere& sphere =
00254         dynamic_cast<urdf::Sphere&>(*link.visual->geometry);
00255     output->scale.x = 2 * sphere.radius;
00256     output->scale.y = 2 * sphere.radius;
00257     output->scale.z = 2 * sphere.radius;
00258   }
00259 }
00260 
00261 std::string Builder::NodeName(const std::string& name) {
00262   return "robot " + name;
00263 }
00264 }  // namespace robot_markers


robot_markers
Author(s):
autogenerated on Sat Jun 8 2019 20:39:25