srdf_writer.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2012, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Dave Coleman */
36 
37 #include <tinyxml.h>
38 #include <srdfdom/srdf_writer.h>
39 
40 namespace srdf
41 {
42 // ******************************************************************************************
43 // Constructor
44 // ******************************************************************************************
46 {
47  // Intialize the SRDF model
48  srdf_model_.reset(new srdf::Model());
49 }
50 
51 // ******************************************************************************************
52 // Destructor
53 // ******************************************************************************************
55 {
56 }
57 
58 // ******************************************************************************************
59 // Load SRDF data from a pre-populated string
60 // ******************************************************************************************
61 bool SRDFWriter::initString(const urdf::ModelInterface& robot_model, const std::string& srdf_string)
62 {
63  // Parse string into srdf_model_ and Error check
64  if (!srdf_model_->initString(robot_model, srdf_string))
65  {
66  return false; // error loading file. improper format?
67  }
68 
69  // copy fields into this object
70  initModel(robot_model, *srdf_model_);
71 
72  return true;
73 }
74 
75 // ******************************************************************************************
76 // Load SRDF data from a pre-populated string
77 // ******************************************************************************************
78 void SRDFWriter::initModel(const urdf::ModelInterface& robot_model, const srdf::Model& srdf_model)
79 {
80  // copy to internal srdf_model_
81  if (srdf_model_.get() != &srdf_model)
82  {
83  *srdf_model_ = srdf_model;
84  }
85 
86  // Copy all read-only data from srdf model to this object
87  disabled_collisions_ = srdf_model_->getDisabledCollisionPairs();
88  link_sphere_approximations_ = srdf_model_->getLinkSphereApproximations();
89  groups_ = srdf_model_->getGroups();
90  virtual_joints_ = srdf_model_->getVirtualJoints();
91  end_effectors_ = srdf_model_->getEndEffectors();
92  group_states_ = srdf_model_->getGroupStates();
93  passive_joints_ = srdf_model_->getPassiveJoints();
94 
95  // Copy the robot name b/c the root xml element requires this attribute
96  robot_name_ = robot_model.getName();
97 }
98 
99 // ******************************************************************************************
100 // Update the SRDF Model class using a new SRDF string
101 // ******************************************************************************************
102 void SRDFWriter::updateSRDFModel(const urdf::ModelInterface& robot_model)
103 {
104  // Get an up to date SRDF String
105  const std::string srdf_string = getSRDFString();
106 
107  // Error check
108  if (!srdf_model_->initString(robot_model, srdf_string))
109  {
110  throw std::runtime_error("Unable to update the SRDF Model");
111  }
112 }
113 
114 // ******************************************************************************************
115 // Save to file a generated SRDF document
116 // ******************************************************************************************
117 bool SRDFWriter::writeSRDF(const std::string& file_path)
118 {
119  // Generate the SRDF
120  TiXmlDocument document = generateSRDF();
121 
122  // Save to file
123  return document.SaveFile(file_path);
124 }
125 
126 // ******************************************************************************************
127 // Get a string of a generated SRDF document
128 // ******************************************************************************************
130 {
131  // Generate the SRDF
132  TiXmlDocument document = generateSRDF();
133 
134  // Setup printer
135  TiXmlPrinter printer;
136  printer.SetIndent(" ");
137  document.Accept(&printer);
138 
139  // Return string
140  return printer.CStr();
141 }
142 
143 // ******************************************************************************************
144 // Generate SRDF XML of all contained data
145 // ******************************************************************************************
147 {
148  TiXmlDocument document;
149  TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "", "");
150  document.LinkEndChild(decl);
151 
152  // Convenience comments
153  TiXmlComment* comment = new TiXmlComment("This does not replace URDF, and is not an extension of URDF.\n This is "
154  "a format for "
155  "representing semantic information about the robot structure.\n A URDF "
156  "file must exist for "
157  "this robot as well, where the joints and the links that are referenced are "
158  "defined\n");
159  document.LinkEndChild(comment);
160 
161  // Root
162  TiXmlElement* robot_root = new TiXmlElement("robot");
163  robot_root->SetAttribute("name", robot_name_); // robot name
164  document.LinkEndChild(robot_root);
165 
166  // Add Groups
167  createGroupsXML(robot_root);
168 
169  // Add Group States
170  createGroupStatesXML(robot_root);
171 
172  // Add End Effectors
173  createEndEffectorsXML(robot_root);
174 
175  // Add Virtual Joints
176  createVirtualJointsXML(robot_root);
177 
178  // Add Passive Joints
179  createPassiveJointsXML(robot_root);
180 
181  // Add Link Sphere approximations
183 
184  // Add Disabled Collisions
185  createDisabledCollisionsXML(robot_root);
186 
187  // Save
188  return document;
189 }
190 
191 // ******************************************************************************************
192 // Generate XML for SRDF groups
193 // ******************************************************************************************
194 void SRDFWriter::createGroupsXML(TiXmlElement* root)
195 {
196  // Convenience comments
197  if (groups_.size()) // only show comments if there are corresponding elements
198  {
199  TiXmlComment* comment;
200  comment = new TiXmlComment("GROUPS: Representation of a set of joints and links. This can be useful for specifying "
201  "DOF to plan for, defining arms, end effectors, etc");
202  root->LinkEndChild(comment);
203  comment = new TiXmlComment("LINKS: When a link is specified, the parent joint of that link (if it exists) is "
204  "automatically included");
205  root->LinkEndChild(comment);
206  comment = new TiXmlComment("JOINTS: When a joint is specified, the child link of that joint (which will always "
207  "exist) is automatically included");
208  root->LinkEndChild(comment);
209  comment = new TiXmlComment("CHAINS: When a chain is specified, all the links along the chain (including endpoints) "
210  "are included in the group. Additionally, all the joints that are parents to included "
211  "links are also included. This means that joints along the chain and the parent joint "
212  "of the base link are included in the group");
213  root->LinkEndChild(comment);
214  comment = new TiXmlComment("SUBGROUPS: Groups can also be formed by referencing to already defined group names");
215  root->LinkEndChild(comment);
216  }
217 
218  // Loop through all of the top groups
219  for (std::vector<srdf::Model::Group>::iterator group_it = groups_.begin(); group_it != groups_.end(); ++group_it)
220  {
221  // Create group element
222  TiXmlElement* group = new TiXmlElement("group");
223  group->SetAttribute("name", group_it->name_); // group name
224  root->LinkEndChild(group);
225 
226  // LINKS
227  for (std::vector<std::string>::const_iterator link_it = group_it->links_.begin(); link_it != group_it->links_.end();
228  ++link_it)
229  {
230  TiXmlElement* link = new TiXmlElement("link");
231  link->SetAttribute("name", *link_it); // link name
232  group->LinkEndChild(link);
233  }
234 
235  // JOINTS
236  for (std::vector<std::string>::const_iterator joint_it = group_it->joints_.begin();
237  joint_it != group_it->joints_.end(); ++joint_it)
238  {
239  TiXmlElement* joint = new TiXmlElement("joint");
240  joint->SetAttribute("name", *joint_it); // joint name
241  group->LinkEndChild(joint);
242  }
243 
244  // CHAINS
245  for (std::vector<std::pair<std::string, std::string> >::const_iterator chain_it = group_it->chains_.begin();
246  chain_it != group_it->chains_.end(); ++chain_it)
247  {
248  TiXmlElement* chain = new TiXmlElement("chain");
249  chain->SetAttribute("base_link", chain_it->first);
250  chain->SetAttribute("tip_link", chain_it->second);
251  group->LinkEndChild(chain);
252  }
253 
254  // SUBGROUPS
255  for (std::vector<std::string>::const_iterator subgroup_it = group_it->subgroups_.begin();
256  subgroup_it != group_it->subgroups_.end(); ++subgroup_it)
257  {
258  TiXmlElement* subgroup = new TiXmlElement("group");
259  subgroup->SetAttribute("name", *subgroup_it); // subgroup name
260  group->LinkEndChild(subgroup);
261  }
262  }
263 }
264 
265 // ******************************************************************************************
266 // Generate XML for SRDF link collision spheres
267 // ******************************************************************************************
269 {
270  if (link_sphere_approximations_.empty()) // skip it if there are none
271  return;
272 
273  // Convenience comments
274  TiXmlComment* comment = new TiXmlComment();
275  comment->SetValue("COLLISION SPHERES: Purpose: Define a set of spheres that bounds a link.");
276  root->LinkEndChild(comment);
277 
278  for (std::vector<srdf::Model::LinkSpheres>::const_iterator link_sphere_it = link_sphere_approximations_.begin();
279  link_sphere_it != link_sphere_approximations_.end(); ++link_sphere_it)
280  {
281  if (link_sphere_it->spheres_.empty()) // skip if no spheres for this link
282  continue;
283 
284  // Create new element for the link
285  TiXmlElement* link = new TiXmlElement("link_sphere_approximation");
286  link->SetAttribute("link", link_sphere_it->link_);
287  root->LinkEndChild(link);
288 
289  // Add all spheres for the link
290  for (std::vector<srdf::Model::Sphere>::const_iterator sphere_it = link_sphere_it->spheres_.begin();
291  sphere_it != link_sphere_it->spheres_.end(); ++sphere_it)
292  {
293  TiXmlElement* sphere = new TiXmlElement("sphere");
294  std::stringstream center;
295  center.precision(20);
296  center << sphere_it->center_x_ << " " << sphere_it->center_y_ << " " << sphere_it->center_z_;
297  sphere->SetAttribute("center", center.str());
298  sphere->SetDoubleAttribute("radius", sphere_it->radius_);
299  link->LinkEndChild(sphere);
300  }
301  }
302 }
303 
304 // ******************************************************************************************
305 // Generate XML for SRDF disabled collisions of robot link pairs
306 // ******************************************************************************************
308 {
309  // Convenience comments
310  if (disabled_collisions_.size()) // only show comments if there are corresponding elements
311  {
312  TiXmlComment* comment = new TiXmlComment();
313  comment->SetValue("DISABLE COLLISIONS: By default it is assumed that any link of the robot could potentially come "
314  "into collision with any other link in the robot. This tag disables collision checking between a "
315  "specified pair of links. ");
316  root->LinkEndChild(comment);
317  }
318 
319  for (std::vector<srdf::Model::DisabledCollision>::const_iterator pair_it = disabled_collisions_.begin();
320  pair_it != disabled_collisions_.end(); ++pair_it)
321  {
322  // Create new element for each link pair
323  TiXmlElement* link_pair = new TiXmlElement("disable_collisions");
324  link_pair->SetAttribute("link1", pair_it->link1_);
325  link_pair->SetAttribute("link2", pair_it->link2_);
326  link_pair->SetAttribute("reason", pair_it->reason_);
327 
328  root->LinkEndChild(link_pair);
329  }
330 }
331 
332 // ******************************************************************************************
333 // Generate XML for SRDF group states
334 // ******************************************************************************************
335 void SRDFWriter::createGroupStatesXML(TiXmlElement* root)
336 {
337  // Convenience comments
338  if (group_states_.size()) // only show comments if there are corresponding elements
339  {
340  TiXmlComment* comment = new TiXmlComment();
341  comment->SetValue("GROUP STATES: Purpose: Define a named state for a particular group, in terms of joint values. "
342  "This is useful to define states like 'folded arms'");
343  root->LinkEndChild(comment);
344  }
345 
346  for (std::vector<srdf::Model::GroupState>::const_iterator state_it = group_states_.begin();
347  state_it != group_states_.end(); ++state_it)
348  {
349  // Create new element for each group state
350  TiXmlElement* state = new TiXmlElement("group_state");
351  state->SetAttribute("name", state_it->name_);
352  state->SetAttribute("group", state_it->group_);
353  root->LinkEndChild(state);
354 
355  // Add all joints
356  for (std::map<std::string, std::vector<double> >::const_iterator value_it = state_it->joint_values_.begin();
357  value_it != state_it->joint_values_.end(); ++value_it)
358  {
359  TiXmlElement* joint = new TiXmlElement("joint");
360  joint->SetAttribute("name", value_it->first); // joint name
361  joint->SetDoubleAttribute("value", value_it->second[0]); // joint value
362 
363  // TODO: use the vector to support multi-DOF joints
364  state->LinkEndChild(joint);
365  }
366  }
367 }
368 
369 // ******************************************************************************************
370 // Generate XML for SRDF end effectors
371 // ******************************************************************************************
372 void SRDFWriter::createEndEffectorsXML(TiXmlElement* root)
373 {
374  // Convenience comments
375  if (end_effectors_.size()) // only show comments if there are corresponding elements
376  {
377  TiXmlComment* comment = new TiXmlComment();
378  comment->SetValue("END EFFECTOR: Purpose: Represent information about an end effector.");
379  root->LinkEndChild(comment);
380  }
381 
382  for (std::vector<srdf::Model::EndEffector>::const_iterator effector_it = end_effectors_.begin();
383  effector_it != end_effectors_.end(); ++effector_it)
384  {
385  // Create new element for each link pair
386  TiXmlElement* effector = new TiXmlElement("end_effector");
387  effector->SetAttribute("name", effector_it->name_);
388  effector->SetAttribute("parent_link", effector_it->parent_link_);
389  effector->SetAttribute("group", effector_it->component_group_);
390  if (!effector_it->parent_group_.empty())
391  effector->SetAttribute("parent_group", effector_it->parent_group_);
392  root->LinkEndChild(effector);
393  }
394 }
395 
396 // ******************************************************************************************
397 // Generate XML for SRDF virtual joints
398 // ******************************************************************************************
399 void SRDFWriter::createVirtualJointsXML(TiXmlElement* root)
400 {
401  // Convenience comments
402  if (virtual_joints_.size()) // only show comments if there are corresponding elements
403  {
404  TiXmlComment* comment = new TiXmlComment();
405  comment->SetValue("VIRTUAL JOINT: Purpose: this element defines a virtual joint between a robot link and an "
406  "external frame of reference (considered fixed with respect to the robot)");
407  root->LinkEndChild(comment);
408  }
409 
410  for (std::vector<srdf::Model::VirtualJoint>::const_iterator virtual_it = virtual_joints_.begin();
411  virtual_it != virtual_joints_.end(); ++virtual_it)
412  {
413  // Create new element for each link pair
414  TiXmlElement* virtual_joint = new TiXmlElement("virtual_joint");
415  virtual_joint->SetAttribute("name", virtual_it->name_);
416  virtual_joint->SetAttribute("type", virtual_it->type_);
417  virtual_joint->SetAttribute("parent_frame", virtual_it->parent_frame_);
418  virtual_joint->SetAttribute("child_link", virtual_it->child_link_);
419 
420  root->LinkEndChild(virtual_joint);
421  }
422 }
423 
424 void SRDFWriter::createPassiveJointsXML(TiXmlElement* root)
425 {
426  if (passive_joints_.size())
427  {
428  TiXmlComment* comment = new TiXmlComment();
429  comment->SetValue("PASSIVE JOINT: Purpose: this element is used to mark joints that are not actuated");
430  root->LinkEndChild(comment);
431  }
432  for (std::vector<srdf::Model::PassiveJoint>::const_iterator p_it = passive_joints_.begin();
433  p_it != passive_joints_.end(); ++p_it)
434  {
435  // Create new element for each link pair
436  TiXmlElement* p_joint = new TiXmlElement("passive_joint");
437  p_joint->SetAttribute("name", p_it->name_);
438  root->LinkEndChild(p_joint);
439  }
440 }
441 } // namespace srdf
void createEndEffectorsXML(TiXmlElement *root)
void createDisabledCollisionsXML(TiXmlElement *root)
Representation of semantic information about the robot.
Definition: model.h:52
void createGroupStatesXML(TiXmlElement *root)
void updateSRDFModel(const urdf::ModelInterface &robot_model)
void initModel(const urdf::ModelInterface &robot_model, const srdf::Model &srdf_model)
Definition: srdf_writer.cpp:78
std::vector< srdf::Model::VirtualJoint > virtual_joints_
Definition: srdf_writer.h:169
void createPassiveJointsXML(TiXmlElement *root)
std::vector< srdf::Model::DisabledCollision > disabled_collisions_
Definition: srdf_writer.h:172
std::vector< srdf::Model::EndEffector > end_effectors_
Definition: srdf_writer.h:170
std::vector< srdf::Model::LinkSpheres > link_sphere_approximations_
Definition: srdf_writer.h:171
std::string robot_name_
Definition: srdf_writer.h:179
void createVirtualJointsXML(TiXmlElement *root)
srdf::ModelSharedPtr srdf_model_
Definition: srdf_writer.h:176
void createLinkSphereApproximationsXML(TiXmlElement *root)
bool writeSRDF(const std::string &file_path)
Main namespace.
Definition: model.h:49
TiXmlDocument generateSRDF()
void createGroupsXML(TiXmlElement *root)
bool initString(const urdf::ModelInterface &robot_model, const std::string &srdf_string)
Definition: srdf_writer.cpp:61
std::vector< srdf::Model::Group > groups_
Definition: srdf_writer.h:167
std::string getSRDFString()
std::vector< srdf::Model::GroupState > group_states_
Definition: srdf_writer.h:168
std::vector< srdf::Model::PassiveJoint > passive_joints_
Definition: srdf_writer.h:173


srdfdom
Author(s): Ioan Sucan , Guillaume Walck
autogenerated on Mon Feb 28 2022 23:49:16