Skip to content
Open
Changes from 1 commit
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

The following precedence order applies to parameter assignments:

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

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

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

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

* Assignments targeting a specific node prevail to wildcard assignments.
* Within a file, in case of the contradictory assignments, the last assignment applies (i.e.: the one nearer to the end of the file).
* 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:

* 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.
The parameter file is assigning `my_int` to `2`.
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.