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 }
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
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 }