rclcpp icon indicating copy to clipboard operation
rclcpp copied to clipboard

Priority of the different mechanisms to initialize ROS 2 parameters

Open alsora opened this issue 1 year ago • 2 comments
trafficstars

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-args command 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?

alsora avatar Jan 18 '24 19:01 alsora

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.

fujitatomoya avatar Jan 30 '24 18:01 fujitatomoya

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

alsora avatar Jan 30 '24 20:01 alsora