Description
Bug report
Required Info:
- Operating System:
- Ubuntu 22.04
- Installation type:
- Any
- Version or commit hash:
- Iron / Humble
- DDS implementation:
- Any
- Client library (if applicable):
- rclcpp and rclpy
While implementing parameter services for rclrs, we noticed that the behavior of rclcpp
and rclpy
is inconsistent with the documentation of rcl_interfaces/srv/GetParameterTypes
which says it returns a "List of types which is the same length and order as the provided names." and also "ParameterType.PARAMETER_NOT_SET indicates that the parameter is not currently set.".
However in the implementation of rclcpp and rclpy, if the node is set with allow_undeclared_parameters(false)
and the service request includes an undeclared parameter, you get an empty response back:
$ ros2 service call /minimal_publisher/get_parameter_types rcl_interfaces/srv/GetParameterTypes "{names: [use_sim_time, hello]}"
requester: making request: rcl_interfaces.srv.GetParameterTypes_Request(names=['use_sim_time', 'hello'])
response:
rcl_interfaces.srv.GetParameterTypes_Response(types=[])
This contradicts the documentation for the service, which does not indicate any situation in which the response array would be a different size from the request array.
It seems the current behavior of rclcpp and rclpy was an intentional choice with the rationale that asking about an undeclared parameter should be seen as an error. However the mismatch between the behavior of the client libraries and the service documentation means either:
- the client libraries must be changed to match the service documentation, or
- the service documentation must be changed to match the client library behavior.
I would argue that the current service documentation makes more sense than the client library behavior, so the client libraries should change their behavior to comply with it for the following reasons:
- Returning an empty array is unhelpful whether the client is a human or a program. It provides the least amount of information possible in response to the service request and forces clients to always make multiple service requests in order to reliably detect the values of parameters.
- The concept of declared / undeclared does not even exist in
rcl_interfaces
. I see parameter declaration as an implementation detail for parameter management that's internal to a node. Clients of parameter services should not generally need to be concerned about parameter declaration settings within a node that they are querying, but the current behavior is leaking that abstraction into the behavior of the parameter services. - An undeclared parameter in an
allow_undeclared_parameters(false)
node can be thought of as unsettable, and therefore its value is just permanently unset. Naturally this means any client asking for the value of that parameter should be told that the value of the parameter is unset. - If we guarantee that the response array is always the same size as the request array, we reduce the likelihood that clients will write an accidental buffer overflow while iterating through the request and response arrays simultaneously because they weren't aware of the service behavior diverging due to parameter declaration.
Furthermore if a client calls rcl_interfaces/srv/SetParameters
with an undeclared parameter on a node with allow_undeclared_parameters(false)
then the client libraries should return something like { successful: false, reason: "Parameter is not declared by the node, which only allows declared parameters" }
where the reason
value is a fixed and consistent string literal across all client libraries so that parameter service clients can do a simple string comparison against. I would recommend defining the string literal inside of rcl_interfaces/msg/SetParametersResult
with a name like REASON_UNDECLARED_PARAMETER
. Currently rclcpp
and rclpy
produce different reason
values for this same situation. Admittedly the service documentation says that reason
should only be read by humans, but I think this particular case warrants a fixed and consistent value.
I'm happy to submit PRs for these recommended changes, but I thought I'd open a discussion on this first in case there are any strong objections. Tagging @fujitatomoya @ivanpauno and @wjwwood as the main people who participated in the original discussion.