Authors:?Michel Hidalgo
Date Written: 2019-09
Last Modified: 2021-08
As it was the case in ROS 1, ROS 2 nodes allow configuration via command line arguments to a certain degree. In ROS 2, this interface had to become more complex to cope with a larger set of configuration options, an ambiguity in remapping rules and parameter assignment syntax (as a result of the leading underscore name convention for hidden resources), a one-to-many relationship between executables and nodes, to name a few.
Because of this, increasingly precise addressing mechanisms as well as leading double underscores (__
) in some positional arguments, both natural extensions of existing ROS 1 command line features, are combined with ROS 2 specific command line flags. Flags, in contrast with other custom syntax alternatives, are:
Unfortunately, since these flags coexist with user-defined ones, additional guarding and extraction devices must be put in place – one of the reasons why these were avoided entirely in ROS 1 command lines.
To prevent ROS specific command line flags from colliding with user-defined ones, the former are scoped using the?--ros-args
?flag and a trailing double dash token (--
):
ros2 run some_package some_node [<user-defined-arg-0>...<user-defined-arg-N>] \
--ros-args [<ros-specific-arg-0>...] -- [<user-defined-arg-N+1>...]
Note that?--ros-args --
?i.e. an empty set is a valid invocation.
If no user defined arguments are provided after ROS specific arguments are, the double dash token (--
) may be elided:
ros2 run some_package some_node [<user-defined-arg-0>...] --ros-args [<ros-specific-arg-0>...]
Note that a sole trailing?--ros-args
?remains a valid invocation.
More than one set of ROS specific flags may appear in the same command line:
ros2 run some_package some_node --ros-args [<ros-specific-arg-0>...<ros-specific-arg-N>] -- \
[<user-defined-arg-0>...] --ros-args [<ros-specific-arg-N+1>...]
This way, multiple sources, potentially unaware of each other, can append flags to the command line with no regard for previous sets.
As a quick summary of ROS command line capabilities:
--remap from:=to
?or?-r from:=to
.--param name:=value
?or?-p name:=value
?where value is in YAML format.--params-file path/to/file.yaml
?and a parameters YAML file.--log-level LEVEL_NAME
.--log-config-file path/to/file.config
?and a log configuration file.rosout
, use?--enable-rosout-logs
?or?--disable-rosout-logs
stdout
, use?--enable-stdout-logs
?or?--disable-stdout-logs
--enable-external-lib-logs
?or?--disable-external-lib-logs
--enclave value
?or?-e value
?where value is fully qualified enclave path.For name remapping and parameter assignment, specific nodes can be targeted by prepending the option value with the node name followed by a colon?:
, as in?--remap my_node:from:=to
?and?--param my_node:name:=value
.
Remapping rules may be introduced using the?--remap
/-r
?option. This option takes a single?from:=to
?remapping rule.
As an example, to remap from?foo
?to?bar
?for?some_ros_executable
, one may execute:
ros2 run some_package some_ros_executable --ros-args --remap foo:=bar
or its shorter equivalent:
ros2 run some_package some_ros_executable --ros-args -r foo:=bar
As is, this remapping rule applies to each and every node that?some_ros_executable
?spawns unless explicitly ignored in code. To limit it to?some_node
, one may execute:
ros2 run some_package some_ros_executable --ros-args -r some_node:foo:=bar
Parameter assignment may be achieved using the?--param
/-p
?option. This option takes a single?name:=value
?assignment statement, where?value
?is in?YAML format?and thus YAML type inference rules apply.
As an example, to assign a string value?test
?to a parameter?string_param
?for?some_ros_executable
, one may execute:
ros2 run some_package some_ros_executable --ros-args --param string_param:=test
or its shorter equivalent:
ros2 run some_package some_ros_executable --ros-args -p string_param:=test
As is, this parameter assignment applies to each and every node that?some_ros_executable
?spawns unless explicitly ignored in code. To limit it to?some_node
, one may execute:
ros2 run some_package some_ros_executable --ros-args -p some_node:string_param:=test
Multiple parameter assignments can be performed at once using the?--params-file
?option. This option takes a?YAML?file with the following structure:
node0_name:
ros__parameters:
param0_name: param0_value
...
paramN_name: paramN_value
...
nodeM_name:
ros__parameters:
...
Multiple nodes in a single executable can be targeted this way. Note that YAML type inference rules for parameter values apply.
As an example, to assign a string value?foo
?to a parameter?string_param
?for?some_node
?and a string value?bar
?to that same parameter?string_param
?but for?another_node
?upon running?some_ros_executable
?that contains both, one may execute:
ros2 run some_package some_ros_executable --ros-args --params-file params_file.yaml
where?params_file.yaml
?reads:
some_node:
ros__parameters:
string_param: foo
another_node:
ros__parameters:
string_param: bar
Wildcards can be used for node names and namespaces as described in?Remapping Names.?*
?matches a single token delimeted by slashes (/
).?**
?matches zero or more tokens delimeted by slashes. Partial matches are not allowed (e.g.?foo*
).
For example,
/**:
ros__parameters:
string_param: foo
will set the parameter?string_param
?on all nodes,
/**/some_node:
ros__parameters:
string_param: foo
will set the parameter?string_param
?on nodes named?some_node
?in any namespace,
/foo/*:
ros__parameters:
string_param: foo
will set the parameter?string_param
?on any node in the namespace?/foo
.
Minimum logging level can be externally set either globally or per logger using the?--log-level
?option.
As an example, to set a global logging level to?DEBUG
?for?some_ros_executable
, one may execute:
ros2 run some_package some_ros_executable --ros-args --log-level DEBUG
Loggers can be set using the?--log-level
?option as well:
ros2 run some_package some_ros_executable --ros-args --log-level talker1:=DEBUG --log-level talker2:=WARN --log-level rclcpp:=DEBUG
The minimum logging level of a specific logger will override the globally specified minimum logger level. If a logging level is specified more than once in the passed command line arguments, the last one prevails.
See?rcutils
?and?rcl
?logging documentation for reference on existing logging levels.
External logging may be configured using the?--log-config-file
?option. This option takes a single configuration file, whose format depends on the actual external logging library being used.
As an example, to pass?some_log.config
?configuration file to?some_ros_executable
, one may execute:
ros2 run some_package some_ros_executable --ros-args --log-config-file some_log.config
Logging to?rosout
,?stdout
?and an external logging library can be independently enabled or disabled.
As an example, to disable logging to?rosout
?and?stdout
?but not to an external logging library for?some_ros_executable
, one may execute:
ros2 run some_package some_ros_executable --ros-args --disable-rosout-logs --disable-stdout-logs --enable-external-lib-logs
Logging is fully enabled by default, thus?--enable-*
?options are usually redundant unless a?--disable-*
?option found earlier in the command line is being overridden.
Enclave assignment may be achieved using the?--enclave
/-e
?option. This option takes a single string?value
?assignment statement, where?value
?is a fully qualified enclave path used to locate the respective security artifacts within the configured keystore.
As an example, to assign an enclave path?/foo/bar
?one may execute:
ros2 run some_package some_ros_executable --ros-args --enclave="/foo/bar"
or its shorter equivalent:
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.
Command line argument extraction happens within?rcl
. When an instance of the?--ros-args
?flag is found in?argv
, until either a double dash token (--
) is found or the end of the argument array is reached, all arguments that follow are taken as ROS specific arguments to be parsed as such. Remaining arguments can still be accessed by the user via?rcl
?API.
At the time of writing, most ROS specific arguments target and are thus parsed by?rcl
. This is the case for name remapping rules or parameter assignments flags, to name a few. However, to support ROS specific arguments that target upper ROS layers e.g. a ROS client library like?rclcpp
, arguments unknown to?rcl
?are left unparsed but accessible by these layers, which in turn can continue parsing or eventually warn the user if unknown arguments remain.
Other, alternative designs were under discussion.
Stop using the same?:=
?operator for parameter assignments and name remapping rules and introduce additional operators e.g.?:=
?for parameter assignment and?~=
?for name remapping. This keeps the command line verbosity at a minimum and avoids the need for flags, but is error prone.
Rely on full name addressing to disambiguate operator significance e.g.?rosparam://this:=that
?would result in a?that
?string value being assigned to parameter?this
?while?rosremap://this:=that
?would result in name?this
?being remapped to name?that
. Other URL schemes, specific to each interface type e.g.?rostopic
?and?rosservice
, may also be used to further scope remapping rules. This signficantly increases command line verbosity, but still avoids the need for flags.
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.