urdfreader.cc
Go to the documentation of this file.
1 
2 #include <fstream>
3 #include <stack>
4 
5 #include <urdf_model/model.h>
6 #include <urdf_parser/urdf_parser.h>
7 #include "ros/ros.h"
8 
9 #include "rdl_dynamics/Model.h"
12 
13 using namespace std;
14 
15 namespace RobotDynamics
16 {
17 namespace Urdf
18 {
19 using namespace Math;
20 
21 typedef vector<urdf::LinkSharedPtr> URDFLinkVector;
22 typedef vector<urdf::JointSharedPtr> URDFJointVector;
23 typedef map<string, urdf::LinkSharedPtr> URDFLinkMap;
24 typedef map<string, urdf::JointSharedPtr> URDFJointMap;
25 
26 bool construct_model(ModelPtr rdl_model, urdf::ModelInterfaceSharedPtr urdf_model, bool floating_base, bool verbose)
27 {
28  urdf::LinkSharedPtr urdf_root_link;
29 
30  URDFLinkMap link_map;
31  link_map = urdf_model->links_;
32 
33  URDFJointMap joint_map;
34  joint_map = urdf_model->joints_;
35 
36  vector<string> joint_names;
37 
38  stack<urdf::LinkSharedPtr> link_stack;
39  stack<int> joint_index_stack;
40 
41  // add the bodies in a depth-first order of the model tree
42  link_stack.push(link_map[(urdf_model->getRoot()->name)]);
43 
44  // add the root body
45  urdf::LinkConstSharedPtr root = urdf_model->getRoot();
46  Vector3d root_inertial_rpy;
47  Vector3d root_inertial_position;
48  Matrix3d root_inertial_inertia;
49  // cppcheck-suppress variableScope
50 
51  if (root->inertial)
52  {
53  double root_inertial_mass = root->inertial->mass;
54 
55  root_inertial_position.set(root->inertial->origin.position.x, root->inertial->origin.position.y, root->inertial->origin.position.z);
56 
57  root->inertial->origin.rotation.getRPY(root_inertial_rpy[0], root_inertial_rpy[1], root_inertial_rpy[2]);
58 
60  root_inertia_in_com_frame(0, 0) = root->inertial->ixx;
61  root_inertia_in_com_frame(0, 1) = root->inertial->ixy;
62  root_inertia_in_com_frame(0, 2) = root->inertial->ixz;
63  root_inertia_in_com_frame(1, 0) = root->inertial->ixy;
64  root_inertia_in_com_frame(1, 1) = root->inertial->iyy;
65  root_inertia_in_com_frame(1, 2) = root->inertial->iyz;
66  root_inertia_in_com_frame(2, 0) = root->inertial->ixz;
67  root_inertia_in_com_frame(2, 1) = root->inertial->iyz;
68  root_inertia_in_com_frame(2, 2) = root->inertial->izz;
69 
70  RobotDynamics::Math::SpatialTransform X_body_to_inertial = RobotDynamics::Math::XeulerXYZ(root_inertial_rpy);
71  root_inertial_inertia =
72  root_inertial_rpy == Vector3d(0., 0., 0.) ? root_inertia_in_com_frame : X_body_to_inertial.E.transpose() * root_inertia_in_com_frame * X_body_to_inertial.E;
73  Body root_link = Body(root_inertial_mass, root_inertial_position, root_inertial_inertia);
74 
75  Joint root_joint(JointTypeFixed);
76  if (floating_base)
77  {
78  root_joint = Joint(JointTypeFloatingBase);
79  }
80 
81  SpatialTransform root_joint_frame = SpatialTransform();
82 
83  if (verbose)
84  {
85  cout << "+ Adding Root Body " << endl;
86  cout << " joint frame: " << root_joint_frame << endl;
87  if (floating_base)
88  {
89  cout << " joint type : floating" << endl;
90  }
91  else
92  {
93  cout << " joint type : fixed" << endl;
94  }
95  cout << " body inertia: " << endl << root_link.mInertia << endl;
96  cout << " body mass : " << root_link.mMass << endl;
97  cout << " body name : " << root->name << endl;
98  }
99 
100  rdl_model->appendBody(root_joint_frame, root_joint, root_link, root->name);
101  }
102 
103  if (link_stack.top()->child_joints.size() > 0)
104  {
105  joint_index_stack.push(0);
106  }
107 
108  // while(link_stack.size() > 0)
109  while (!link_stack.empty())
110  {
111  urdf::LinkSharedPtr cur_link = link_stack.top();
112  unsigned int joint_idx;
113  if (joint_index_stack.size() > 0)
114  {
115  joint_idx = joint_index_stack.top();
116  }
117  else
118  {
119  joint_idx = 0;
120  }
121 
122  if (joint_idx < cur_link->child_joints.size())
123  {
124  urdf::JointSharedPtr cur_joint = cur_link->child_joints[joint_idx];
125 
126  // increment joint index
127  joint_index_stack.pop();
128  joint_index_stack.push(joint_idx + 1);
129 
130  link_stack.push(link_map[cur_joint->child_link_name]);
131  joint_index_stack.push(0);
132 
133  if (verbose)
134  {
135  for (unsigned int i = 1; i < joint_index_stack.size() - 1; i++)
136  {
137  cout << " ";
138  }
139  cout << "joint '" << cur_joint->name << "' child link '" << link_stack.top()->name << "' type = " << cur_joint->type << endl;
140  }
141 
142  joint_names.push_back(cur_joint->name);
143  }
144  else
145  {
146  link_stack.pop();
147  joint_index_stack.pop();
148  }
149  }
150 
151  unsigned int j;
152  for (j = 0; j < joint_names.size(); j++)
153  {
154  urdf::JointSharedPtr urdf_joint = joint_map[joint_names[j]];
155  urdf::LinkSharedPtr urdf_parent = link_map[urdf_joint->parent_link_name];
156  urdf::LinkSharedPtr urdf_child = link_map[urdf_joint->child_link_name];
157 
158  // determine where to add the current joint and child body
159  unsigned int rdl_parent_id = 0;
160  if (rdl_model->mBodies.size() != 1 || rdl_model->mFixedBodies.size() != 0)
161  {
162  rdl_parent_id = rdl_model->GetBodyId(urdf_parent->name.c_str());
163  }
164 
165  if (rdl_parent_id == std::numeric_limits<unsigned int>::max())
166  {
167  cerr << "Error while processing joint '" << urdf_joint->name << "': parent link '" << urdf_parent->name << "' could not be found." << endl;
168  }
169 
170  // create the joint
171  Joint rdl_joint;
172  if (urdf_joint->type == urdf::Joint::REVOLUTE || urdf_joint->type == urdf::Joint::CONTINUOUS)
173  {
174  rdl_joint = Joint(SpatialVector(urdf_joint->axis.x, urdf_joint->axis.y, urdf_joint->axis.z, 0., 0., 0.));
175  }
176  else if (urdf_joint->type == urdf::Joint::PRISMATIC)
177  {
178  rdl_joint = Joint(SpatialVector(0., 0., 0., urdf_joint->axis.x, urdf_joint->axis.y, urdf_joint->axis.z));
179  }
180  else if (urdf_joint->type == urdf::Joint::FIXED)
181  {
182  rdl_joint = Joint(JointTypeFixed);
183  }
184  else if (urdf_joint->type == urdf::Joint::FLOATING)
185  {
186  // todo: what order of DoF should be used?
187  rdl_joint = Joint(SpatialVector(0., 0., 0., 1., 0., 0.), SpatialVector(0., 0., 0., 0., 1., 0.), SpatialVector(0., 0., 0., 0., 0., 1.),
188  SpatialVector(1., 0., 0., 0., 0., 0.), SpatialVector(0., 1., 0., 0., 0., 0.), SpatialVector(0., 0., 1., 0., 0., 0.));
189  }
190  else if (urdf_joint->type == urdf::Joint::PLANAR)
191  {
192  // todo: which two directions should be used that are perpendicular
193  // to the specified axis?
194  cerr << "Error while processing joint '" << urdf_joint->name << "': planar joints not yet supported!" << endl;
195  return false;
196  }
197 
198  // compute the joint transformation
199  Vector3d joint_rpy;
200  Vector3d joint_translation;
201  urdf_joint->parent_to_joint_origin_transform.rotation.getRPY(joint_rpy[0], joint_rpy[1], joint_rpy[2]);
202  joint_translation.set(urdf_joint->parent_to_joint_origin_transform.position.x, urdf_joint->parent_to_joint_origin_transform.position.y,
203  urdf_joint->parent_to_joint_origin_transform.position.z);
204  SpatialTransform rdl_joint_frame = Xrot(joint_rpy[0], Vector3d(1., 0., 0.)) * Xrot(joint_rpy[1], Vector3d(0., 1., 0.)) *
205  Xrot(joint_rpy[2], Vector3d(0., 0., 1.)) * Xtrans(Vector3d(joint_translation));
206 
207  // assemble the body
208  Vector3d link_inertial_position;
209  Vector3d link_inertial_rpy;
210  Matrix3d link_inertial_inertia = Matrix3d::Zero();
211  double link_inertial_mass = 0.;
212 
213  // but only if we actually have inertial data
214  if (urdf_child->inertial)
215  {
216  link_inertial_mass = urdf_child->inertial->mass;
217 
218  link_inertial_position.set(urdf_child->inertial->origin.position.x, urdf_child->inertial->origin.position.y, urdf_child->inertial->origin.position.z);
219  urdf_child->inertial->origin.rotation.getRPY(link_inertial_rpy[0], link_inertial_rpy[1], link_inertial_rpy[2]);
220 
222  link_inertia_in_com_frame(0, 0) = urdf_child->inertial->ixx;
223  link_inertia_in_com_frame(0, 1) = urdf_child->inertial->ixy;
224  link_inertia_in_com_frame(0, 2) = urdf_child->inertial->ixz;
225  link_inertia_in_com_frame(1, 0) = urdf_child->inertial->ixy;
226  link_inertia_in_com_frame(1, 1) = urdf_child->inertial->iyy;
227  link_inertia_in_com_frame(1, 2) = urdf_child->inertial->iyz;
228  link_inertia_in_com_frame(2, 0) = urdf_child->inertial->ixz;
229  link_inertia_in_com_frame(2, 1) = urdf_child->inertial->iyz;
230  link_inertia_in_com_frame(2, 2) = urdf_child->inertial->izz;
231 
232  RobotDynamics::Math::SpatialTransform X_body_to_inertial = RobotDynamics::Math::XeulerXYZ(link_inertial_rpy);
233  link_inertial_inertia = link_inertial_rpy == Vector3d(0., 0., 0.) ? link_inertia_in_com_frame :
234  X_body_to_inertial.E.transpose() * link_inertia_in_com_frame * X_body_to_inertial.E;
235  }
236 
237  Body rdl_body = Body(link_inertial_mass, link_inertial_position, link_inertial_inertia);
238 
239  if (verbose)
240  {
241  cout << "+ Adding Body " << endl;
242  cout << " parent_id : " << rdl_parent_id << endl;
243  cout << " joint frame: " << rdl_joint_frame << endl;
244  cout << " joint dofs : " << rdl_joint.mDoFCount << endl;
245  for (unsigned int j = 0; j < rdl_joint.mDoFCount; j++)
246  {
247  cout << " " << j << ": " << rdl_joint.mJointAxes[j].transpose() << endl;
248  }
249  cout << " body inertia: " << endl << rdl_body.mInertia << endl;
250  cout << " body mass : " << rdl_body.mMass << endl;
251  cout << " body name : " << urdf_child->name << endl;
252  }
253 
254  if (urdf_joint->type == urdf::Joint::FLOATING)
255  {
256  Matrix3d zero_matrix = Matrix3d::Zero();
257  Body null_body(0., Vector3d::Zero(3), zero_matrix);
258  Joint joint_txtytz(JointTypeTranslationXYZ);
259  string trans_body_name = urdf_child->name + "_Translate";
260  rdl_model->addBody(rdl_parent_id, rdl_joint_frame, joint_txtytz, null_body, trans_body_name);
261 
262  Joint joint_euler_zyx(JointTypeEulerXYZ);
263  rdl_model->appendBody(SpatialTransform(), joint_euler_zyx, rdl_body, urdf_child->name);
264  }
265  else
266  {
267  rdl_model->addBody(rdl_parent_id, rdl_joint_frame, rdl_joint, rdl_body, urdf_child->name);
268  }
269  }
270 
271  return true;
272 }
273 
274 bool parseJointBodyNameMapFromFile(const char* filename, std::map<std::string, std::string>& jointBodyMap)
275 {
276  ifstream model_file(filename);
277  if (!model_file)
278  {
279  cerr << "Error opening file '" << filename << "'." << endl;
280  return false;
281  }
282 
283  // reserve memory for the contents of the file
284  std::string model_xml_string;
285  model_file.seekg(0, std::ios::end);
286  model_xml_string.reserve(model_file.tellg());
287  model_file.seekg(0, std::ios::beg);
288  model_xml_string.assign((std::istreambuf_iterator<char>(model_file)), std::istreambuf_iterator<char>());
289 
290  model_file.close();
291 
292  return parseJointBodyNameMapFromString(model_xml_string.c_str(), jointBodyMap);
293 }
294 
295 bool parseJointAndBodyNamesFromString(const char* model_xml_string, std::vector<std::string>& joint_names, std::vector<std::string>& body_names)
296 {
297  TiXmlDocument doc;
298 
299  // Check if contents are valid, if not, abort
300  if (!doc.Parse(model_xml_string) && doc.Error())
301  {
302  std::cerr << "Can't parse urdf. Xml is invalid" << std::endl;
303  return false;
304  }
305 
306  // Find joints in transmission tags
307  TiXmlElement* root = doc.RootElement();
308 
309  for (TiXmlElement* joint = root->FirstChildElement("joint"); joint; joint = joint->NextSiblingElement("joint"))
310  {
311  if (!std::strcmp(joint->Attribute("type"), "fixed") || !std::strcmp(joint->Attribute("type"), "floating"))
312  {
313  continue;
314  }
315 
316  joint_names.push_back(joint->Attribute("name"));
317  body_names.push_back(joint->FirstChildElement("child")->Attribute("link"));
318  }
319 
320  return true;
321 }
322 
323 bool parseJointAndBodyNamesFromString(const std::string& model_xml_string, std::vector<std::string>& joint_names, std::vector<std::string>& body_names)
324 {
325  return parseJointAndBodyNamesFromString(model_xml_string.c_str(), joint_names, body_names);
326 }
327 
328 bool parseJointBodyNameMapFromString(const std::string& model_xml_string, std::map<std::string, std::string>& jointBodyMap)
329 {
330  std::vector<std::string> joint_names, body_names;
331  if (!parseJointAndBodyNamesFromString(model_xml_string, joint_names, body_names))
332  {
333  return false;
334  }
335 
336  jointBodyMap.clear();
337  for (unsigned int i = 0; i < joint_names.size(); i++)
338  {
339  jointBodyMap.insert(std::pair<std::string, std::string>(joint_names[i], body_names[i]));
340  }
341 
342  return true;
343 }
344 
345 bool parseJointBodyNameMapFromString(const char* model_xml_string, std::map<std::string, std::string>& jointBodyMap)
346 {
347  std::vector<std::string> joint_names, body_names;
348  if (!parseJointAndBodyNamesFromString(model_xml_string, joint_names, body_names))
349  {
350  return false;
351  }
352 
353  jointBodyMap.clear();
354  for (unsigned int i = 0; i < joint_names.size(); i++)
355  {
356  jointBodyMap.insert(std::pair<std::string, std::string>(joint_names[i], body_names[i]));
357  }
358 
359  return true;
360 }
361 
362 bool parseJointAndQIndex(const RobotDynamics::Model& model, const std::vector<std::string>& body_names, std::vector<unsigned int>& q_indices)
363 {
364  q_indices.clear();
365  for (unsigned int i = 0; i < body_names.size(); i++)
366  {
367  q_indices.push_back(model.mJoints[model.GetBodyId(body_names[i].c_str())].q_index);
368  }
369 
370  return true;
371 }
372 
373 bool parseJointAndQIndex(const std::string& model_xml_string, std::vector<unsigned int>& q_indices)
374 {
376  if (!urdfReadFromString(model_xml_string, model))
377  {
378  return false;
379  }
380 
381  std::vector<std::string> joint_names, body_names;
382  if (!parseJointAndBodyNamesFromString(model_xml_string, joint_names, body_names))
383  {
384  return false;
385  }
386 
387  return parseJointAndQIndex(*model, body_names, q_indices);
388 }
389 
390 bool urdfReadFromFile(const char* filename, ModelPtr model, bool floating_base, bool verbose)
391 {
392  ifstream model_file(filename);
393  if (!model_file)
394  {
395  cerr << "Error opening file '" << filename << "'." << endl;
396  return false;
397  }
398 
399  // reserve memory for the contents of the file
400  string model_xml_string;
401  model_file.seekg(0, std::ios::end);
402  model_xml_string.reserve(model_file.tellg());
403  model_file.seekg(0, std::ios::beg);
404  model_xml_string.assign((std::istreambuf_iterator<char>(model_file)), std::istreambuf_iterator<char>());
405 
406  model_file.close();
407 
408  return urdfReadFromString(model_xml_string.c_str(), model, floating_base, verbose);
409 }
410 
411 bool urdfReadFromString(const char* model_xml_string, ModelPtr model, bool floating_base, bool verbose)
412 {
413  assert(model);
414 
415  urdf::ModelInterfaceSharedPtr urdf_model = urdf::parseURDF(model_xml_string);
416 
417  if (!construct_model(model, urdf_model, floating_base, verbose))
418  {
419  cerr << "Error constructing model from urdf file." << endl;
420  return false;
421  }
422 
423  model->gravity.SpatialVector::set(0., 0., 0., 0., 0., -9.81);
424 
425  return true;
426 }
427 
428 bool urdfReadFromFile(const std::string& filename, ModelPtr model)
429 {
430  ifstream model_file(filename.c_str());
431  if (!model_file)
432  {
433  cerr << "Error opening file '" << filename << "'." << endl;
434  return false;
435  }
436 
437  // reserve memory for the contents of the file
438  std::string model_xml_string;
439  model_file.seekg(0, std::ios::end);
440  model_xml_string.reserve(model_file.tellg());
441  model_file.seekg(0, std::ios::beg);
442  model_xml_string.assign((std::istreambuf_iterator<char>(model_file)), std::istreambuf_iterator<char>());
443 
444  model_file.close();
445 
446  return urdfReadFromString(model_xml_string, model);
447 }
448 
449 bool urdfReadFromString(const std::string& model_xml_string, ModelPtr model)
450 {
451  assert(model);
452 
453  urdf::ModelInterfaceSharedPtr urdf_model = urdf::parseURDF(model_xml_string.c_str());
454 
455  bool floating_base = std::strcmp(urdf_model->getRoot()->name.c_str(), "world") ? true : false;
456 
457  if (!construct_model(model, urdf_model, floating_base, false))
458  {
459  cerr << "Error constructing model from urdf file." << endl;
460  return false;
461  }
462 
463  model->gravity.SpatialVector::set(0., 0., 0., 0., 0., -9.81);
464 
465  return true;
466 }
467 } // namespace Urdf
468 } // namespace RobotDynamics
std::vector< Joint > mJoints
bool verbose
map< string, urdf::LinkSharedPtr > URDFLinkMap
Definition: urdfreader.cc:23
std::shared_ptr< Model > ModelPtr
SpatialTransform Xtrans(const Vector3d &r)
JointTypeFixed
bool parseJointBodyNameMapFromFile(const char *filename, std::map< std::string, std::string > &jointBodyMap)
This will build a map of joint name to body name.
Definition: urdfreader.cc:274
vector< urdf::LinkSharedPtr > URDFLinkVector
Definition: urdfreader.cc:21
vector< urdf::JointSharedPtr > URDFJointVector
Definition: urdfreader.cc:22
Math::Matrix3d mInertia
bool parseJointAndBodyNamesFromString(const std::string &model_xml_string, std::vector< std::string > &joint_names, std::vector< std::string > &body_names)
This will build vectors of joint name and body name pairs.
Definition: urdfreader.cc:323
map< string, urdf::JointSharedPtr > URDFJointMap
Definition: urdfreader.cc:24
JointTypeEulerXYZ
unsigned int GetBodyId(const char *body_name) const
Matrix3d Matrix3dZero(0., 0., 0., 0., 0., 0., 0., 0., 0.)
bool construct_model(ModelPtr rdl_model, urdf::ModelInterfaceSharedPtr urdf_model, bool floating_base, bool verbose)
Definition: urdfreader.cc:26
bool parseJointBodyNameMapFromString(const char *model_xml_string, std::map< std::string, std::string > &jointBodyMap)
This will build a map of joint name to body name.
Definition: urdfreader.cc:345
string filename
unsigned int mDoFCount
Math::SpatialVector * mJointAxes
JointTypeFloatingBase
void set(const Eigen::Vector3d &v)
bool urdfReadFromFile(const char *filename, ModelPtr model, bool floating_base, bool verbose=false)
Read urdf from file path.
Definition: urdfreader.cc:390
SpatialTransform XeulerXYZ(double roll, double pitch, double yaw)
JointTypeTranslationXYZ
bool urdfReadFromString(const char *model_xml_string, ModelPtr model, bool floating_base, bool verbose=false)
Read urdf from string contents.
Definition: urdfreader.cc:411
SpatialTransform Xrot(double angle_rad, const Vector3d &axis)
bool parseJointAndQIndex(const RobotDynamics::Model &model, const std::vector< std::string > &body_names, std::vector< unsigned int > &q_indices)
This will build a vector of joint indices in the same order as the list of joints.
Definition: urdfreader.cc:362


rdl_urdfreader
Author(s):
autogenerated on Tue Apr 20 2021 02:25:38