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
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
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

##### Parameter assignments

* Arguments targeting a specific node prevail arguments targeting all the nodes in the executable.
* Arguments are parsed left to right. In case of overlapping parameter assignments, the rightmost argument prevails.

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
```

Assuming that `some_exec` only has a node named `my_node`, this will result in `my_param` being set to `1` and `another_param` being set to `2`.

##### Remapping rules

* Arguments are parsed from left to right. In case of overlapping rules, the leftmost argument prevails.
* 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
```

Assuming that `some_exec` only has a node named `my_node`, this will result in `my_topic` being remapped to `first` and `another_topic` being remapped to `first`.

##### Parameter files

* Parameter assignments targeting a specific node prevail over those using wildcards.
* Within a file, in case of the overlapping assignments, the last assignment applies (i.e.: the one closest to EOF).
* 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 with the current precedence rules:

* 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 `2` to `my_int`.
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