ed_gui_server
robot.cpp
Go to the documentation of this file.
1 #include "robot.h"
2 
3 #include <urdf/model.h>
4 
5 #include <tf2/transform_datatypes.h>
6 #include <tf2/LinearMath/Transform.h>
7 #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
8 #include <tf2_ros/buffer.h>
9 
10 #include <ros/package.h>
11 #include <ros/console.h>
12 
13 #include <geolib/Box.h>
14 #include <geolib/CompositeShape.h>
15 #include <geolib/io/import.h>
18 
19 #include <ed/error_context.h>
20 #include <ed/models/shape_loader.h>
21 
22 
23 // ----------------------------------------------------------------------------------------------------
24 
25 geo::ShapePtr URDFGeometryToShape(const urdf::GeometrySharedPtr& geom)
26 {
27  geo::ShapePtr shape;
28 
29  if (geom->type == urdf::Geometry::MESH)
30  {
31  urdf::Mesh* mesh = static_cast<urdf::Mesh*>(geom.get());
32  if (!mesh)
33  {
34  ROS_WARN_NAMED("robot", "[gui_server] Robot model error: No mesh geometry defined");
35  return shape;
36  }
37 
38  std::string pkg_prefix = "package://";
39  if (mesh->filename.substr(0, pkg_prefix.size()) == pkg_prefix)
40  {
41  std::string str = mesh->filename.substr(pkg_prefix.size());
42  size_t i_slash = str.find("/");
43 
44  std::string pkg = str.substr(0, i_slash);
45  std::string rel_filename = str.substr(i_slash + 1);
46  std::string pkg_path = ros::package::getPath(pkg);
47  std::string abs_filename = pkg_path + "/" + rel_filename;
48 
49  shape = geo::io::readMeshFile(abs_filename, mesh->scale.x);
50 
51  if (!shape)
52  ROS_ERROR_STREAM_NAMED("robot", "[gui_server] Could not load mesh shape from '" << abs_filename << "'");
53  }
54  }
55  else if (geom->type == urdf::Geometry::BOX)
56  {
57  urdf::Box* box = static_cast<urdf::Box*>(geom.get());
58  if (!box)
59  {
60  ROS_WARN_NAMED("robot", "[gui_server] Robot model error: No box geometry defined");
61  return shape;
62  }
63 
64  double hx = box->dim.x / 2;
65  double hy = box->dim.y / 2;
66  double hz = box->dim.z / 2;
67 
68  shape.reset(new geo::Box(geo::Vector3(-hx, -hy, -hz), geo::Vector3(hx, hy, hz)));
69  }
70  else if (geom->type == urdf::Geometry::CYLINDER)
71  {
72  urdf::Cylinder* cyl = static_cast<urdf::Cylinder*>(geom.get());
73  if (!cyl)
74  {
75  ROS_WARN_NAMED("robot", "[gui_server] Robot model error: No cylinder geometry defined");
76  return shape;
77  }
78 
79  shape.reset(new geo::Shape());
80  ed::models::createCylinder(*shape, cyl->radius, cyl->length, 20);
81  }
82  else if (geom->type == urdf::Geometry::SPHERE)
83  {
84  urdf::Sphere* sphere = static_cast<urdf::Sphere*>(geom.get());
85  if (!sphere)
86  {
87  ROS_WARN_NAMED("robot", "[gui_server] Robot model error: No sphere geometry defined");
88  return shape;
89  }
90 
91  shape.reset(new geo::Shape());
92  ed::models::createSphere(*shape, sphere->radius);
93  }
94 
95  return shape;
96 }
97 
98 // ----------------------------------------------------------------------------------------------------
99 
100 geo::ShapePtr LinkToVisual(const urdf::LinkSharedPtr& link)
101 {
102  geo::CompositeShapePtr visual;
103 
104  for (urdf::VisualSharedPtr& vis : link->visual_array)
105  {
106  const urdf::GeometrySharedPtr& geom = vis->geometry;
107  if (!geom)
108  {
109  ROS_WARN_STREAM_NAMED("robot", "[gui_server] Robot model error: missing geometry for visual in link: '" << link->name << "'");
110  continue;
111  }
112 
113  geo::Pose3D offset;
114  const urdf::Pose& o = vis->origin;
115  offset.t = geo::Vector3(o.position.x, o.position.y, o.position.z);
116  offset.R.setRotation(geo::Quaternion(o.rotation.x, o.rotation.y, o.rotation.z, o.rotation.w));
117 
118  geo::ShapePtr subshape = URDFGeometryToShape(geom);
119  if (!subshape)
120  continue;
121 
122  if (!visual)
123  visual.reset(new geo::CompositeShape());
124  visual->addShape(*subshape, offset);
125  }
126 
127  return visual;
128 }
129 
130 
131 namespace gui
132 {
133 
134 // ----------------------------------------------------------------------------------------------------
135 
136 Robot::Robot() : tf_buffer_(nullptr)
137 {
138  ed::ErrorContext errc("robot::constructor");
139 }
140 
141 // ----------------------------------------------------------------------------------------------------
142 
143 Robot::Robot(const ed::TFBufferConstPtr& tf_buffer) : tf_buffer_(tf_buffer)
144 {
145  ed::ErrorContext errc("robot::constructor(tf_buffer");
146 }
147 
148 
149 // ----------------------------------------------------------------------------------------------------
150 
152 {
153  ed::ErrorContext errc("robot::destructor");
154 }
155 
156 // ----------------------------------------------------------------------------------------------------
157 
158 void Robot::initialize(const std::string& name, const std::string& urdf_rosparam, const std::string& tf_prefix)
159 {
160  ed::ErrorContext errc("robot::initialize; robot =", name_.c_str());
161 
162  name_ = name;
163 
164  urdf_rosparam_ = urdf_rosparam;
165 
166  tf_prefix_ = tf_prefix;
167  if (!tf_prefix_.empty() && tf_prefix_.back() != '/')
168  tf_prefix_ = tf_prefix_ + "/";
169 
170  // Load URDF model from parameter server
171  urdf::Model robot_model;
172 
173  std::string urdf_xml;
174 
175  ros::NodeHandle nh;
176  if (!nh.getParam(urdf_rosparam, urdf_xml))
177  {
178  ROS_ERROR_STREAM_NAMED("robot", "ROS parameter not set: '" << urdf_rosparam << "'.");
179  return;
180  }
181 
182  if (!robot_model.initString(urdf_xml))
183  {
184  ROS_ERROR_STREAM_NAMED("robot", "Could not load robot model for '" << name << ".");
185  return;
186  }
187 
189  robot_model.getLinks(links);
190 
191  for (const urdf::LinkSharedPtr& link : links)
192  {
193  if (!link->visual_array.empty())
194  {
195  geo::ShapePtr shape = LinkToVisual(link);
196 
197  if (shape)
198  {
199  // The desired solution is to have static tf_prefixing
200  // (see http://wiki.ros.org/tf2/Migration#Removal_of_support_for_tf_prefix)
201  // The problem here is that the hsrb_description does not support (static) tf prefixing (in the xacro)
202  // and hence not in the resulting urdf on the parameter server and not in tf,
203  // while we do want this prefix in ED for easy filtering of WM entities.
204  // Therefore we need a seperation between names of links and entities.
205  std::string full_link_name = tf_prefix_ + link->name;
206 
207  // Don't prefix if link already starts with robot name
208  std::string entity_name;
209  if (link->name.length() >= name_.length() && link->name.substr(0, name_.length()) == name_)
210  entity_name = link->name;
211  else
212  entity_name = name_ + "/" + link->name;
213 
214  Visual visual;
215 
216  // Determine color
217 
218  visual.color.a = 255;
219  if (link->visual->material_name == "Black" || full_link_name == "/amigo/base_kinect/openni_camera")
220  {
221  visual.color.r = 0;
222  visual.color.g = 0;
223  visual.color.b = 0;
224  }
225  else if (link->visual->material_name == "White" || link->visual->material_name == "amigo_description/white"
226  || link->visual->material_name == "amigo_description/bottomcovers")
227  {
228  visual.color.r = 204;
229  visual.color.g = 204;
230  visual.color.b = 204;
231  }
232  else if (link->visual->material_name == "Grey" || link->visual->material_name == "amigo_description/aluminium")
233  {
234  visual.color.r = 102;
235  visual.color.g = 102;
236  visual.color.b = 102;
237  }
238  else if (link->visual->material_name == "amigo_description/orange")
239  {
240  visual.color.r = 204;
241  visual.color.g = 102;
242  visual.color.b = 0;
243  }
244  else if (link->visual->material_name == "amigo_description/logo")
245  {
246  visual.color.r = 0;
247  visual.color.g = 0;
248  visual.color.b = 102;
249  }
250  else
251  {
252  ROS_INFO_STREAM("[gui_server] " << entity_name << ": " << link->visual->material_name);
253  visual.color.a = 0;
254  }
255 
256  visual.shape = shape;
257  visual.link = full_link_name;
258 
259  shapes_[entity_name] = visual;
260  }
261  }
262  }
263 }
264 
265 // ----------------------------------------------------------------------------------------------------
266 
268 {
269  ed::ErrorContext errc("robot::getShape; robot =", name_.c_str());
270  ShapeMap::const_iterator it = shapes_.find(id);
271  if (it != shapes_.end())
272  return it->second.shape;
273  return geo::ShapeConstPtr();
274 }
275 
276 // ----------------------------------------------------------------------------------------------------
277 
278 bool Robot::contains(const std::string& id) const
279 {
280  ed::ErrorContext errc("robot::contains; robot =", name_.c_str());
281  ShapeMap::const_iterator it = shapes_.find(id);
282  if (it != shapes_.end())
283  return true;
284  return false;
285 }
286 
287 // ----------------------------------------------------------------------------------------------------
288 
290 {
291  ed::ErrorContext errc("robot::getEntities; robot =", name_.c_str());
292 
293  for(ShapeMap::const_iterator it = shapes_.begin(); it != shapes_.end(); ++it)
294  {
295  ed_gui_server_msgs::EntityInfo e;
296  e.id = it->first;
297 
298  try
299  {
300  geometry_msgs::TransformStamped ts = tf_buffer_->lookupTransform("map", it->second.link, ros::Time(0));
301  tf2::Stamped<tf2::Transform> t;
302  tf2::convert(ts, t);
303 
304  geo::Pose3D pose;
305  geo::convert(t, pose);
306 
307  geo::convert(pose, e.pose);
308  e.has_pose = true;
309 
310  e.color = it->second.color;
311 
312  e.visual_revision = 1;
313 
314  entities.push_back(e);
315  }
316  catch (tf2::TransformException& ex)
317  {
318  ROS_DEBUG_STREAM_NAMED("robot", "[gui_server] No transform from 'map' to '" << it->second.link << "': " << ex.what());
319  }
320  }
321 }
322 
323 } // end namespace gui
geo::Vector3
Vec3 Vector3
geo::Mat3T::setRotation
void setRotation(const QuaternionT< T > &q)
robot.h
geo::QuaternionT
std::string
ed::TFBufferConstPtr
shared_ptr< const tf2_ros::Buffer > TFBufferConstPtr
std::shared_ptr
geo::ShapeConstPtr
std::shared_ptr< const Shape > ShapeConstPtr
t
Timer t
import.h
std::vector
std::string::find
T find(T... args)
std::string::size
T size(T... args)
geo::Box
gui::Robot::urdf_rosparam_
std::string urdf_rosparam_
Definition: robot.h:50
std::string::back
T back(T... args)
geo::Transform3T
Visual::link
std::string link
Definition: robot.h:17
ed::ErrorContext
std::shared_ptr::reset
T reset(T... args)
gui::Robot::getEntities
void getEntities(std::vector< ed_gui_server_msgs::EntityInfo > &entities) const
Definition: robot.cpp:289
gui::Robot::getShape
geo::ShapeConstPtr getShape(const std::string &id) const
Definition: robot.cpp:267
Visual
Definition: robot.h:13
gui::Robot::contains
bool contains(const std::string &id) const
Definition: robot.cpp:278
gui::Robot::initialize
void initialize(const std::string &name, const std::string &urdf_rosparam, const std::string &tf_prefix)
Definition: robot.cpp:158
shape_loader.h
std::string::c_str
T c_str(T... args)
gui::Robot::~Robot
virtual ~Robot()
Definition: robot.cpp:151
gui::Robot::name_
std::string name_
Definition: robot.h:48
geo::io::readMeshFile
ShapePtr readMeshFile(const std::string &filename, const geo::Vec3 &scale)
geo::Transform3T::t
Vec3T< T > t
CompositeShape.h
geo::Vector3
geo::convert
void convert(const geo::DepthCamera &cam_model, sensor_msgs::CameraInfo &msg)
Visual::shape
geo::ShapeConstPtr shape
Definition: robot.h:15
Visual::color
ed_gui_server_msgs::Color color
Definition: robot.h:16
std::string::substr
T substr(T... args)
ed::models::createCylinder
void createCylinder(geo::Shape &shape, double radius, double height, int num_corners=12)
geo::CompositeShape
gui::Robot::name
const std::string & name() const
Definition: robot.h:38
gui::Robot::Robot
Robot()
Definition: robot.cpp:136
ed::models::createSphere
void createSphere(geo::Shape &shape, double radius, uint recursion_level=2)
gui
Definition: robot.cpp:131
LinkToVisual
geo::ShapePtr LinkToVisual(const urdf::LinkSharedPtr &link)
Definition: robot.cpp:100
tf2_conversions.h
std::map::begin
T begin(T... args)
geo::Transform3T::R
Mat3T< T > R
std::string::empty
T empty(T... args)
gui::Robot::tf_buffer_
ed::TFBufferConstPtr tf_buffer_
Definition: robot.h:54
Box.h
std::map::end
T end(T... args)
gui::Robot::shapes_
ShapeMap shapes_
Definition: robot.h:56
URDFGeometryToShape
geo::ShapePtr URDFGeometryToShape(const urdf::GeometrySharedPtr &geom)
Definition: robot.cpp:25
gui::Robot::tf_prefix_
std::string tf_prefix_
Definition: robot.h:52
error_context.h
msg_conversions.h
geo::Shape
entities
std::map< std::string, EntityViz > entities
Definition: rviz_publisher.cpp:25