transmission_parser.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2013, Open Source Robotics Foundation
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 the Open Source Robotics Foundation
18  * nor the names of its contributors may be
19  * used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *********************************************************************/
35 
36 #include <sstream>
38 
39 namespace transmission_interface
40 {
41 
42 bool TransmissionParser::parse(const std::string& urdf, std::vector<TransmissionInfo>& transmissions)
43 {
44  // initialize TiXmlDocument doc with a string
45  TiXmlDocument doc;
46  if (!doc.Parse(urdf.c_str()) && doc.Error())
47  {
48  ROS_ERROR("Can't parse transmissions. Invalid robot description.");
49  return false;
50  }
51 
52  // Find joints in transmission tags
53  TiXmlElement *root = doc.RootElement();
54 
55  // Constructs the transmissions by parsing custom xml.
56  TiXmlElement *trans_it = nullptr;
57  for (trans_it = root->FirstChildElement("transmission"); trans_it;
58  trans_it = trans_it->NextSiblingElement("transmission"))
59  {
61 
62  // Transmission name
63  if(trans_it->Attribute("name"))
64  {
65  transmission.name_ = trans_it->Attribute("name");
66  if (transmission.name_.empty())
67  {
68  ROS_ERROR_STREAM_NAMED("parser","Empty name attribute specified for transmission.");
69  continue;
70  }
71  }
72  else
73  {
74  ROS_ERROR_STREAM_NAMED("parser","No name attribute specified for transmission.");
75  continue;
76  }
77 
78  // Transmission type
79  TiXmlElement *type_child = trans_it->FirstChildElement("type");
80  if(!type_child)
81  {
82  ROS_ERROR_STREAM_NAMED("parser","No type element found in transmission '"
83  << transmission.name_ << "'.");
84  continue;
85  }
86  if (!type_child->GetText())
87  {
88  ROS_ERROR_STREAM_NAMED("parser","Skipping empty type element in transmission '"
89  << transmission.name_ << "'.");
90  continue;
91  }
92  transmission.type_ = type_child->GetText();
93 
94  // Load joints
95  if(!parseJoints(trans_it, transmission.joints_))
96  {
97  ROS_ERROR_STREAM_NAMED("parser","Failed to load joints for transmission '"
98  << transmission.name_ << "'.");
99  continue;
100  }
101 
102  // Load actuators
103  if(!parseActuators(trans_it, transmission.actuators_))
104  {
105  ROS_ERROR_STREAM_NAMED("parser","Failed to load actuators for transmission '"
106  << transmission.name_ << "'.");
107  continue;
108  }
109 
110  // Save loaded transmission
111  transmissions.push_back(transmission);
112 
113  } // end for <transmission>
114 
115  if( transmissions.empty() )
116  {
117  ROS_DEBUG_STREAM_NAMED("parser", "No valid transmissions found.");
118  }
119 
120  return true;
121 }
122 
123 bool TransmissionParser::parseJoints(TiXmlElement *trans_it, std::vector<JointInfo>& joints)
124 {
125  // Loop through each available joint
126  TiXmlElement *joint_it = nullptr;
127  for (joint_it = trans_it->FirstChildElement("joint"); joint_it;
128  joint_it = joint_it->NextSiblingElement("joint"))
129  {
130  // Create new joint
132 
133  // Joint name
134  if(joint_it->Attribute("name"))
135  {
136  joint.name_ = joint_it->Attribute("name");
137  if (joint.name_.empty())
138  {
139  ROS_ERROR_STREAM_NAMED("parser","Empty name attribute specified for joint.");
140  continue;
141  }
142  }
143  else
144  {
145  ROS_ERROR_STREAM_NAMED("parser","No name attribute specified for joint.");
146  return false;
147  }
148 
149  TiXmlElement *role_it = joint_it->FirstChildElement("role");
150  if(role_it)
151  {
152  joint.role_ = role_it->GetText() ? role_it->GetText() : std::string();
153  }
154 
155  // Hardware interfaces (required)
156  TiXmlElement *hw_iface_it = nullptr;
157  for (hw_iface_it = joint_it->FirstChildElement("hardwareInterface"); hw_iface_it;
158  hw_iface_it = hw_iface_it->NextSiblingElement("hardwareInterface"))
159  {
160  if(!hw_iface_it) {continue;}
161  if (!hw_iface_it->GetText())
162  {
163  ROS_DEBUG_STREAM_NAMED("parser","Skipping empty hardware interface element in joint '"
164  << joint.name_ << "'.");
165  continue;
166  }
167  const std::string hw_iface_name = hw_iface_it->GetText();
168  joint.hardware_interfaces_.push_back(hw_iface_name);
169  }
170  if (joint.hardware_interfaces_.empty())
171  {
172  ROS_ERROR_STREAM_NAMED("parser","No valid hardware interface element found in joint '"
173  << joint.name_ << "'.");
174  continue;
175  }
176 
177  // Joint xml element
178  std::stringstream ss;
179  ss << *joint_it;
180  joint.xml_element_ = ss.str();
181 
182  // Add joint to vector
183  joints.push_back(joint);
184  }
185 
186  if(joints.empty())
187  {
188  ROS_DEBUG_NAMED("parser","No valid joint element found.");
189  return false;
190  }
191 
192  return true;
193 }
194 
195 bool TransmissionParser::parseActuators(TiXmlElement *trans_it, std::vector<ActuatorInfo>& actuators)
196 {
197  // Loop through each available actuator
198  TiXmlElement *actuator_it = nullptr;
199  for (actuator_it = trans_it->FirstChildElement("actuator"); actuator_it;
200  actuator_it = actuator_it->NextSiblingElement("actuator"))
201  {
202  // Create new actuator
204 
205  // Actuator name
206  if(actuator_it->Attribute("name"))
207  {
208  actuator.name_ = actuator_it->Attribute("name");
209  if (actuator.name_.empty())
210  {
211  ROS_ERROR_STREAM_NAMED("parser","Empty name attribute specified for actuator.");
212  continue;
213  }
214  }
215  else
216  {
217  ROS_ERROR_STREAM_NAMED("parser","No name attribute specified for actuator.");
218  return false;
219  }
220 
221  // Hardware interfaces (optional)
222  TiXmlElement *hw_iface_it = nullptr;
223  for (hw_iface_it = actuator_it->FirstChildElement("hardwareInterface"); hw_iface_it;
224  hw_iface_it = hw_iface_it->NextSiblingElement("hardwareInterface"))
225  {
226  if(!hw_iface_it) {continue;}
227  if (!hw_iface_it->GetText())
228  {
229  ROS_DEBUG_STREAM_NAMED("parser","Skipping empty hardware interface element in actuator '"
230  << actuator.name_ << "'.");
231  continue;
232  }
233  const std::string hw_iface_name = hw_iface_it->GetText();
234  actuator.hardware_interfaces_.push_back(hw_iface_name);
235  }
236  if (actuator.hardware_interfaces_.empty())
237  {
238  ROS_DEBUG_STREAM_NAMED("parser","No valid hardware interface element found in actuator '"
239  << actuator.name_ << "'.");
240  // continue; // NOTE: Hardware interface is optional, so we keep on going
241  }
242 
243  // Actuator xml element
244  std::stringstream ss;
245  ss << *actuator_it;
246  actuator.xml_element_ = ss.str();
247 
248  // Add actuator to vector
249  actuators.push_back(actuator);
250  }
251 
252  if(actuators.empty())
253  {
254  ROS_DEBUG_NAMED("parser","No valid actuator element found.");
255  return false;
256  }
257 
258  return true;
259 }
260 
261 } // namespace
static bool parse(const std::string &urdf_string, std::vector< TransmissionInfo > &transmissions)
Parses the transmission elements of a URDF.
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_ERROR_STREAM_NAMED(name, args)
Contains semantic info about a given actuator loaded from XML (URDF)
Parses <transmission> elements into corresponding structs from XML (URDF).
Contains semantic info about a given joint loaded from XML (URDF)
Contains semantic info about a given transmission loaded from XML (URDF)
std::vector< std::string > hardware_interfaces_
#define ROS_DEBUG_NAMED(name,...)
static bool parseJoints(TiXmlElement *trans_it, std::vector< JointInfo > &joints)
Parses the joint elements within transmission elements of a URDF.
static bool parseActuators(TiXmlElement *trans_it, std::vector< ActuatorInfo > &actuators)
Parses the actuator elements within transmission elements of a URDF.
std::vector< ActuatorInfo > actuators_
#define ROS_ERROR(...)
std::vector< std::string > hardware_interfaces_


transmission_interface
Author(s): Adolfo Rodriguez Tsouroukdissian
autogenerated on Mon Feb 28 2022 23:30:26