@@ -117,8 +117,16 @@ std::string get_attribute_value(
117117 attr = element_it->FindAttribute (attribute_name);
118118 if (!attr)
119119 {
120+ const char * name = element_it->Attribute (kNameAttribute );
121+ if (name && std::strlen (name) > 0 )
122+ {
123+ throw std::runtime_error (
124+ fmt::format (
125+ FMT_COMPILE (" no attribute '{}' in '{}' tag with name '{}'" ), attribute_name, tag_name,
126+ name));
127+ }
120128 throw std::runtime_error (
121- fmt::format (FMT_COMPILE (" no attribute {} in {} tag" ), attribute_name, tag_name));
129+ fmt::format (FMT_COMPILE (" no attribute '{}' in '{}' tag" ), attribute_name, tag_name));
122130 }
123131 return ros2_control::strip (element_it->Attribute (attribute_name));
124132}
@@ -337,7 +345,7 @@ int parse_thread_priority_attribute(const tinyxml2::XMLElement * elem)
337345 * \throws std::runtime_error if a component attribute or tag is not found
338346 */
339347std::unordered_map<std::string, std::string> parse_parameters_from_xml (
340- const tinyxml2::XMLElement * params_it)
348+ const tinyxml2::XMLElement * params_it, const std::string & context_name )
341349{
342350 std::unordered_map<std::string, std::string> parameters;
343351 const tinyxml2::XMLAttribute * attr;
@@ -348,7 +356,10 @@ std::unordered_map<std::string, std::string> parse_parameters_from_xml(
348356 attr = params_it->FindAttribute (kNameAttribute );
349357 if (!attr)
350358 {
351- throw std::runtime_error (" no parameter name attribute set in param tag" );
359+ throw std::runtime_error (
360+ fmt::format (
361+ FMT_COMPILE (" no parameter name attribute set in param tag{}" ),
362+ context_name.empty () ? " " : " for '" + context_name + " '" ));
352363 }
353364 const std::string parameter_name = ros2_control::strip (params_it->Attribute (kNameAttribute ));
354365 const std::string parameter_value =
@@ -368,7 +379,7 @@ std::unordered_map<std::string, std::string> parse_parameters_from_xml(
368379 * \throws std::runtime_error if the interfaceType text not set in a tag
369380 */
370381hardware_interface::InterfaceInfo parse_interfaces_from_xml (
371- const tinyxml2::XMLElement * interfaces_it)
382+ const tinyxml2::XMLElement * interfaces_it, const std::string & context_name )
372383{
373384 hardware_interface::InterfaceInfo interface;
374385
@@ -378,7 +389,7 @@ hardware_interface::InterfaceInfo parse_interfaces_from_xml(
378389
379390 // Optional min/max attributes
380391 std::unordered_map<std::string, std::string> interface_params =
381- parse_parameters_from_xml (interfaces_it->FirstChildElement (kParamTag ));
392+ parse_parameters_from_xml (interfaces_it->FirstChildElement (kParamTag ), context_name );
382393 auto interface_param = interface_params.find (kMinTag );
383394 if (interface_param != interface_params.end ())
384395 {
@@ -414,7 +425,7 @@ hardware_interface::InterfaceInfo parse_interfaces_from_xml(
414425 const auto * params_it = interfaces_it->FirstChildElement (kParamTag );
415426 if (params_it)
416427 {
417- interface.parameters = parse_parameters_from_xml (params_it);
428+ interface.parameters = parse_parameters_from_xml (params_it, context_name );
418429 }
419430
420431 interface.data_type = parse_data_type_attribute (interfaces_it);
@@ -466,7 +477,7 @@ ComponentInfo parse_component_from_xml(const tinyxml2::XMLElement * component_it
466477 const auto * command_interfaces_it = component_it->FirstChildElement (kCommandInterfaceTag );
467478 while (command_interfaces_it)
468479 {
469- InterfaceInfo cmd_info = parse_interfaces_from_xml (command_interfaces_it);
480+ InterfaceInfo cmd_info = parse_interfaces_from_xml (command_interfaces_it, component. name );
470481 cmd_info.enable_limits &= component.enable_limits ;
471482 component.command_interfaces .push_back (cmd_info);
472483 command_interfaces_it = command_interfaces_it->NextSiblingElement (kCommandInterfaceTag );
@@ -476,7 +487,7 @@ ComponentInfo parse_component_from_xml(const tinyxml2::XMLElement * component_it
476487 const auto * state_interfaces_it = component_it->FirstChildElement (kStateInterfaceTag );
477488 while (state_interfaces_it)
478489 {
479- InterfaceInfo state_info = parse_interfaces_from_xml (state_interfaces_it);
490+ InterfaceInfo state_info = parse_interfaces_from_xml (state_interfaces_it, component. name );
480491 state_info.enable_limits &= component.enable_limits ;
481492 component.state_interfaces .push_back (state_info);
482493 state_interfaces_it = state_interfaces_it->NextSiblingElement (kStateInterfaceTag );
@@ -486,7 +497,7 @@ ComponentInfo parse_component_from_xml(const tinyxml2::XMLElement * component_it
486497 const auto * params_it = component_it->FirstChildElement (kParamTag );
487498 if (params_it)
488499 {
489- component.parameters = parse_parameters_from_xml (params_it);
500+ component.parameters = parse_parameters_from_xml (params_it, component. name );
490501 }
491502
492503 return component;
@@ -513,23 +524,25 @@ ComponentInfo parse_complex_component_from_xml(const tinyxml2::XMLElement * comp
513524 const auto * command_interfaces_it = component_it->FirstChildElement (kCommandInterfaceTag );
514525 while (command_interfaces_it)
515526 {
516- component.command_interfaces .push_back (parse_interfaces_from_xml (command_interfaces_it));
527+ component.command_interfaces .push_back (
528+ parse_interfaces_from_xml (command_interfaces_it, component.name ));
517529 command_interfaces_it = command_interfaces_it->NextSiblingElement (kCommandInterfaceTag );
518530 }
519531
520532 // Parse state interfaces
521533 const auto * state_interfaces_it = component_it->FirstChildElement (kStateInterfaceTag );
522534 while (state_interfaces_it)
523535 {
524- component.state_interfaces .push_back (parse_interfaces_from_xml (state_interfaces_it));
536+ component.state_interfaces .push_back (
537+ parse_interfaces_from_xml (state_interfaces_it, component.name ));
525538 state_interfaces_it = state_interfaces_it->NextSiblingElement (kStateInterfaceTag );
526539 }
527540
528541 // Parse parameters
529542 const auto * params_it = component_it->FirstChildElement (kParamTag );
530543 if (params_it)
531544 {
532- component.parameters = parse_parameters_from_xml (params_it);
545+ component.parameters = parse_parameters_from_xml (params_it, component. name );
533546 }
534547
535548 return component;
@@ -574,7 +587,10 @@ TransmissionInfo parse_transmission_from_xml(const tinyxml2::XMLElement * transm
574587 const auto * type_it = transmission_it->FirstChildElement (kPluginNameTag );
575588 if (!type_it)
576589 {
577- throw std::runtime_error (" Missing <plugin> tag of <transmission> element in your URDF." );
590+ throw std::runtime_error (
591+ fmt::format (
592+ FMT_COMPILE (" Missing <plugin> tag of <transmission> element for '{}' in your URDF." ),
593+ transmission.name ));
578594 }
579595 transmission.type = get_text_for_element (type_it, kPluginNameTag );
580596
@@ -598,7 +614,7 @@ TransmissionInfo parse_transmission_from_xml(const tinyxml2::XMLElement * transm
598614 const auto * params_it = transmission_it->FirstChildElement (kParamTag );
599615 if (params_it)
600616 {
601- transmission.parameters = parse_parameters_from_xml (params_it);
617+ transmission.parameters = parse_parameters_from_xml (params_it, transmission. name );
602618 }
603619
604620 return transmission;
@@ -692,7 +708,10 @@ HardwareInfo parse_resource_from_xml(
692708 const auto * type_it = ros2_control_child_it->FirstChildElement (kPluginNameTag );
693709 if (!type_it)
694710 {
695- throw std::runtime_error (" Missing <plugin> tag of <hardware> element in your URDF." );
711+ throw std::runtime_error (
712+ fmt::format (
713+ FMT_COMPILE (" Missing <plugin> tag of <hardware> element for '{}' in your URDF." ),
714+ hardware.name ));
696715 }
697716 hardware.hardware_plugin_name =
698717 get_text_for_element (type_it, std::string (" hardware " ) + kPluginNameTag );
@@ -704,7 +723,7 @@ HardwareInfo parse_resource_from_xml(
704723 const auto * params_it = ros2_control_child_it->FirstChildElement (kParamTag );
705724 if (params_it)
706725 {
707- hardware.hardware_parameters = parse_parameters_from_xml (params_it);
726+ hardware.hardware_parameters = parse_parameters_from_xml (params_it, hardware. name );
708727 }
709728 }
710729 else if (std::string (kPropertiesTag ) == ros2_control_child_it->Name ())
@@ -987,7 +1006,8 @@ std::vector<HardwareInfo> parse_control_resources_from_urdf(const std::string &
9871006
9881007 if (!ros2_control_it)
9891008 {
990- throw std::runtime_error (fmt::format (FMT_COMPILE (" no {} tag" ), kROS2ControlTag ));
1009+ throw std::runtime_error (
1010+ fmt::format (FMT_COMPILE (" no '{}' tag found in the URDF" ), kROS2ControlTag ));
9911011 }
9921012
9931013 std::vector<HardwareInfo> hardware_info;
0 commit comments