bindings/python/parsers/urdf/geometry.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2015-2020 CNRS INRIA
3 //
4 
8 
9 #include <boost/python.hpp>
10 
11 namespace pinocchio
12 {
13  namespace python
14  {
15 
16  namespace bp = boost::python;
17 
18 #ifdef PINOCCHIO_WITH_URDFDOM
19  typedef ::hpp::fcl::MeshLoaderPtr MeshLoaderPtr;
20 
21  void
22  buildGeomFromUrdf_existing(const Model & model,
23  const std::istream & stream,
24  const GeometryType type,
25  GeometryModel & geometry_model,
26  bp::object py_pkg_dirs,
27  bp::object py_mesh_loader)
28  {
29  MeshLoaderPtr mesh_loader = MeshLoaderPtr();
30  if (!py_mesh_loader.is_none()) {
31 #ifdef PINOCCHIO_WITH_HPP_FCL
34  mesh_loader = bp::extract<::hpp::fcl::MeshLoaderPtr>(py_mesh_loader);
36 #else
37  PyErr_WarnEx(PyExc_UserWarning, "Mesh loader is ignored because Pinocchio is not built with hpp-fcl", 1);
38 #endif
39  }
40 
41  std::vector<std::string> pkg_dirs;
42 
43  bp::extract<std::string> pkg_dir_extract(py_pkg_dirs);
44  bp::extract<bp::list> pkg_dirs_list_extract(py_pkg_dirs);
45  bp::extract<const std::vector<std::string>&> pkg_dirs_vect_extract(py_pkg_dirs);
46  if (py_pkg_dirs.is_none()) {} // Provided None
47  else if (pkg_dir_extract.check()) // Provided a string
48  pkg_dirs.push_back(pkg_dir_extract());
49  else if (pkg_dirs_list_extract.check()) // Provided a list of string
50  extract(pkg_dirs_list_extract(), pkg_dirs);
51  else if (pkg_dirs_vect_extract.check()) // Provided a vector of string
52  pkg_dirs = pkg_dirs_vect_extract();
53  else { // Did not understand the provided argument
54  std::string what = bp::extract<std::string>(py_pkg_dirs.attr("__str__")())();
55  throw std::invalid_argument("pkg_dirs must be either None, a string or a list of strings. Provided " + what);
56  }
57 
58  pinocchio::urdf::buildGeom(model,stream,type,geometry_model,pkg_dirs,mesh_loader);
59  }
60 
61  // This function is complex in order to keep backward compatibility.
62  GeometryModel*
63  buildGeomFromUrdfStream(const Model & model,
64  const std::istream & stream,
65  const GeometryType type,
66  bp::object py_geom_model,
67  bp::object package_dirs,
68  bp::object mesh_loader)
69  {
70  GeometryModel* geom_model;
71  if (py_geom_model.is_none())
72  geom_model = new GeometryModel;
73  else {
74  bp::extract<GeometryModel*> geom_model_extract(py_geom_model);
75  if (geom_model_extract.check())
76  geom_model = geom_model_extract();
77  else {
78  // When backward compat is removed, the code in this `else` section
79  // can be removed and the argument py_geom_model changed into a GeometryModel*
80  PyErr_WarnEx(PyExc_UserWarning,
81  "You passed package dir(s) via argument geometry_model and provided package_dirs.",1);
82 
83  // At this stage, py_geom_model contains the package dir(s). mesh_loader can
84  // be passed either by package_dirs or mesh_loader
85  bp::object new_pkg_dirs = py_geom_model;
86  if (!package_dirs.is_none() && !mesh_loader.is_none())
87  throw std::invalid_argument("package_dirs and mesh_loader cannot be both provided since you passed the package dirs via argument geometry_model.");
88  if (mesh_loader.is_none())
89  mesh_loader = package_dirs;
90  try {
91  // If geom_model is not a valid package_dir(s), then rethrow with clearer message
92  geom_model = new GeometryModel;
93  buildGeomFromUrdf_existing(model, stream, type, *geom_model, new_pkg_dirs, mesh_loader);
94  return geom_model;
95  } catch (std::invalid_argument const& e) {
96  std::cout << "Caught: " << e.what() << std::endl;
97  throw std::invalid_argument("Argument geometry_model should be a GeometryModel");
98  }
99  }
100  }
101  buildGeomFromUrdf_existing(model, stream, type, *geom_model, package_dirs, mesh_loader);
102  return geom_model;
103  }
104 
105  GeometryModel*
106  buildGeomFromUrdfFile(const Model & model,
107  const std::string & filename,
108  const GeometryType type,
109  bp::object geom_model,
110  bp::object package_dirs,
111  bp::object mesh_loader)
112  {
113  std::ifstream stream(filename.c_str());
114  if (!stream.is_open())
115  {
116  throw std::invalid_argument(filename + " does not seem to be a valid file.");
117  }
118  return buildGeomFromUrdfStream(model, stream, type, geom_model, package_dirs, mesh_loader);
119  }
120 
121  GeometryModel*
122  buildGeomFromUrdfString(const Model & model,
123  const std::string & xmlString,
124  const GeometryType type,
125  bp::object geom_model,
126  bp::object package_dirs,
127  bp::object mesh_loader)
128  {
129  std::istringstream stream(xmlString);
130  return buildGeomFromUrdfStream(model, stream, type, geom_model, package_dirs, mesh_loader);
131  }
132 
133 #ifdef PINOCCHIO_WITH_HPP_FCL
134 # define MESH_LOADER_DOC "\tmesh_loader: an hpp-fcl mesh loader (to load only once the related geometries).\n"
135 #else // #ifdef PINOCCHIO_WITH_HPP_FCL
136 # define MESH_LOADER_DOC "\tmesh_loader: unused because the Pinocchio is built without hpp-fcl\n"
137 #endif // #ifdef PINOCCHIO_WITH_HPP_FCL
138  template <std::size_t owner_arg = 1>
139  struct return_value_policy : bp::return_internal_reference<owner_arg>
140  {
141  public:
142  template <class ArgumentPackage>
143  static PyObject* postcall(ArgumentPackage const& args_, PyObject* result)
144  {
145  // If owner_arg exists, we run bp::return_internal_reference postcall
146  // result lifetime will be tied to the owner_arg lifetime
147  PyObject* patient = bp::detail::get_prev<owner_arg>::execute(args_, result);
148  if (patient != Py_None)
149  return bp::return_internal_reference<owner_arg>::postcall(args_, result);
150  // If owner_arg doesn't exist, then Python will have to manage the result lifetime
151  bp::extract<GeometryModel*> geom_model_extract(result);
152  if (geom_model_extract.check())
153  {
154  return bp::to_python_indirect<GeometryModel, bp::detail::make_owning_holder>()(geom_model_extract());
155  }
156  // If returned value is not a GeometryModel*, then raise an error
157  PyErr_SetString(PyExc_RuntimeError, "pinocchio::python::return_value_policy only works on GeometryModel* data type");
158  return 0;
159  }
160  };
161 
162 
163  template<typename F>
164  void defBuildUrdf(const char* name, F f, const char* urdf_arg, const char* urdf_doc)
165  {
166  std::ostringstream doc;
167  doc << "Parse the URDF file given as input looking for the geometry of the given input model and\n"
168  "and store either the collision geometries (GeometryType.COLLISION) or the visual geometries (GeometryType.VISUAL) in a GeometryModel object.\n"
169  "Parameters:\n"
170  "\tmodel: model of the robot\n"
171  "\n" << urdf_arg << ": " << urdf_doc << "\n"
172  "\tgeom_type: type of geometry to extract from the URDF file (either the VISUAL for display or the COLLISION for collision detection).\n"
173  "\tgeometry_model: if provided, this geometry model will be used to store the parsed information instead of creating a new one\n"
174  "\tpackage_dirs: either a single path or a vector of paths pointing to folders containing the model of the robot\n"
175  MESH_LOADER_DOC
176  "\n"
177  "Retuns:\n"
178  "\ta new GeometryModel if `geometry_model` is None else `geometry_model` (that has been updated).\n";
179 
180  bp::def(name, f,
181  (bp::arg("model"),
182  bp::arg(urdf_arg),
183  bp::arg("geom_type"),
184  bp::arg("geometry_model") = static_cast<GeometryModel*>(NULL),
185  bp::arg("package_dirs") = bp::object(),
186  bp::arg("mesh_loader") = bp::object()),
187  doc.str().c_str(), return_value_policy<4>());
188  }
189 
190 #endif
191 
193  {
194 #ifdef PINOCCHIO_WITH_URDFDOM
195  defBuildUrdf("buildGeomFromUrdf", buildGeomFromUrdfFile, "urdf_filename",
196  "path to the URDF file containing the model of the robot");
197  defBuildUrdf("buildGeomFromUrdfString", buildGeomFromUrdfString, "urdf_string",
198  "a string containing the URDF model of the robot");
199 #endif // #ifdef PINOCCHIO_WITH_URDFDOM
200  }
201  }
202 }
203 
boost::python
pinocchio::name
std::string name(const LieGroupGenericTpl< LieGroupCollection > &lg)
Visit a LieGroupVariant to get the name of it.
PINOCCHIO_COMPILER_DIAGNOSTIC_POP
#define PINOCCHIO_COMPILER_DIAGNOSTIC_POP
Definition: include/pinocchio/macros.hpp:95
PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
#define PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
Definition: include/pinocchio/macros.hpp:97
simulation-pendulum.type
type
Definition: simulation-pendulum.py:14
list.hpp
append-urdf-model-with-another-model.package_dirs
package_dirs
Definition: append-urdf-model-with-another-model.py:20
filename
filename
python
urdf.hpp
pinocchio::urdf::buildGeom
GeometryModel & buildGeom(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const std::string &filename, const GeometryType type, GeometryModel &geom_model, const std::vector< std::string > &package_paths=std::vector< std::string >(), ::hpp::fcl::MeshLoaderPtr mesh_loader=::hpp::fcl::MeshLoaderPtr())
Build The GeometryModel from a URDF file. Search for meshes in the directories specified by the user ...
PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
#define PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
macros for pragma push/pop/ignore deprecated warnings
Definition: include/pinocchio/macros.hpp:94
append-urdf-model-with-another-model.geom_model
geom_model
Definition: append-urdf-model-with-another-model.py:25
pinocchio::Model
ModelTpl< double > Model
Definition: multibody/fwd.hpp:35
pinocchio::python::extract
void extract(const boost::python::list &list, std::vector< T, Allocator > &vec)
Definition: list.hpp:24
pinocchio::GeometryType
GeometryType
Definition: fcl.hpp:122
pinocchio::python::exposeURDFGeometry
void exposeURDFGeometry()
Definition: bindings/python/parsers/urdf/geometry.cpp:192
urdf.hpp
pinocchio::model
JointCollectionTpl & model
Definition: joint-configuration.hpp:746
pinocchio
Main pinocchio namespace.
Definition: timings.cpp:28


pinocchio
Author(s):
autogenerated on Tue Feb 13 2024 03:43:58