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

[roslaunch] raise ArgException in _arg_tag to avoid unexpected error in roslaunch.config.load_config_default #2371

Open
wants to merge 2 commits into
base: noetic-devel
Choose a base branch
from

Conversation

knorth55
Copy link
Contributor

@knorth55 knorth55 commented Apr 11, 2024

this PR fix a bug in roslaunch.config.load_config_default

Overview

When we have one arg with no default value, and another arg defined by the former arg,
_arg_tag in roslaunch.xmlloader.XmlLoader raises XmlParseException, even when ignore_unset_args is True.

this PR change to raise ArgException as expected not to raise the error when ignore_unset_args is True.
this function is used in roslaunch_add_file_check in cmake,
and test always fail when we have this kind of launches.

How to reproduce the error

launch file

<launch>
  <arg name="input1"/>
  <arg name="input2" value="$(arg input1)"/>

  <node name="usb_cam_node" pkg="usb_cam" type="usb_cam_node">
    <remap from="~input" to="$(arg input2)"/>
  </node>
</launch>

ipython

In [1]: from rosmaster import DEFAULT_MASTER_PORT

In [2]: import roslaunch

In [3]: roslaunch.config.load_config_default(['./sample.launch'], DEFAULT_MASTER_PORT, verbose=False, ignore_unset_args=True)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/substitution_args.py:278, in _eval_arg(name, args)
    277 try:
--> 278     return args[name]
    279 except KeyError:

KeyError: 'input1'

During handling of the above exception, another exception occurred:

ArgException                              Traceback (most recent call last)
File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/xmlloader.py:297, in XmlLoader._arg_tag(self, tag, context, ros_config, verbose)
    296 (name,) = self.reqd_attrs(tag, context, ('name',))
--> 297 value, default, doc = self.opt_attrs(tag, context, ('value', 'default', 'doc'))
    299 if value is not None and default is not None:

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/xmlloader.py:208, in XmlLoader.opt_attrs(self, tag, context, attrs)
    207         return None
--> 208 return [self.resolve_args(tag_value(tag,a), context) for a in attrs]

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/xmlloader.py:208, in <listcomp>(.0)
    207         return None
--> 208 return [self.resolve_args(tag_value(tag,a), context) for a in attrs]

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/xmlloader.py:189, in XmlLoader.resolve_args(self, args, context)
    188     context.resolve_dict['filename'] = context.filename
--> 189     return substitution_args.resolve_args(args, context=context.resolve_dict, resolve_anon=self.resolve_anon)
    190 else:

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/substitution_args.py:387, in resolve_args(arg_str, context, resolve_anon, filename)
    380 commands = {
    381     'env': _env,
    382     'optenv': _optenv,
   (...)
    385     'arg': _arg,
    386 }
--> 387 resolved = _resolve_args(arg_str, context, resolve_anon, commands)
    388 # then resolve 'find' as it requires the subsequent path to be expanded already

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/substitution_args.py:405, in _resolve_args(arg_str, context, resolve_anon, commands)
    404     if command in commands:
--> 405         resolved = commands[command](resolved, a, args, context)
    406 return resolved

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/substitution_args.py:296, in _arg(resolved, a, args, context)
    295     context['arg'] = {}
--> 296 return resolved.replace("$(%s)" % a, _eval_arg(name=args[0], args=context['arg']))

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/substitution_args.py:280, in _eval_arg(name, args)
    279 except KeyError:
--> 280     raise ArgException(name)

ArgException: input1

During handling of the above exception, another exception occurred:

XmlParseException                         Traceback (most recent call last)
File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/config.py:461, in load_config_default(roslaunch_files, port, roslaunch_strs, loader, verbose, assign_machines, ignore_unset_args)
    460     logger.info('loading config file %s'%f)
--> 461     loader.load(f, config, argv=args, verbose=verbose)
    462 except roslaunch.xmlloader.XmlParseException as e:

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/xmlloader.py:763, in XmlLoader.load(self, filename, ros_config, core, argv, verbose)
    762     ros_config.add_roslaunch_file(filename)
--> 763     self._load_launch(launch, ros_config, is_core=core, filename=filename, argv=argv, verbose=verbose)
    764 except ArgException as e:

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/xmlloader.py:735, in XmlLoader._load_launch(self, launch, ros_config, is_core, filename, argv, verbose)
    734     print("WARNING: ignoring defunct <master /> tag", file=sys.stderr)
--> 735 self._recurse_load(ros_config, launch.childNodes, self.root_context, None, is_core, verbose)

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/xmlloader.py:660, in XmlLoader._recurse_load(self, ros_config, tags, context, default_machine, is_core, verbose)
    659 if name == 'arg':
--> 660     self._arg_tag(tag, context, ros_config, verbose=verbose)
    661 elif self.args_only:
    662     # do not load other tags

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/xmlloader.py:96, in ifunless.<locals>.call(*args, **kwds)
     95 if ifunless_test(args[0], args[1], args[2]):
---> 96     return f(*args, **kwds)

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/xmlloader.py:306, in XmlLoader._arg_tag(self, tag, context, ros_config, verbose)
    305 except substitution_args.ArgException as e:
--> 306     raise XmlParseException(
    307         "arg '%s' is not defined. \n\nArg xml is %s"%(e, tag.toxml()))
    308 except ResourceNotFound as e:

XmlParseException: arg 'input1' is not defined.

Arg xml is <arg name="input2" value="$(arg input1)"/>

During handling of the above exception, another exception occurred:

RLException                               Traceback (most recent call last)
Cell In[3], line 1
----> 1 roslaunch.config.load_config_default(['./sample.launch'], DEFAULT_MASTER_PORT, verbose=False, ignore_unset_args=True)

File /opt/ros/noetic/lib/python3/dist-packages/roslaunch/config.py:463, in load_config_default(roslaunch_files, port, roslaunch_strs, loader, verbose, assign_machines, ignore_unset_args)
    461     loader.load(f, config, argv=args, verbose=verbose)
    462 except roslaunch.xmlloader.XmlParseException as e:
--> 463     raise RLException(e)
    464 except roslaunch.loader.LoadException as e:
    465     raise RLException(e)

RLException: arg 'input1' is not defined.

Arg xml is <arg name="input2" value="$(arg input1)"/>

Expected behavior with this PR.

with the same launch file, load_config_default should not raise the error when ignore_unset_args is true.

In [1]: from rosmaster import DEFAULT_MASTER_PORT

In [2]: import roslaunch

In [3]: roslaunch.config.load_config_default(['./sample.launch'], DEFAULT_MASTER_PORT, verbose=False, ignore_unset_args=True)
Out[3]: <roslaunch.config.ROSLaunchConfig at 0x7f5e96cd8af0>

@knorth55 knorth55 force-pushed the ignore-unset-args-special-case branch from 0c0e756 to 870817e Compare April 11, 2024 23:47
@knorth55 knorth55 changed the title [roslaunch] raise ArgException in _arg_tag to avoid unexpected error in roslaunch.config.load_config_default [roslaunch] raise ArgException in _arg_tag to avoid unexpected error in roslaunch.config.load_config_default Apr 11, 2024
@knorth55 knorth55 closed this Sep 9, 2024
@knorth55 knorth55 reopened this Sep 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant