pinocchio  2.4.4
A fast and flexible implementation of Rigid Body Dynamics algorithms and their analytical derivatives
model.cpp
1 //
2 // Copyright (c) 2015-2020 CNRS
3 // Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France.
4 //
5 
6 #include "pinocchio/parsers/urdf.hpp"
7 
8 #include <urdf_model/model.h>
9 #include <urdf_parser/urdf_parser.h>
10 
11 #include <sstream>
12 #include <boost/foreach.hpp>
13 #include <limits>
14 
15 namespace pinocchio
16 {
17  namespace urdf
18  {
19  namespace details
20  {
28  inline Inertia convertFromUrdf (const ::urdf::Inertial & Y)
29  {
30  const ::urdf::Vector3 & p = Y.origin.position;
31  const ::urdf::Rotation & q = Y.origin.rotation;
32 
33  const Eigen::Vector3d com(p.x,p.y,p.z);
34  const Eigen::Matrix3d & R = Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix();
35 
36  Eigen::Matrix3d I; I <<
37  Y.ixx,Y.ixy,Y.ixz,
38  Y.ixy,Y.iyy,Y.iyz,
39  Y.ixz,Y.iyz,Y.izz;
40  return Inertia(Y.mass,com,R*I*R.transpose());
41  }
42 
43  inline Inertia convertFromUrdf (const ::urdf::InertialSharedPtr & Y)
44  {
45  if (Y) return convertFromUrdf (*Y);
46  return Inertia::Zero();
47  }
48 
56  inline SE3 convertFromUrdf (const ::urdf::Pose & M)
57  {
58  const ::urdf::Vector3 & p = M.position;
59  const ::urdf::Rotation & q = M.rotation;
60  return SE3( Eigen::Quaterniond(q.w,q.x,q.y,q.z).matrix(), Eigen::Vector3d(p.x,p.y,p.z));
61  }
62 
63  FrameIndex getParentLinkFrame(const ::urdf::LinkConstSharedPtr link,
64  UrdfVisitorBase& model)
65  {
66  PINOCCHIO_CHECK_INPUT_ARGUMENT(link && link->getParent());
67  FrameIndex id = model.getBodyId(link->getParent()->name);
68  return id;
69  }
70 
78  void parseTree(::urdf::LinkConstSharedPtr link,
79  UrdfVisitorBase& model)
80  {
81  typedef UrdfVisitorBase::Scalar Scalar;
82  typedef UrdfVisitorBase::SE3 SE3;
83  typedef UrdfVisitorBase::Vector Vector;
84  typedef UrdfVisitorBase::Vector3 Vector3;
85  typedef Model::FrameIndex FrameIndex;
86 
87  // Parent joint of the current body
88  const ::urdf::JointConstSharedPtr joint =
89  ::urdf::const_pointer_cast< ::urdf::Joint>(link->parent_joint);
90 
91  if(joint) // if the link is not the root of the tree
92  {
93  PINOCCHIO_CHECK_INPUT_ARGUMENT(link->getParent());
94 
95  const std::string & joint_name = joint->name;
96  const std::string & link_name = link->name;
97  const std::string & parent_link_name = link->getParent()->name;
98  std::ostringstream joint_info;
99 
100  FrameIndex parentFrameId = getParentLinkFrame(link, model);
101 
102  // Transformation from the parent link to the joint origin
103  const SE3 jointPlacement
104  = convertFromUrdf(joint->parent_to_joint_origin_transform);
105 
106  const Inertia Y = convertFromUrdf(link->inertial);
107 
108  Vector max_effort(1), max_velocity(1), min_config(1), max_config(1);
109  Vector3 axis (joint->axis.x, joint->axis.y, joint->axis.z);
110 
111  const Scalar infty = std::numeric_limits<Scalar>::infinity();
112 
113  switch(joint->type)
114  {
115  case ::urdf::Joint::FLOATING:
116  joint_info << "joint FreeFlyer";
117 
118  max_effort = Vector::Constant(6, infty);
119  max_velocity = Vector::Constant(6, infty);
120  min_config = Vector::Constant(7,-infty);
121  max_config = Vector::Constant(7, infty);
122  min_config.tail<4>().setConstant(-1.01);
123  max_config.tail<4>().setConstant( 1.01);
124 
125  model.addJointAndBody(UrdfVisitorBase::FLOATING, axis,
126  parentFrameId,jointPlacement,joint->name,
127  Y,link->name,
128  max_effort,max_velocity,min_config,max_config);
129  break;
130 
131  case ::urdf::Joint::REVOLUTE:
132  joint_info << "joint REVOLUTE with axis";
133 
134  // TODO I think the URDF standard forbids REVOLUTE with no limits.
135  assert(joint->limits);
136  if (joint->limits)
137  {
138  max_effort << joint->limits->effort;
139  max_velocity << joint->limits->velocity;
140  min_config << joint->limits->lower;
141  max_config << joint->limits->upper;
142  }
143 
144  model.addJointAndBody(UrdfVisitorBase::REVOLUTE, axis,
145  parentFrameId,jointPlacement,joint->name,
146  Y,link->name,
147  max_effort,max_velocity,min_config,max_config);
148  break;
149 
150  case ::urdf::Joint::CONTINUOUS: // Revolute joint with no joint limits
151  joint_info << "joint CONTINUOUS with axis";
152 
153  min_config.resize(2);
154  max_config.resize(2);
155  min_config << -1.01, -1.01;
156  max_config << 1.01, 1.01;
157 
158  if(joint->limits)
159  {
160  max_effort << joint->limits->effort;
161  max_velocity << joint->limits->velocity;
162  } else {
163  max_effort << infty;
164  max_velocity << infty;
165  }
166 
167  model.addJointAndBody(UrdfVisitorBase::CONTINUOUS, axis,
168  parentFrameId,jointPlacement,joint->name,
169  Y,link->name,
170  max_effort,max_velocity,min_config,max_config);
171  break;
172 
173  case ::urdf::Joint::PRISMATIC:
174  joint_info << "joint PRISMATIC with axis";
175 
176  // TODO I think the URDF standard forbids REVOLUTE with no limits.
177  assert(joint->limits);
178  if (joint->limits)
179  {
180  max_effort << joint->limits->effort;
181  max_velocity << joint->limits->velocity;
182  min_config << joint->limits->lower;
183  max_config << joint->limits->upper;
184  }
185 
186  model.addJointAndBody(UrdfVisitorBase::PRISMATIC, axis,
187  parentFrameId,jointPlacement,joint->name,
188  Y,link->name,
189  max_effort,max_velocity,min_config,max_config);
190  break;
191 
192  case ::urdf::Joint::PLANAR:
193  joint_info << "joint PLANAR with normal axis along Z";
194 
195  max_effort = Vector::Constant(3, infty);
196  max_velocity = Vector::Constant(3, infty);
197  min_config = Vector::Constant(4,-infty);
198  max_config = Vector::Constant(4, infty);
199  min_config.tail<2>().setConstant(-1.01);
200  max_config.tail<2>().setConstant( 1.01);
201 
202  model.addJointAndBody(UrdfVisitorBase::PLANAR, axis,
203  parentFrameId,jointPlacement,joint->name,
204  Y,link->name,
205  max_effort,max_velocity,min_config,max_config);
206  break;
207 
208  case ::urdf::Joint::FIXED:
209  // In case of fixed joint, if link has inertial tag:
210  // -add the inertia of the link to his parent in the model
211  // Otherwise do nothing.
212  // In all cases:
213  // -let all the children become children of parent
214  // -inform the parser of the offset to apply
215  // -add fixed body in model to display it in gepetto-viewer
216 
217  joint_info << "fixed joint";
218  model.addFixedJointAndBody(parentFrameId, jointPlacement,
219  joint_name, Y, link_name);
220  break;
221 
222  default:
223  throw std::invalid_argument("The type of joint " + joint_name + " is not supported.");
224  break;
225  }
226 
227  model
228  << "Adding Body" << '\n'
229  << '\"' << link_name << "\" connected to \"" << parent_link_name << "\" through joint \"" << joint_name << "\"\n"
230  << "joint type: " << joint_info.str() << '\n'
231  << "joint placement:\n" << jointPlacement << '\n'
232  << "body info: " << '\n'
233  << " mass: " << Y.mass() << '\n'
234  << " lever: " << Y.lever().transpose() << '\n'
235  << " inertia elements (Ixx,Iyx,Iyy,Izx,Izy,Izz): " << Y.inertia().data().transpose() << '\n' << '\n';
236  }
237  else if (link->getParent())
238  throw std::invalid_argument(link->name + " - joint information missing.");
239 
240  BOOST_FOREACH(::urdf::LinkConstSharedPtr child, link->child_links)
241  {
242  parseTree(child, model);
243  }
244  }
245 
253  void parseRootTree(const ::urdf::ModelInterface * urdfTree,
254  UrdfVisitorBase& model)
255  {
256  model.setName(urdfTree->getName());
257 
258  ::urdf::LinkConstSharedPtr root_link = urdfTree->getRoot();
259  model.addRootJoint(convertFromUrdf(root_link->inertial), root_link->name);
260 
261  BOOST_FOREACH(::urdf::LinkConstSharedPtr child, root_link->child_links)
262  {
263  parseTree(child, model);
264  }
265  }
266 
267  void parseRootTree(const std::string & filename,
268  UrdfVisitorBase& model)
269  {
270  ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDFFile (filename);
271  if (urdfTree)
272  return parseRootTree (urdfTree.get(), model);
273  else
274  throw std::invalid_argument("The file " + filename + " does not "
275  "contain a valid URDF model.");
276  }
277 
278  void parseRootTreeFromXML(const std::string & xmlString,
279  UrdfVisitorBase& model)
280  {
281  ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDF(xmlString);
282  if (urdfTree)
283  return parseRootTree (urdfTree.get(), model);
284  else
285  throw std::invalid_argument("The XML stream does not contain a valid "
286  "URDF model.");
287  }
288  } // namespace details
289  } // namespace urdf
290 } // namespace pinocchio
SE3 convertFromUrdf(const ::urdf::Pose &M)
Convert URDF Pose quantity to SE3.
Definition: geometry.cpp:107
JointIndex id(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointIdVisitor to get the index of the joint in the kinematic chain...
Definition: types.hpp:29
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: model.cpp:78
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: model.cpp:253
Main pinocchio namespace.
Definition: treeview.dox:24