Description
Feature request
Allow node author to define expected parameters and what happens when an unexpected parameter is set.
Feature description
This issue is a first step towards larger features like parameter constraints (allowed types, read-only parameters, allowed ranges, etc...). These will be ticketed separately.
If a node does not use parameters:
- Universal parameters like
use_sim_time
should still work - Reject attempts to set parameters to give feedback to run-time user
If a node uses parameters and knows all parameters it can use at compile time
- Initial values might be needed if parameter is required and run-time user doesn't set it
- Run-time user may set a new value for a known parameter provided it is a legal value
- Future work: parameter constraints
- For now: If a type changes then handle the update the same as an unexpected parameter
If a node uses parameters but does not know all parameters it can use at compile time
- Initial values needed for known parameters that don't get set by a user
- Node author needs ability to accept/reject parameters that are not known at compile time
- Example:
costmap_2d::ObstacleLayer
does not know all of the parameter names until afterobservation_sources
is set.
- Example:
Implementation considerations
Some parameters functionality will move to rcl (ros2/rcl#194). This ticket assumes the client library (rclcpp
, rclpy
, etc) will be responsible for parameter storage including default values and having knowledge of expected versus unexpected parameters.
Lifecycle considerations
If a node author wants custom logic for unexpected parameters then that logic must be set up before a parameter can be set by a run-time user. This includes defining expected parameters. Parameters cannot be set until a node is added to an executor, and that can't happen until a node is constructed. Therefore, a node author may define parameters and set up unexpected parameter handling in their constructor.
Creating a parameter
/// Create a parameter with an optional initial value
/*
* \param[in] initial_value the name and initial value of the parameter
* \raise an exception if an error occurs
*/
void
NodeParameters::create_parameter(const ParameterVariant & initial_value);
void
NodePamameters::create_parameter(const std::string & name)
{
/* TODO it does not appear possible to create a ParameterVariant with a name but no type */
}
// Convenience call
template <typename T>
void
NodePamameters::create_parameter(const std::string & name, T value)
{
ParameterVariant param(name, value);
return create_parameter(param);
}
Deleting/undeclaring a parameter
/// Undeclare parameter with a given name
/* Deleted parameters are treated as unexpected the next time a user tries to set them
* \param[in] name the name of the parameter to declare
* \raise an exception if an error occurs
*/
void
NodeParameters::delete_parameter(const std::string & name);
Registering callback for unexpected parameters.
// Set callback to be called when when an unexpected parameter is set
// This callback controls whether the parameter change is accepted or rejected
// \sa register_param_change_callback() for a callback called on all parameter changes
void
NodeParameters::register_unexpected_param_change_callback(ParametersCallbackFunction callback);
Does setting a parameter define/create/declare it?
If No:
- Pros
- Default behavior of setting an undeclared parameter is the same for both node authors and run-time users (deny set by default)
- Node author typo in parameter name raises an exception instead of silently proceeding with the wrong name
- Cons
- Forces a node author to declare parameters or change the unexpected parameter handling
if yes:
- Pros
- Opt-in to declaring parameters, otherwise current API stays the same
- Cons
- Typos by node author are harder to catch
- Default behavior of setting an unexpected parameter is different if you're a node author vs node user
- In a future with parameter constraints, what are the default constraints when setting a parameter?
Behavior:
Assuming node author does not declare parameters or change how unexpected parameters are handled
- Node author calls set_parameter() on the same name twice, but with different types
- If no:
- Both calls fail because the parameter is unexpected
- If yes:
- First
set_parameter()
call succeeds - Second
set_parameter()
call fails since first call declared a parameter with a given type
- First
- If no:
- Run-time user tries to set parameter never declared by node author
- If no or yes: Run-time parameter is rejected as an unexpected parameter
- Node author calls set_parameter(), run-time user later tries to set parameter with same type
- if no:
- Node author
set_parameter()
fails - run time set parameter fails because the parameter is undeclared
- Node author
- if yes:
- Node author's call to
set_parameter()
succeeds - run time set parameter succeeds
- Node author's call to
- if no:
- Node author calls set_parameter(), run-time user later tries to set parameter with different type
- if no:
- Node author
set_parameter()
fails - run time set parameter fails because the parameter is undeclared
- Node author
- if yes:
- Node author's call to
set_parameter()
succeeds - run time set parameter fails because it tried to change the type
- Node author's call to
- if no: