Skip to content

Commit 7fbb2e0

Browse files
committed
Add functions to validate URDF against XSD and extract ROS2 Control XSD tag
1 parent 3d287e3 commit 7fbb2e0

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

hardware_interface/include/hardware_interface/component_validator.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,19 @@ bool validate_urdf_file_path_with_xsd(
4545

4646
} // namespace hardware_interface
4747

48+
/// Validate URDF against an XSD file provides in URDF itself
49+
/**
50+
* \param[in] urdf string with robot's urdf
51+
* \return true if the URDF is valid according to the XSD, false otherwise
52+
*/
53+
bool validate_urdf_with_xsd_tag(const std::string & urdf);
54+
55+
/// Extract ROS2 Control XSD tag from URDF
56+
/**
57+
* \param[in] urdf string with robot's urdf contains xmlns:ros2_control
58+
* \param[out] string of xlmns:ros2_control
59+
* \return true if extraction successful else false
60+
*/
61+
bool extract_ros2_control_xsd_tag(const std::string & urdf, std::string & ros2_control_xsd);
62+
4863
#endif // HARDWARE_INTERFACE__COMPONENT_VALIDATOR_HPP_

hardware_interface/src/component_validator.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#include <cstring>
1516
#include <fstream>
1617
#include <sstream>
1718

@@ -87,4 +88,63 @@ bool validate_urdf_file_path_with_xsd(
8788
return validate_urdf_with_xsd(urdf, xsd_file_path);
8889
}
8990

91+
bool validate_urdf_with_xsd_tag(const std::string & urdf)
92+
{
93+
if (urdf.empty())
94+
{
95+
throw std::runtime_error("empty URDF passed to robot");
96+
}
97+
// extract xmlns tag from the urdf
98+
std::string ros2_control_xsd;
99+
bool result = extract_ros2_control_xsd_tag(urdf, ros2_control_xsd);
100+
if (!result)
101+
{
102+
return false;
103+
}
104+
return validate_urdf_with_xsd(urdf, ros2_control_xsd);
105+
}
106+
107+
bool extract_ros2_control_xsd_tag(const std::string & urdf, std::string & ros2_control_xsd)
108+
{
109+
if (urdf.empty())
110+
{
111+
throw std::runtime_error("empty URDF passed to robot");
112+
}
113+
114+
xmlDocPtr doc = xmlReadMemory(urdf.c_str(), static_cast<int>(urdf.size()), nullptr, nullptr, 0);
115+
if (!doc)
116+
{
117+
return {};
118+
}
119+
120+
xmlNodePtr root = xmlDocGetRootElement(doc);
121+
if (root)
122+
{
123+
auto check = [&](xmlNsPtr ns) -> bool
124+
{
125+
if (
126+
ns && ns->prefix &&
127+
std::strcmp(reinterpret_cast<const char *>(ns->prefix), "ros2_control") == 0)
128+
{
129+
ros2_control_xsd = ns->href ? reinterpret_cast<const char *>(ns->href) : "";
130+
return true;
131+
}
132+
return false;
133+
};
134+
if (!check(root->ns))
135+
{
136+
for (xmlNsPtr cur = root->nsDef; cur; cur = cur->next)
137+
{
138+
if (check(cur))
139+
{
140+
break;
141+
}
142+
}
143+
}
144+
}
145+
146+
xmlFreeDoc(doc);
147+
return false;
148+
}
149+
90150
} // namespace hardware_interface

0 commit comments

Comments
 (0)