src/parsers/urdf/model.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2015-2020 CNRS
3 // Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France.
4 //
5 
8 #include "pinocchio/parsers/urdf/model.hxx"
9 
10 #include <urdf_model/model.h>
11 #include <urdf_parser/urdf_parser.h>
12 
13 #include <sstream>
14 #include <boost/foreach.hpp>
15 #include <limits>
16 
17 namespace pinocchio
18 {
19  namespace urdf
20  {
21  namespace details
22  {
30  static Inertia convertFromUrdf(const ::urdf::Inertial & Y)
31  {
32  const ::urdf::Vector3 & p = Y.origin.position;
33  const ::urdf::Rotation & q = Y.origin.rotation;
34 
35  const Inertia::Vector3 com(p.x, p.y, p.z);
36  const Inertia::Matrix3 & R =
37  Eigen::Quaterniond(q.w, q.x, q.y, q.z).cast<Inertia::Scalar>().matrix();
38 
39  Inertia::Matrix3 I;
40  I << Y.ixx, Y.ixy, Y.ixz, Y.ixy, Y.iyy, Y.iyz, Y.ixz, Y.iyz, Y.izz;
41  return Inertia(Y.mass, com, R * I * R.transpose());
42  }
43 
44  static Inertia convertFromUrdf(const ::urdf::InertialSharedPtr & Y)
45  {
46  if (Y)
47  return convertFromUrdf(*Y);
48  return Inertia::Zero();
49  }
50 
51  static FrameIndex
52  getParentLinkFrame(const ::urdf::LinkConstSharedPtr link, UrdfVisitorBase & model)
53  {
54  PINOCCHIO_CHECK_INPUT_ARGUMENT(link && link->getParent());
55  FrameIndex id = model.getBodyId(link->getParent()->name);
56  return id;
57  }
58 
67  void parseTree(::urdf::LinkConstSharedPtr link, UrdfVisitorBase & model)
68  {
70  typedef UrdfVisitorBase::SE3 SE3;
71  typedef UrdfVisitorBase::Vector Vector;
74 
75  // Parent joint of the current body
76  const ::urdf::JointConstSharedPtr joint =
77  ::urdf::const_pointer_cast<::urdf::Joint>(link->parent_joint);
78 
79  if (joint) // if the link is not the root of the tree
80  {
81  PINOCCHIO_CHECK_INPUT_ARGUMENT(link->getParent());
82 
83  const std::string & joint_name = joint->name;
84  const std::string & link_name = link->name;
85  const std::string & parent_link_name = link->getParent()->name;
86  std::ostringstream joint_info;
87 
88  FrameIndex parentFrameId = getParentLinkFrame(link, model);
89 
90  // Transformation from the parent link to the joint origin
91  const SE3 jointPlacement =
92  convertFromUrdf(joint->parent_to_joint_origin_transform).cast<Scalar>();
93 
94  const Inertia Y = convertFromUrdf(link->inertial).cast<Scalar>();
95 
96  Vector max_effort(1), max_velocity(1), min_config(1), max_config(1);
97  Vector friction(Vector::Constant(1, 0.)), damping(Vector::Constant(1, 0.));
98  Vector3 axis(joint->axis.x, joint->axis.y, joint->axis.z);
99 
100  const Scalar infty = std::numeric_limits<Scalar>::infinity();
101 
102  switch (joint->type)
103  {
104  case ::urdf::Joint::FLOATING:
105  joint_info << "joint FreeFlyer";
106 
107  max_effort = Vector::Constant(6, infty);
108  max_velocity = Vector::Constant(6, infty);
109  min_config = Vector::Constant(7, -infty);
110  max_config = Vector::Constant(7, infty);
111  min_config.tail<4>().setConstant(-1.01);
112  max_config.tail<4>().setConstant(1.01);
113 
114  friction = Vector::Constant(6, 0.);
115  damping = Vector::Constant(6, 0.);
116 
117  model.addJointAndBody(
118  UrdfVisitorBase::FLOATING, axis, parentFrameId, jointPlacement, joint->name, Y,
119  link->name, max_effort, max_velocity, min_config, max_config, friction, damping);
120  break;
121 
122  case ::urdf::Joint::REVOLUTE:
123  joint_info << "joint REVOLUTE with axis";
124 
125  // TODO I think the URDF standard forbids REVOLUTE with no limits.
126  assert(joint->limits);
127  if (joint->limits)
128  {
129  max_effort << joint->limits->effort;
130  max_velocity << joint->limits->velocity;
131  min_config << joint->limits->lower;
132  max_config << joint->limits->upper;
133  }
134 
135  if (joint->dynamics)
136  {
137  friction << joint->dynamics->friction;
138  damping << joint->dynamics->damping;
139  }
140 
141  model.addJointAndBody(
142  UrdfVisitorBase::REVOLUTE, axis, parentFrameId, jointPlacement, joint->name, Y,
143  link->name, max_effort, max_velocity, min_config, max_config, friction, damping);
144  break;
145 
146  case ::urdf::Joint::CONTINUOUS: // Revolute joint with no joint limits
147  joint_info << "joint CONTINUOUS with axis";
148 
149  min_config.resize(2);
150  max_config.resize(2);
151  min_config << -1.01, -1.01;
152  max_config << 1.01, 1.01;
153 
154  if (joint->limits)
155  {
156  max_effort << joint->limits->effort;
157  max_velocity << joint->limits->velocity;
158  }
159  else
160  {
161  max_effort << infty;
162  max_velocity << infty;
163  }
164 
165  if (joint->dynamics)
166  {
167  friction << joint->dynamics->friction;
168  damping << joint->dynamics->damping;
169  }
170 
171  model.addJointAndBody(
172  UrdfVisitorBase::CONTINUOUS, axis, parentFrameId, jointPlacement, joint->name, Y,
173  link->name, max_effort, max_velocity, min_config, max_config, friction, damping);
174  break;
175 
176  case ::urdf::Joint::PRISMATIC:
177  joint_info << "joint PRISMATIC with axis";
178 
179  // TODO I think the URDF standard forbids REVOLUTE with no limits.
180  assert(joint->limits);
181  if (joint->limits)
182  {
183  max_effort << joint->limits->effort;
184  max_velocity << joint->limits->velocity;
185  min_config << joint->limits->lower;
186  max_config << joint->limits->upper;
187  }
188 
189  if (joint->dynamics)
190  {
191  friction << joint->dynamics->friction;
192  damping << joint->dynamics->damping;
193  }
194 
195  model.addJointAndBody(
196  UrdfVisitorBase::PRISMATIC, axis, parentFrameId, jointPlacement, joint->name, Y,
197  link->name, max_effort, max_velocity, min_config, max_config, friction, damping);
198  break;
199 
200  case ::urdf::Joint::PLANAR:
201  joint_info << "joint PLANAR with normal axis along Z";
202 
203  max_effort = Vector::Constant(3, infty);
204  max_velocity = Vector::Constant(3, infty);
205  min_config = Vector::Constant(4, -infty);
206  max_config = Vector::Constant(4, infty);
207  min_config.tail<2>().setConstant(-1.01);
208  max_config.tail<2>().setConstant(1.01);
209 
210  friction = Vector::Constant(3, 0.);
211  damping = Vector::Constant(3, 0.);
212 
213  model.addJointAndBody(
214  UrdfVisitorBase::PLANAR, axis, parentFrameId, jointPlacement, joint->name, Y,
215  link->name, max_effort, max_velocity, min_config, max_config, friction, damping);
216  break;
217 
218  case ::urdf::Joint::FIXED:
219  // In case of fixed joint, if link has inertial tag:
220  // -add the inertia of the link to his parent in the model
221  // Otherwise do nothing.
222  // In all cases:
223  // -let all the children become children of parent
224  // -inform the parser of the offset to apply
225  // -add fixed body in model to display it in gepetto-viewer
226 
227  joint_info << "fixed joint";
228  model.addFixedJointAndBody(parentFrameId, jointPlacement, joint_name, Y, link_name);
229  break;
230 
231  default:
232  throw std::invalid_argument("The type of joint " + joint_name + " is not supported.");
233  break;
234  }
235 
236  model << "Adding Body" << '\n'
237  << '\"' << link_name << "\" connected to \"" << parent_link_name
238  << "\" through joint \"" << joint_name << "\"\n"
239  << "joint type: " << joint_info.str() << '\n'
240  << "joint placement:\n"
241  << jointPlacement << '\n'
242  << "body info: " << '\n'
243  << " mass: " << Y.mass() << '\n'
244  << " lever: " << Y.lever().transpose() << '\n'
245  << " inertia elements (Ixx,Iyx,Iyy,Izx,Izy,Izz): "
246  << Y.inertia().data().transpose() << '\n'
247  << '\n';
248  }
249  else if (link->getParent())
250  throw std::invalid_argument(link->name + " - joint information missing.");
251 
252  BOOST_FOREACH (::urdf::LinkConstSharedPtr child, link->child_links)
253  {
254  parseTree(child, model);
255  }
256  }
257 
266  void parseRootTree(const ::urdf::ModelInterface * urdfTree, UrdfVisitorBase & model)
267  {
268  model.setName(urdfTree->getName());
269 
270  ::urdf::LinkConstSharedPtr root_link = urdfTree->getRoot();
271  model.addRootJoint(convertFromUrdf(root_link->inertial).cast<double>(), root_link->name);
272 
273  BOOST_FOREACH (::urdf::LinkConstSharedPtr child, root_link->child_links)
274  {
275  parseTree(child, model);
276  }
277  }
278 
279  void parseRootTree(const std::string & filename, UrdfVisitorBase & model)
280  {
281  ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDFFile(filename);
282  if (urdfTree)
283  return parseRootTree(urdfTree.get(), model);
284  else
285  throw std::invalid_argument(
286  "The file " + filename
287  + " does not "
288  "contain a valid URDF model.");
289  }
290 
291  void parseRootTreeFromXML(const std::string & xmlString, UrdfVisitorBase & model)
292  {
293  ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDF(xmlString);
294  if (urdfTree)
295  return parseRootTree(urdfTree.get(), model);
296  else
297  throw std::invalid_argument("The XML stream does not contain a valid "
298  "URDF model.");
299  }
300  } // namespace details
301  } // namespace urdf
302 } // namespace pinocchio
pinocchio::InertiaTpl< context::Scalar, context::Options >
pinocchio::FrameIndex
Index FrameIndex
Definition: multibody/fwd.hpp:28
PINOCCHIO_CHECK_INPUT_ARGUMENT
#define PINOCCHIO_CHECK_INPUT_ARGUMENT(...)
Macro to check an assert-like condition and throw a std::invalid_argument exception (with a message) ...
Definition: include/pinocchio/macros.hpp:193
pinocchio::Inertia
InertiaTpl< context::Scalar, context::Options > Inertia
Definition: spatial/fwd.hpp:65
pinocchio::id
JointIndex id(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointIdVisitor to get the index of the joint in the kinematic chain.
pinocchio::urdf::details::parseTree
void parseTree(::urdf::LinkConstSharedPtr link, UrdfVisitorBase &model)
Recursive procedure for reading the URDF tree. The function returns an exception as soon as a necessa...
Definition: src/parsers/urdf/model.cpp:67
pinocchio::SE3Tpl< context::Scalar, context::Options >
pinocchio::python::Scalar
context::Scalar Scalar
Definition: admm-solver.cpp:29
pinocchio::urdf::details::convertFromUrdf
SE3 convertFromUrdf(const ::urdf::Pose &M)
Convert URDF Pose quantity to SE3.
Definition: utils.cpp:10
R
R
pinocchio::urdf::details::parseRootTreeFromXML
void parseRootTreeFromXML(const std::string &xmlString, UrdfVisitorBase &model)
Definition: src/parsers/urdf/model.cpp:291
pinocchio::InertiaTpl< context::Scalar, context::Options >::Zero
static InertiaTpl Zero()
Definition: spatial/inertia.hpp:332
dpendulum.p
p
Definition: dpendulum.py:6
details
filename
filename
urdf.hpp
pinocchio::ModelTpl::FrameIndex
pinocchio::FrameIndex FrameIndex
Definition: multibody/model.hpp:70
pinocchio::urdf::details::parseRootTree
void parseRootTree(const ::urdf::ModelInterface *urdfTree, UrdfVisitorBase &model)
Parse a tree with a specific root joint linking the model to the environment. The function returns an...
Definition: src/parsers/urdf/model.cpp:266
pinocchio::context::Vector3
Eigen::Matrix< Scalar, 3, 1, Options > Vector3
Definition: context/generic.hpp:53
axis
axis
utils.hpp
pinocchio::q
JointCollectionTpl const Eigen::MatrixBase< ConfigVectorType > & q
Definition: joint-configuration.hpp:1117
pinocchio::SE3Tpl::cast
SE3Tpl< NewScalar, Options > cast() const
Definition: spatial/se3-tpl.hpp:379
append-urdf-model-with-another-model.joint_name
string joint_name
Definition: append-urdf-model-with-another-model.py:33
urdf
Definition: types.hpp:29
Y
Y
pinocchio::urdf::details::getParentLinkFrame
static FrameIndex getParentLinkFrame(const ::urdf::LinkConstSharedPtr link, UrdfVisitorBase &model)
Definition: src/parsers/urdf/model.cpp:52
pinocchio::python::context::SE3
SE3Tpl< Scalar, Options > SE3
Definition: bindings/python/context/generic.hpp:53
pinocchio::SE3
SE3Tpl< context::Scalar, context::Options > SE3
Definition: spatial/fwd.hpp:60
robot-wrapper-viewer.com
com
Definition: robot-wrapper-viewer.py:45
pinocchio::model
JointCollectionTpl & model
Definition: joint-configuration.hpp:1116
pinocchio
Main pinocchio namespace.
Definition: timings.cpp:27


pinocchio
Author(s):
autogenerated on Tue Jun 25 2024 02:42:40