Skip to content

Avoid calling user parameter callbacks for "qos_overrides" parameter changes #1587

@jacobperron

Description

@jacobperron

Feature request

This is less of an explicit request, and more a question about how we should interact with user-defined parameter callbacks.

Feature description

If a user registers a callback with rclcpp::Node::add_on_set_parameters_callback(), should the callback be triggered for any qos_overrides* parameters that are internally created by the node (since #1465)?

For example, it is somewhat common to see user callbacks that look like this:

  auto result = rcl_interfaces::msg::SetParametersResult();
  result.successful = true;

  for (auto parameter : parameters) {
    if (parameter.get_name().compare("user_defined_param") == 0) {
      // do something with the value here ...
    } else {
      string_result << "The parameter " << parameter.get_name() << " is not reconfigurable.\n";
      result.successful = false;
    }
  }

Since #1465, user code doing something like the code above will fail (the node terminates the process) if QoS overrides are enabled, because the parameter validation callback is not aware of the qos_overrides parameters declared by the nodes implementation.

Possible fixes:

  1. Document this pitfall well and provide an example of handling the new "qos_overrides" parameters like:
  auto result = rcl_interfaces::msg::SetParametersResult();
  result.successful = true;

  for (auto parameter : parameters) {
    if (parameter.get_name().compare("user_defined_param") == 0) {
      // do something with the value here ...
+   else if (parameter.name.rfind("qos_overrides", 0) == 0) {
+     // Ignore changes to QoS override parameters here.
+     // Optionally, we could validate QoS values here, but we also have a more convenient mechanism for that when enabling QoS overrides
    } else {
      string_result << "The parameter " << parameter.get_name() << " is not reconfigurable.\n";
      result.successful = false;
    }
  }
  1. Document that rejecting unknown parameters is an anti-pattern
    Just because one user callback doesn't know how to deal with a parameter doesn't mean that it should reject it. It's possible that another registered callback is expecting said parameter. If one callback rejects a change, then it may prevent other callbacks from getting a chance to handle the change. We would then recommend that the original example above be changed to look like:
  auto result = rcl_interfaces::msg::SetParametersResult();
  result.successful = true;

  for (auto parameter : parameters) {
    if (parameter.get_name().compare("user_defined_param") == 0) {
      // do something with the value here ...
+  }
-   } else {
-     string_result << "The parameter " << parameter.get_name() << " is not reconfigurable.\n";
-     result.successful = false;
-   }
  }
  1. Change the rclcpp implementation to avoid calling user-defined callbacks for qos_overrides parameters
    This would make all existing code work as-is, but it is a little odd that qos_overrides parameters are not passed to user callbacks when other default node params, like use_sim_time are.

Implementation considerations

Whatever we choose, it would be good to resolve this prior to the Galactic release so there is a clear path forward for users porting to Galactic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions