Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adapt component parser to new xml schema #209

Merged
merged 3 commits into from
Oct 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,9 @@ struct ComponentInfo
*/
std::string name;
/**
* \brief type of the component: sensor or actuator.
* \brief type of the component: sensor or joint.
*/
std::string type;
/**
* \brief component's class, which will be dynamically loaded.
*/
std::string class_type;
/**
* \brief name of the command interfaces that can be set, e.g. "position", "velocity", etc.
* Used by joints.
Expand Down
108 changes: 43 additions & 65 deletions hardware_interface/src/component_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ namespace
constexpr const auto kRobotTag = "robot";
constexpr const auto kROS2ControlTag = "ros2_control";
constexpr const auto kHardwareTag = "hardware";
constexpr const auto kClassTypeTag = "classType";
constexpr const auto kClassTypeTag = "plugin";
constexpr const auto kParamTag = "param";
constexpr const auto kJointTag = "joint";
constexpr const auto kSensorTag = "sensor";
constexpr const auto kTransmissionTag = "transmission";
constexpr const auto kCommandInterfaceTypeTag = "commandInterfaceType";
constexpr const auto kStateInterfaceTypeTag = "stateInterfaceType";
constexpr const auto kCommandInterfaceTag = "command_interface";
constexpr const auto kStateInterfaceTag = "state_interface";
constexpr const auto kMinTag = "min";
constexpr const auto kMaxTag = "max";
constexpr const auto kNameAttribute = "name";
constexpr const auto kTypeAttribute = "type";
} // namespace

namespace hardware_interface
Expand Down Expand Up @@ -118,11 +120,11 @@ std::unordered_map<std::string, std::string> parse_parameters_from_xml(

while (params_it) {
// Fill the map with parameters
attr = params_it->FindAttribute("name");
attr = params_it->FindAttribute(kNameAttribute);
if (!attr) {
throw std::runtime_error("no parameter name attribute set in param tag");
}
const std::string parameter_name = params_it->Attribute("name");
const std::string parameter_name = params_it->Attribute(kNameAttribute);
const std::string parameter_value = get_text_for_element(params_it, parameter_name);
parameters[parameter_name] = parameter_value;

Expand All @@ -139,54 +141,36 @@ std::unordered_map<std::string, std::string> parse_parameters_from_xml(
* \return std::vector< std::__cxx11::string > list of interface types
* \throws std::runtime_error if the interfaceType text not set in a tag
*/
std::vector<InterfaceInfo> parse_interfaces_from_xml(
const tinyxml2::XMLElement * interfaces_it, const char * interfaceTag)
hardware_interface::InterfaceInfo parse_interfaces_from_xml(
const tinyxml2::XMLElement * interfaces_it)
{
std::vector<InterfaceInfo> interfaces;

while (interfaces_it) {
hardware_interface::InterfaceInfo interface;

// Joint interfaces have a name attribute
if (std::string(interfaceTag) == "commandInterfaceType") {
const std::string interface_name = get_attribute_value(
interfaces_it, "name",
std::string(interfaceTag));
interface.name = interface_name;

// Optional min/max attributes
std::unordered_map<std::string, std::string> interface_params =
parse_parameters_from_xml(interfaces_it->FirstChildElement(kParamTag));
std::unordered_map<std::string, std::string>::const_iterator interface_param =
interface_params.find(kMinTag);
if (interface_param != interface_params.end()) {
interface.min = interface_param->second;
}
interface_param = interface_params.find(kMaxTag);
if (interface_param != interface_params.end()) {
interface.max = interface_param->second;
}
}
// State interfaces have an element to define the type, not a name attribute
if (std::string(interfaceTag) == "stateInterfaceType") {
const std::string interface_type = get_text_for_element(
interfaces_it,
std::string(interfaceTag) + " type ");
interface.name = interface_type;
}

interfaces.push_back(interface);
interfaces_it = interfaces_it->NextSiblingElement(interfaceTag);
hardware_interface::InterfaceInfo interface;

const std::string interface_name = get_attribute_value(
interfaces_it, kNameAttribute, interfaces_it->Name());
interface.name = interface_name;

// Optional min/max attributes
std::unordered_map<std::string, std::string> interface_params =
parse_parameters_from_xml(interfaces_it->FirstChildElement(kParamTag));
auto interface_param =
interface_params.find(kMinTag);
if (interface_param != interface_params.end()) {
interface.min = interface_param->second;
}
interface_param = interface_params.find(kMaxTag);
if (interface_param != interface_params.end()) {
interface.max = interface_param->second;
}

return interfaces;
return interface;
}

/**
* \brief Search XML snippet from URDF for information about a control component.
*
* \param component_it pointer to the iterator where component info should be found
* \return robot_control_components::ComponentInfo filled with information about component
* \return ComponentInfo filled with information about component
* \throws std::runtime_error if a component attribute or tag is not found
*/
ComponentInfo parse_component_from_xml(const tinyxml2::XMLElement * component_it)
Expand All @@ -195,29 +179,23 @@ ComponentInfo parse_component_from_xml(const tinyxml2::XMLElement * component_it

// Find name, type and class of a component
component.type = component_it->Name();
component.name = get_attribute_value(component_it, "name", component.type);

const auto * classType_it = component_it->FirstChildElement(kClassTypeTag);
if (!classType_it) {
throw std::runtime_error("no class type tag found in " + component.name);
}
component.class_type = get_text_for_element(classType_it, component.name + " " + kClassTypeTag);
component.name = get_attribute_value(component_it, kNameAttribute, component.type);

// Parse commandInterfaceType tags
const auto * command_interfaces_it = component_it->FirstChildElement(kCommandInterfaceTypeTag);
if (command_interfaces_it) {
component.command_interfaces = parse_interfaces_from_xml(
command_interfaces_it, kCommandInterfaceTypeTag);
// Parse all command interfaces
const auto * command_interfaces_it = component_it->FirstChildElement(kCommandInterfaceTag);
while (command_interfaces_it) {
component.command_interfaces.push_back(parse_interfaces_from_xml(command_interfaces_it));
command_interfaces_it = command_interfaces_it->NextSiblingElement(kCommandInterfaceTag);
}

// Parse stateInterfaceType tags
const auto * state_interfaces_it = component_it->FirstChildElement(kStateInterfaceTypeTag);
if (state_interfaces_it) {
component.state_interfaces = parse_interfaces_from_xml(
state_interfaces_it, kStateInterfaceTypeTag);
// Parse state interfaces
const auto * state_interfaces_it = component_it->FirstChildElement(kStateInterfaceTag);
while (state_interfaces_it) {
component.state_interfaces.push_back(parse_interfaces_from_xml(state_interfaces_it));
state_interfaces_it = state_interfaces_it->NextSiblingElement(kStateInterfaceTag);
}

// Parse paramter tags
// Parse parameters
const auto * params_it = component_it->FirstChildElement(kParamTag);
if (params_it) {
component.parameters = parse_parameters_from_xml(params_it);
Expand All @@ -230,14 +208,14 @@ ComponentInfo parse_component_from_xml(const tinyxml2::XMLElement * component_it
* \brief Parse a control resource from an "ros2_control" tag.
*
* \param ros2_control_it pointer to ros2_control element with informtions about resource.
* \return robot_control_components::ComponentInfo filled with information about the robot
* \return ComponentInfo filled with information about the robot
* \throws std::runtime_error if a attributes or tag are not found
*/
HardwareInfo parse_resource_from_xml(const tinyxml2::XMLElement * ros2_control_it)
{
HardwareInfo hardware;
hardware.name = get_attribute_value(ros2_control_it, "name", kROS2ControlTag);
hardware.type = get_attribute_value(ros2_control_it, "type", kROS2ControlTag);
hardware.name = get_attribute_value(ros2_control_it, kNameAttribute, kROS2ControlTag);
hardware.type = get_attribute_value(ros2_control_it, kTypeAttribute, kROS2ControlTag);

// Parse everything under ros2_control tag
hardware.hardware_class_type = "";
Expand Down
Loading