rclcpp
rclcpp copied to clipboard
Priority of the different mechanisms to initialize ROS 2 parameters
Half-way between a bug report and a feature request (i.e. imo the current behavior is not correct, i would be ok with changing it or with providing utilities to live with it).
Currently there are a ton of ways to set ROS 2 parameters at startup.
- the value can be set via
--ros-argscommand line arguments - the value can be set in the yaml file
- the value can be set using
rclcpp::NodeOptions().append_parameter_override()and passed to the node constructor - the value can be set when declaring the parameter
IMO these approaches should have the priority as I ordered them.
However, that's not the case and the rclcpp::NodeOptions().parameter_overrides() has the highest priority.
This seems very strange to me.
Consider the following use-case: I have a ROS 2 node, implemented in its own library. This node declares a parameter with a "reasonable default value".
This happens inside the library, the node has no idea in which application it will be used.
Then I have two C++ applications that want to use this node. These may be very different applications and they may want to use a different default value for the parameter, so they set it via rclcpp::NodeOptions.
Lastly, a user who wants to quickly modify a parameter, they may want to use the yaml file, but they can't and they are forced to modify the C++ code and rebuild the application.
Ideas that I discarded:
- the default value declared in the library may make no sense at all for an application, so the C++ code must be able to indicate a new default. Creating a derived class and overriding the function that declares the parameters seems a lot of work and doesn't scale well with the number of parameters and applications using them.
- I don't like passing parameters via command line using
--ros-args: If you have component nodes, you are going to have a lot of nodes in the same executable and I want to set a parameter only in 1 node.
Possible solutions:
- change the priority order, and have yaml file take precedence over the
rclcpp::NodeOptions - add a C++ utility to "override a parameter only if it's not present in the yaml"
Thoughts?
Lastly, a user who wants to quickly modify a parameter, they may want to use the yaml file, but they can't and they are forced to modify the C++ code and rebuild the application.
it means that user cannot to overwrite the parameters with --ros-args --params-file end_user_params.yaml? and this is because parameter_overrides from NodeOptions prevails to arguments(either local or global).
the something we can do right now is ros2 param load <node name> <param file> w/o any code change by end user? but i guess that if parameter is read_only this does not work for this use case.
add a C++ utility to "override a parameter only if it's not present in the yaml"
sounds reasonable to me.
it means that user cannot to overwrite the parameters with --ros-args --params-file end_user_params.yaml?
Yes, if you set a parameter via the NodeOptions, the yaml files will be ignored.
Note that you could still modify the parameter via something like --ros-args -p param_name:=param_value, but this is not an acceptable solution as it won't scale for applications with hundreds of parameters and multiple (composed) ROS 2 nodes in the same executable