Skip to content

Exception when declaring parameters after callback is set #769

Closed
@Karsten1987

Description

@Karsten1987

I am struggling with how to declare parameters for my diagnostic_updater. Specifically, I have the following setup: I am spawning the URG laser driver, which is a node and has a diagnostics updater instance as a class member variable. That diagnostics updater takes a node (or better node interfaces) in its constructor. The diagnostics updater has a parameter period which is meant to be updated dynamically. The URG node itself has multiple laser specific parameters declared as well.

Within code, this kind of looks like this:

Urg::Urg()
: rclcpp::Node("urg_laser_node")
{
  // Get parameters so we can change these later.
  this->declare_parameter<std::string>("ip_address", ip_address_);
  this->declare_parameter<int>("ip_port", ip_port_);
  this->declare_parameter<std::string>("laser_frame_id", laser_frame_id_);
  ...

  this->set_on_parameters_set_callback(std::bind(&UrgNode::param_change_callback, this, std::placeholders::_1));

  // the diagnostics_updater declares another parameter and results in an exception.
  diagnostic_updater_ = std::make_unique<diagnostic_updater::Updater>(
    this->get_node_base_interface(),
    this->get_node_topics_interface(),
    this->get_node_logging_interface(),
    this->get_node_parameters_interface());
  diagnostic_updater_->add("Hardware Status", this, &UrgNode::populateDiagnosticsStatus);
 
  // Having the parameter callback set at the very end, prevents the exception
  // this->set_on_parameters_set_callback(std::bind(&UrgNode::param_change_callback, this, std::placeholders::_1));
}

I am noticing two problems with this:

1.) When having set_on_parameters_set_callback called before initializing the diagnostics updater instance, I am unable to declare any parameter within the diagnostics instance as the assigned callback for the URG node is not aware of the diagnostics parameter and I get an exception:

libc++abi.dylib: terminating with uncaught exception of type rclcpp::exceptions::InvalidParameterValueException: parameter 'urg_node.diagnostics_updater_period' could not be set: The parameter urg_node.diagnostics_updater_period is not part of the reconfigurable parameters.

So I had to make sure that the parameter callback is set at last and no new parameters were declared after that.

2.) When modifying the URG callback in a way to catch a change of parameter for the diagnostics updater (i.e. the parameter "period"), I need public API on the diagnostics updater in order to set/get the current period on it. Plus, every other node which uses diagnostics, e.g. cartographer has to write the same logic in their code.

After thinking about this for a while, I'd like to have the parameter period being solely declared within the diagnostics updater and ideally have a callback for that parameter which is handled within the diagnostics updater itself.
I remember we talked about having multiple callbacks for parameters, especially with cases like use_sim_time. Is that possible with the current dashing API? If not, do you have any suggestions on how to handle that case?

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingmore-information-neededFurther information is required

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions