diff --git a/launch_ros/launch_ros/actions/node.py b/launch_ros/launch_ros/actions/node.py index 8d7377e9..77a8706c 100644 --- a/launch_ros/launch_ros/actions/node.py +++ b/launch_ros/launch_ros/actions/node.py @@ -125,6 +125,7 @@ def __init__( exec_name: Optional[SomeSubstitutionsType] = None, parameters: Optional[SomeParameters] = None, remappings: Optional[SomeRemapRules] = None, + ros_arguments: Optional[Iterable[SomeSubstitutionsType]] = None, arguments: Optional[Iterable[SomeSubstitutionsType]] = None, **kwargs ) -> None: @@ -180,6 +181,9 @@ def __init__( wildcard namespace (`/**`) and other specific parameter declarations may overwrite it. + Using `ros_arguments` is equivalent to using `arguments` with a + prepended '--ros-args' item. + :param: executable the name of the executable to find if a package is provided or otherwise a path to the executable to run. :param: package the package in which the node executable can be found @@ -191,6 +195,7 @@ def __init__( or dictionaries of parameters. :param: remappings ordered list of 'to' and 'from' string pairs to be passed to the node as ROS remapping rules + :param: ros_arguments list of ROS arguments for the node :param: arguments list of extra arguments for the node """ if package is not None: @@ -198,6 +203,7 @@ def __init__( else: cmd = [executable] cmd += [] if arguments is None else arguments + cmd += [] if ros_arguments is None else ['--ros-args'] + ros_arguments # Reserve space for ros specific arguments. # The substitutions will get expanded when the action is executed. cmd += ['--ros-args'] # Prepend ros specific arguments with --ros-args flag @@ -218,6 +224,7 @@ def __init__( self.__node_namespace = namespace self.__parameters = [] if parameters is None else normalized_params self.__remappings = [] if remappings is None else list(normalize_remap_rules(remappings)) + self.__ros_arguments = ros_arguments self.__arguments = arguments self.__expanded_node_name = self.UNSPECIFIED_NODE_NAME diff --git a/test_launch_ros/test/test_launch_ros/actions/test_node.py b/test_launch_ros/test/test_launch_ros/actions/test_node.py index 062b7630..3ed048a5 100644 --- a/test_launch_ros/test/test_launch_ros/actions/test_node.py +++ b/test_launch_ros/test/test_launch_ros/actions/test_node.py @@ -47,11 +47,12 @@ def _assert_launch_no_errors(self, actions): ls.include_launch_description(ld) assert 0 == ls.run() - def _create_node(self, *, parameters=None, remappings=None): + def _create_node(self, *, parameters=None, remappings=None, ros_arguments=None): return launch_ros.actions.Node( package='demo_nodes_py', executable='talker_qos', output='screen', name='my_node', namespace='my_ns', exec_name='my_node_process', + ros_arguments=ros_arguments, arguments=['--number_of_cycles', '1'], parameters=parameters, remappings=remappings, @@ -92,6 +93,13 @@ def test_launch_node_with_remappings(self): for i in range(2): assert expanded_remappings[i] == ('chatter', 'new_chatter') + def test_launch_node_with_ros_arguments(self): + node_action = self._create_node(ros_arguments=['--log-level', 'debug']) + self._assert_launch_no_errors([node_action]) + + cmd_string = ' '.join(node_action.process_details['cmd']) + assert '--ros-args --log-level debug' in cmd_string + def test_launch_required_node(self): # This node will never exit on its own, it'll keep publishing forever. long_running_node = launch_ros.actions.Node(