pinocchio  2.4.4
A fast and flexible implementation of Rigid Body Dynamics algorithms and their analytical derivatives
geometry.cpp
1 //
2 // Copyright (c) 2015-2020 CNRS INRIA
3 //
4 
5 #include "pinocchio/parsers/urdf.hpp"
6 #include "pinocchio/parsers/urdf/types.hpp"
7 #include "pinocchio/parsers/utils.hpp"
8 
9 #include <boost/property_tree/xml_parser.hpp>
10 #include <boost/property_tree/ptree.hpp>
11 
12 #include <urdf_model/model.h>
13 #include <urdf_parser/urdf_parser.h>
14 
15 namespace pinocchio
16 {
17  namespace urdf
18  {
20  namespace details
21  {
22  struct UrdfTree
23  {
24  typedef boost::property_tree::ptree ptree;
25  typedef std::map<std::string, const ptree&> LinkMap_t;
26 
27  void parse (const std::string & xmlStr)
28  {
29  urdf_ = ::urdf::parseURDF(xmlStr);
30  if (!urdf_) {
31  throw std::invalid_argument ("Enable to parse URDF");
32  }
33 
34  std::istringstream iss(xmlStr);
35  using namespace boost::property_tree;
36  read_xml(iss, tree_, xml_parser::no_comments);
37 
38  BOOST_FOREACH(const ptree::value_type & link, tree_.get_child("robot")) {
39  if (link.first == "link") {
40  std::string name = link.second.get<std::string>("<xmlattr>.name");
41  links_.insert(std::pair<std::string,const ptree&>(name, link.second));
42  }
43  } // BOOST_FOREACH
44  }
45 
46  bool isCapsule (const std::string & linkName,
47  const std::string & geomName) const
48  {
49  LinkMap_t::const_iterator _link = links_.find(linkName);
50  assert (_link != links_.end());
51  const ptree& link = _link->second;
52  if (link.count ("collision_checking") == 0)
53  return false;
54  BOOST_FOREACH(const ptree::value_type & cc, link.get_child("collision_checking")) {
55  if (cc.first == "capsule") {
56 #ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
57  std::cerr << "Warning: support for tag link/collision_checking/capsule"
58  " is not available for URDFDOM < 0.3.0" << std::endl;
59 #else
60  std::string name = cc.second.get<std::string>("<xmlattr>.name");
61  if (geomName == name) return true;
62 #endif
63  }
64  } // BOOST_FOREACH
65 
66  return false;
67  }
68 
69  bool isMeshConvex (const std::string & linkName,
70  const std::string & geomName) const
71  {
72  LinkMap_t::const_iterator _link = links_.find(linkName);
73  assert (_link != links_.end());
74  const ptree& link = _link->second;
75  if (link.count ("collision_checking") == 0)
76  return false;
77  BOOST_FOREACH(const ptree::value_type & cc, link.get_child("collision_checking")) {
78  if (cc.first == "convex") {
79 #ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
80  std::cerr << "Warning: support for tag link/collision_checking/convex"
81  " is not available for URDFDOM < 0.3.0" << std::endl;
82 #else
83  std::string name = cc.second.get<std::string>("<xmlattr>.name");
84  if (geomName == name) return true;
85 #endif
86  }
87  } // BOOST_FOREACH
88 
89  return false;
90  }
91 
92  // For standard URDF tags
93  ::urdf::ModelInterfaceSharedPtr urdf_;
94  // For other tags
95  ptree tree_;
96  // A mapping from link name to corresponding child of tree_
97  LinkMap_t links_;
98  };
99 
107  inline SE3 convertFromUrdf (const ::urdf::Pose & M)
108  {
109  const ::urdf::Vector3 & p = M.position;
110  const ::urdf::Rotation & q = M.rotation;
111  return SE3( Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix(), Eigen::Vector3d(p.x,p.y,p.z));
112  }
113 
114  template<typename Vector3>
115  static void retrieveMeshScale(const ::urdf::MeshSharedPtr & mesh,
116  const Eigen::MatrixBase<Vector3> & scale)
117  {
118  Vector3 & scale_ = PINOCCHIO_EIGEN_CONST_CAST(Vector3,scale);
119  scale_ <<
120  mesh->scale.x,
121  mesh->scale.y,
122  mesh->scale.z;
123  }
124 
125 #ifdef PINOCCHIO_WITH_HPP_FCL
126 # if ( HPP_FCL_MAJOR_VERSION>1 || ( HPP_FCL_MAJOR_VERSION==1 && \
127  ( HPP_FCL_MINOR_VERSION>1 || ( HPP_FCL_MINOR_VERSION==1 && \
128  HPP_FCL_PATCH_VERSION>3))))
129 # define PINOCCHIO_HPP_FCL_SUPERIOR_TO_1_1_3
130 # endif
131 
143  boost::shared_ptr<fcl::CollisionGeometry>
145  fcl::MeshLoaderPtr& meshLoader,
146  const std::string& linkName,
147  const std::string& geomName,
148  const ::urdf::GeometrySharedPtr urdf_geometry,
149  const std::vector<std::string> & package_dirs,
150  std::string & meshPath,
151  Eigen::Vector3d & meshScale)
152  {
153  boost::shared_ptr<fcl::CollisionGeometry> geometry;
154 
155  // Handle the case where collision geometry is a mesh
156  if (urdf_geometry->type == ::urdf::Geometry::MESH)
157  {
158  const ::urdf::MeshSharedPtr urdf_mesh = ::urdf::dynamic_pointer_cast< ::urdf::Mesh> (urdf_geometry);
159  std::string collisionFilename = urdf_mesh->filename;
160 
161  meshPath = retrieveResourcePath(collisionFilename, package_dirs);
162  if (meshPath == "") {
163  std::stringstream ss;
164  ss << "Mesh " << collisionFilename << " could not be found.";
165  throw std::invalid_argument (ss.str());
166  }
167 
168  fcl::Vec3f scale = fcl::Vec3f(urdf_mesh->scale.x,
169  urdf_mesh->scale.y,
170  urdf_mesh->scale.z
171  );
172 
173  retrieveMeshScale(urdf_mesh, meshScale);
174 
175  // Create FCL mesh by parsing Collada file.
176 #ifdef PINOCCHIO_HPP_FCL_SUPERIOR_TO_1_1_3
177  hpp::fcl::BVHModelPtr_t bvh = meshLoader->load (meshPath, scale);
178  bool convex = tree.isMeshConvex (linkName, geomName);
179  if (convex) {
180  bvh->buildConvexRepresentation (false);
181  geometry = bvh->convex;
182  } else
183  geometry = bvh;
184 #else
185  geometry = meshLoader->load (meshPath, scale);
186 #endif
187  }
188 
189  // Handle the case where collision geometry is a cylinder
190  // Use FCL capsules for cylinders
191  else if (urdf_geometry->type == ::urdf::Geometry::CYLINDER)
192  {
193  const bool is_capsule = tree.isCapsule(linkName, geomName);
194  meshScale << 1,1,1;
195  const ::urdf::CylinderSharedPtr collisionGeometry = ::urdf::dynamic_pointer_cast< ::urdf::Cylinder> (urdf_geometry);
196 
197  double radius = collisionGeometry->radius;
198  double length = collisionGeometry->length;
199 
200  // Create fcl capsule geometry.
201  if (is_capsule) {
202  meshPath = "CAPSULE";
203  geometry = boost::shared_ptr < fcl::CollisionGeometry >(new fcl::Capsule (radius, length));
204  } else {
205  meshPath = "CYLINDER";
206  geometry = boost::shared_ptr < fcl::CollisionGeometry >(new fcl::Cylinder (radius, length));
207  }
208  }
209  // Handle the case where collision geometry is a box.
210  else if (urdf_geometry->type == ::urdf::Geometry::BOX)
211  {
212  meshPath = "BOX";
213  meshScale << 1,1,1;
214  const ::urdf::BoxSharedPtr collisionGeometry = ::urdf::dynamic_pointer_cast< ::urdf::Box> (urdf_geometry);
215 
216  double x = collisionGeometry->dim.x;
217  double y = collisionGeometry->dim.y;
218  double z = collisionGeometry->dim.z;
219 
220  geometry = boost::shared_ptr < fcl::CollisionGeometry > (new fcl::Box (x, y, z));
221  }
222  // Handle the case where collision geometry is a sphere.
223  else if (urdf_geometry->type == ::urdf::Geometry::SPHERE)
224  {
225  meshPath = "SPHERE";
226  meshScale << 1,1,1;
227  const ::urdf::SphereSharedPtr collisionGeometry = ::urdf::dynamic_pointer_cast< ::urdf::Sphere> (urdf_geometry);
228 
229  double radius = collisionGeometry->radius;
230 
231  geometry = boost::shared_ptr < fcl::CollisionGeometry > (new fcl::Sphere (radius));
232  }
233  else throw std::invalid_argument("Unknown geometry type :");
234 
235  if (!geometry)
236  {
237  throw std::invalid_argument("The polyhedron retrived is empty");
238  }
239 
240  return geometry;
241  }
242 #endif // PINOCCHIO_WITH_HPP_FCL
243 
251  template<typename T>
252  inline PINOCCHIO_URDF_SHARED_PTR(const T)
253  getLinkGeometry(const ::urdf::LinkConstSharedPtr link);
254 
255  template<>
256  inline ::urdf::CollisionConstSharedPtr
257  getLinkGeometry< ::urdf::Collision>(const ::urdf::LinkConstSharedPtr link)
258  {
259  return link->collision;
260  }
261 
262  template<>
263  inline ::urdf::VisualConstSharedPtr
264  getLinkGeometry< ::urdf::Visual>(const ::urdf::LinkConstSharedPtr link)
265  {
266  return link->visual;
267  }
268 
269 
279  template<typename urdfObject>
280  inline bool getVisualMaterial(const PINOCCHIO_URDF_SHARED_PTR(urdfObject) urdf_object,std::string & meshTexturePath,
281  Eigen::Vector4d & meshColor, const std::vector<std::string> & package_dirs);
282 
283  template<>
284  inline bool getVisualMaterial< ::urdf::Collision>
285  (const ::urdf::CollisionSharedPtr, std::string& meshTexturePath,
286  Eigen::Vector4d & meshColor, const std::vector<std::string> &)
287  {
288  meshColor << 0.9, 0.9, 0.9, 1.;
289  meshTexturePath = "";
290  return false;
291  }
292 
293  template<>
294  inline bool getVisualMaterial< ::urdf::Visual>
295  (const ::urdf::VisualSharedPtr urdf_visual, std::string& meshTexturePath,
296  Eigen::Vector4d & meshColor, const std::vector<std::string> & package_dirs)
297  {
298  meshColor.setZero();
299  meshTexturePath = "";
300  bool overrideMaterial = false;
301  if(urdf_visual->material) {
302  overrideMaterial = true;
303  meshColor << urdf_visual->material->color.r, urdf_visual->material->color.g,
304  urdf_visual->material->color.b, urdf_visual->material->color.a;
305  if(urdf_visual->material->texture_filename!="")
306  meshTexturePath = retrieveResourcePath((urdf_visual)->material->texture_filename, package_dirs);
307  }
308  return overrideMaterial;
309  }
310 
318  template<typename T>
319  inline const std::vector< PINOCCHIO_URDF_SHARED_PTR(T) > &
320  getLinkGeometryArray(const ::urdf::LinkConstSharedPtr link);
321 
322  template<>
323  inline const std::vector< ::urdf::CollisionSharedPtr> &
324  getLinkGeometryArray< ::urdf::Collision>(const ::urdf::LinkConstSharedPtr link)
325  {
326  return link->collision_array;
327  }
328 
329  template<>
330  inline const std::vector< ::urdf::VisualSharedPtr> &
331  getLinkGeometryArray< ::urdf::Visual>(const ::urdf::LinkConstSharedPtr link)
332  {
333  return link->visual_array;
334  }
335 
348  template<typename GeometryType>
349  inline void addLinkGeometryToGeomModel(const UrdfTree & tree,
350  ::hpp::fcl::MeshLoaderPtr & meshLoader,
351  ::urdf::LinkConstSharedPtr link,
352  UrdfGeomVisitorBase& visitor,
353  GeometryModel & geomModel,
354  const std::vector<std::string> & package_dirs)
355  {
356 #ifndef PINOCCHIO_WITH_HPP_FCL
357  PINOCCHIO_UNUSED_VARIABLE(tree);
358  PINOCCHIO_UNUSED_VARIABLE(meshLoader);
359 #endif // PINOCCHIO_WITH_HPP_FCL
360 
361  typedef std::vector< PINOCCHIO_URDF_SHARED_PTR(GeometryType) > VectorSharedT;
362  typedef GeometryModel::SE3 SE3;
363 
364  if(getLinkGeometry<GeometryType>(link))
365  {
366  std::string meshPath = "";
367 
368  Eigen::Vector3d meshScale(Eigen::Vector3d::Ones());
369 
370  const std::string & link_name = link->name;
371 
372  VectorSharedT geometries_array = getLinkGeometryArray<GeometryType>(link);
373 
374  FrameIndex frame_id;
375  UrdfGeomVisitorBase::Frame frame = visitor.getBodyFrame (link_name, frame_id);
376  SE3 body_placement = frame.placement;
377 
378  std::size_t objectId = 0;
379  for (typename VectorSharedT::const_iterator i = geometries_array.begin();i != geometries_array.end(); ++i)
380  {
381  meshPath.clear();
382 #ifdef PINOCCHIO_WITH_HPP_FCL
383 
384 #ifdef PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
385  const std::string & geom_name = (*i)->group_name;
386 #else
387  const std::string & geom_name = (*i)->name;
388 #endif // PINOCCHIO_URDFDOM_COLLISION_WITH_GROUP_NAME
389  const GeometryObject::CollisionGeometryPtr geometry =
390  retrieveCollisionGeometry(tree, meshLoader, link_name, geom_name,
391  (*i)->geometry, package_dirs, meshPath, meshScale);
392 #else
393  ::urdf::MeshSharedPtr urdf_mesh = ::urdf::dynamic_pointer_cast< ::urdf::Mesh> ((*i)->geometry);
394  if (urdf_mesh)
395  {
396  meshPath = retrieveResourcePath(urdf_mesh->filename, package_dirs);
397  retrieveMeshScale(urdf_mesh, meshScale);
398  }
399 
400  const boost::shared_ptr<fcl::CollisionGeometry> geometry(new fcl::CollisionGeometry());
401 #endif // PINOCCHIO_WITH_HPP_FCL
402 
403  Eigen::Vector4d meshColor;
404  std::string meshTexturePath;
405  bool overrideMaterial = getVisualMaterial<GeometryType>((*i), meshTexturePath, meshColor, package_dirs);
406 
407  SE3 geomPlacement = body_placement * convertFromUrdf((*i)->origin);
408  std::ostringstream geometry_object_suffix;
409  geometry_object_suffix << "_" << objectId;
410  const std::string & geometry_object_name = std::string(link_name + geometry_object_suffix.str());
411  GeometryObject geometry_object(geometry_object_name,
412  frame_id, frame.parent,
413  geometry,
414  geomPlacement, meshPath, meshScale,
415  overrideMaterial, meshColor, meshTexturePath);
416  geomModel.addGeometryObject(geometry_object);
417  ++objectId;
418  }
419  }
420  }
421 
436  ::hpp::fcl::MeshLoaderPtr& meshLoader,
437  ::urdf::LinkConstSharedPtr link,
438  UrdfGeomVisitorBase& visitor,
439  GeometryModel & geomModel,
440  const std::vector<std::string> & package_dirs,
441  const GeometryType type)
442  {
443 
444  switch(type)
445  {
446  case COLLISION:
447  addLinkGeometryToGeomModel< ::urdf::Collision >(tree, meshLoader, link, visitor, geomModel, package_dirs);
448  break;
449  case VISUAL:
450  addLinkGeometryToGeomModel< ::urdf::Visual >(tree, meshLoader, link, visitor, geomModel, package_dirs);
451  break;
452  default:
453  break;
454  }
455 
456  BOOST_FOREACH(::urdf::LinkConstSharedPtr child,link->child_links)
457  {
458  recursiveParseTreeForGeom(tree, meshLoader, child, visitor, geomModel, package_dirs,type);
459  }
460 
461  }
462 
463  void parseTreeForGeom(UrdfGeomVisitorBase& visitor,
464  const std::istream& xmlStream,
465  const GeometryType type,
466  GeometryModel & geomModel,
467  const std::vector<std::string> & package_dirs,
468  ::hpp::fcl::MeshLoaderPtr meshLoader)
469  {
470  std::string xmlStr;
471  {
472  std::ostringstream os;
473  os << xmlStream.rdbuf();
474  xmlStr = os.str();
475  }
476 
477  details::UrdfTree tree;
478  tree.parse (xmlStr);
479 
480  std::vector<std::string> hint_directories(package_dirs);
481 
482  // Append the ROS_PACKAGE_PATH
483  std::vector<std::string> ros_pkg_paths = rosPaths();
484  hint_directories.insert(hint_directories.end(), ros_pkg_paths.begin(), ros_pkg_paths.end());
485 
486 #ifdef PINOCCHIO_WITH_HPP_FCL
487  if (!meshLoader) meshLoader = fcl::MeshLoaderPtr(new fcl::MeshLoader);
488 #endif // ifdef PINOCCHIO_WITH_HPP_FCL
489 
490  recursiveParseTreeForGeom(tree, meshLoader, tree.urdf_->getRoot(),
491  visitor, geomModel, hint_directories,type);
492  }
493  } // namespace details
495  } // namespace urdf
496 } // namespace pinocchio
void recursiveParseTreeForGeom(const UrdfTree &tree, ::hpp::fcl::MeshLoaderPtr &meshLoader, ::urdf::LinkConstSharedPtr link, UrdfGeomVisitorBase &visitor, GeometryModel &geomModel, const std::vector< std::string > &package_dirs, const GeometryType type)
Recursive procedure for reading the URDF tree, looking for geometries This function fill the geometri...
Definition: geometry.cpp:435
GeomIndex addGeometryObject(const GeometryObject &object, const ModelTpl< S2, O2, _JointCollectionTpl > &model)
Add a geometry object to a GeometryModel and set its parent joint.
SE3 convertFromUrdf(const ::urdf::Pose &M)
Convert URDF Pose quantity to SE3.
Definition: geometry.cpp:107
std::string name(const LieGroupGenericTpl< LieGroupCollection > &lg)
Visit a LieGroupVariant to get the name of it.
boost::shared_ptr< fcl::CollisionGeometry > retrieveCollisionGeometry(const UrdfTree &tree, fcl::MeshLoaderPtr &meshLoader, const std::string &linkName, const std::string &geomName, const ::urdf::GeometrySharedPtr urdf_geometry, const std::vector< std::string > &package_dirs, std::string &meshPath, Eigen::Vector3d &meshScale)
Get a fcl::CollisionObject from an urdf geometry, searching for it in specified package directories...
Definition: geometry.cpp:144
Definition: types.hpp:29
std::vector< std::string > rosPaths()
Parse the environment variable ROS_PACKAGE_PATH and extract paths.
Main pinocchio namespace.
Definition: treeview.dox:24
const std::vector< PINOCCHIO_URDF_SHARED_PTR(T) > & getLinkGeometryArray(const ::urdf::LinkConstSharedPtr link)
Get the array of geometries attached to a link.
std::string retrieveResourcePath(const std::string &string, const std::vector< std::string > &package_dirs)
Retrieve the path of the file whose path is given in an url-format. Currently convert from the follow...
Definition: utils.hpp:61
bool getVisualMaterial(const PINOCCHIO_URDF_SHARED_PTR(urdfObject) urdf_object, std::string &meshTexturePath, Eigen::Vector4d &meshColor, const std::vector< std::string > &package_dirs)
Get the material values from the link visual object.
void addLinkGeometryToGeomModel(const UrdfTree &tree, ::hpp::fcl::MeshLoaderPtr &meshLoader, ::urdf::LinkConstSharedPtr link, UrdfGeomVisitorBase &visitor, GeometryModel &geomModel, const std::vector< std::string > &package_dirs)
Add the geometries attached to an URDF link to a GeometryModel, looking either for collisions or visu...
Definition: geometry.cpp:349