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

Clarify ros2 arguments precedence #289

Open
wants to merge 10 commits into
base: gh-pages
Choose a base branch
from
Open
113 changes: 113 additions & 0 deletions articles/150_ros_command_line_arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,72 @@ ros2 run some_package some_ros_executable --ros-args -e "/foo/bar"

As is, this enclave assignment applies to each and every Domain Participant that `some_ros_executable` spawns unless explicitly ignored in code or overridden via security environment variables.

#### Precedence order of command line arguments

The following precedence order applies to parameter assignments:
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved

* Arguments targeting a specific node prevail arguments targeting all the nodes in the executable.
* Arguments are parsed from the leftmost to the rightmost. In case of contradictory assignments, the rightmost argument prevails.
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved

As an example:

```sh
ros2 run some_package some_exec --ros-args -r my_topic:=asd -r my_topic:=bsd -p my_node:my_param:=1 -p my_param:=2 -p another_param:=1 -p another_param:=2
```

Supposing the executable only has a node named `my_node`, this will result in `my_param` being set to `1` and `another_param` being set to `2`.
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved

The following precedence order applies to remapping rules:

* Arguments are parsed from the leftmost to the rightmost. In case of contradictory assignments, the leftmost argument prevails.
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved
* Arguments targeting a specific node DO NOT prevail arguments targeting all the nodes in the executable.

As an example:

```sh
ros2 run some_package some_exec --ros-args -r my_topic:=first -r my_topic:=second -r my_node:another_topic:=first -r another_topic:=second
```

Supposing the executable only has a node named `my_node`, this will result in `my_topic` being remapped to `first` and `another_topic` being remapped to `first`.
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved

In the case of parameter files, the following precedence apply:

* Assignments targeting a specific node prevail to wildcard assignments.
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved
* Within a file, in case of the contradictory assignments, the last assignment applies (i.e.: the one nearer to the end of the file).
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved
* Parameter files have the same precedence that command line parameter assignments. They are parsed from left to right, and the rightmost argument prevails.

As an example:

```yaml
# my_params.yaml
my_node:
ros__parameters:
my_int: 1
my_int: 2
another_int: 1
my_float: 1.0
another_float: 1.0
my_node:
ros__parameters:
another_int: 2
/**:
ros__parameters:
my_int: 3
global_int: 1
```

```sh
ros2 run some_package some_exec --ros-args --params-file my_params.yaml
```

will result in: my_int=2, another_int=2, global_int=1, my_float=1.0, another_float=1.0

```sh
ros2 run some_package some_exec --ros-args -p my_node:global_int:=2 -p my_float:=2.0 --params-file my_params.yaml -p my_float:=3.0 -p my_node:another_float:=2.0
```

will result in: my_int=2, another_int=2, global_int=2, my_float=1.0, another_float=2.0

## Implementation

### Extraction
Expand Down Expand Up @@ -255,3 +321,50 @@ This signficantly increases command line verbosity, but still avoids the need fo
Remove the need for double dash tokens (`--`), conventionally used to signify the end of CLI options for a command, by adding the `--ros-` prefix to all ROS specific command line flags e.g. `--ros-remap`, `--ros-param`, etc.
In exchange, it makes argument extraction slightly more difficult as all options must be known ahead of time, whereas `--ros-args`-based namespacing can achieve the same with a couple rules.
It also increases command line verbosity.

## Precedence order discussion

There are some issues of the current precedence rules:
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved

* Precedence orders for remapping rules and parameter assignments are inconsistent.
* In the past, inconsistencies were detected between `rclcpp` and `rclpy` ([example issue](https://github.com/ros2/rclcpp/issues/953)).
* Weird interaction with launch files.

Example of the last item:

```python
LaunchDescription([
Node(
package='my_pkg',
exec='my_exec',
name='my_node',
parameters=['/path/to/my_params.yaml', {'my_int': '3'}]
)
])
```

Where `my_params.yaml` can be find in *Precedence order of command line arguments* section.
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved
The parameter file is assigning `my_int` to `2`.
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved
Launch cannot know the fully qualified name of the node at launch time, as the node namespace wasn't specified.
Thus, it needs to use a "wildcard" rule for the assignment made in the dictionary, and it won't override the parameter file assignment.

Before https://github.com/ros2/launch_ros/pull/154 was merged, it was impossible to override a parameter assignment in a parameter file that targeted an specific node from a launch file.
Now it's possible by doing:

```python
LaunchDescription([
Node(
package='my_pkg',
exec='my_exec',
name='my_node',
namespace='my_ns',
parameters=['/path/to/my_params.yaml', {'my_int': '3'}]
)
])
```

As the fully qualified node name is known at launch time in this last case, `my_int` will be set to `3`.

Possible solutions:
* Warn when parameter files and parameter dictionaries are combined in `Node`, and the fully qualified node name is not known.
* Modify precedence between wildcard and not wildcard assignments.
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved