Program Listing for File param_handler.h
↰ Return to documentation for file (include/hatchbed_common/param_handler.h)
#pragma once
#include <mutex>
#include <string>
#include <unordered_map>
#include <hatchbed_common/parameter.h>
#include <rclcpp/rclcpp.hpp>
#include <rcutils/logging.h>
namespace hatchbed_common {
class ParamHandler {
public:
ParamHandler(rclcpp::Node::SharedPtr node) :
node_(node),
namespace_(node_->get_fully_qualified_name()),
verbose_param_(false)
{
params_callback_handle_ = node_->add_on_set_parameters_callback(
std::bind(&ParamHandler::parametersCallback, this, std::placeholders::_1));
};
~ParamHandler() = default;
void register_verbose_logging_param() {
if (verbose_param_) {
return;
}
verbose_param_ = true;
// determine the default verbose setting based on the current log level
auto log_level = rcutils_logging_get_logger_level(node_->get_logger().get_name());
bool is_verbose = log_level == RCUTILS_LOG_SEVERITY_DEBUG;
if (is_verbose) {
non_verbose_level_ = log_level;
}
param("verbose", is_verbose, "Enable debug logging").callback([this](const bool& value) {
RCLCPP_INFO_STREAM(node_->get_logger(), "setting verbose logging: " << (value ? "true" : "false"));
if (value) {
auto ret = rcutils_logging_set_logger_level(node_->get_logger().get_name(), RCUTILS_LOG_SEVERITY_DEBUG);
if (ret != RCUTILS_RET_OK) {
RCLCPP_WARN_STREAM(node_->get_logger(), "Failed to set log level to debug");
}
}
else {
auto ret = rcutils_logging_set_logger_level(node_->get_logger().get_name(), non_verbose_level_);
if (ret != RCUTILS_RET_OK) {
RCLCPP_WARN_STREAM(node_->get_logger(), "Failed to set log level");
}
}
}).declare();
}
BoolParameter& param(const std::string& name, bool default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
bool_params_[name] = BoolParameter(nullptr, namespace_, name, default_val, description, node_);
return bool_params_[name];
}
BoolParameter& param(bool* param, const std::string& name, bool default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
bool_params_[name] = BoolParameter(param, namespace_, name, default_val, description, node_);
return bool_params_[name];
}
BoolArrayParameter& param(const std::string& name, const std::vector<bool>& default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
bool_array_params_[name] = BoolArrayParameter(nullptr, namespace_, name, default_val, description, node_);
return bool_array_params_[name];
}
BoolArrayParameter& param(std::vector<bool>* param, const std::string& name, const std::vector<bool>& default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
bool_array_params_[name] = BoolArrayParameter(param, namespace_, name, default_val, description, node_);
return bool_array_params_[name];
}
SystemIntParameter& param(const std::string& name, int default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
system_int_params_[name] = SystemIntParameter(nullptr, namespace_, name, default_val, description, node_);
return system_int_params_[name];
}
SystemIntParameter& param(int* param, const std::string& name, int default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
system_int_params_[name] = SystemIntParameter(param, namespace_, name, default_val, description, node_);
return system_int_params_[name];
}
IntParameter& param(const std::string& name, int64_t default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
int_params_[name] = IntParameter(nullptr, namespace_, name, default_val, description, node_);
return int_params_[name];
}
IntParameter& param(int64_t* param, const std::string& name, int64_t default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
int_params_[name] = IntParameter(param, namespace_, name, default_val, description, node_);
return int_params_[name];
}
IntArrayParameter& param(const std::string& name, const std::vector<int64_t>& default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
int_array_params_[name] = IntArrayParameter(nullptr, namespace_, name, default_val, description, node_);
return int_array_params_[name];
}
IntArrayParameter& param(std::vector<int64_t>* param, const std::string& name, const std::vector<int64_t>& default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
int_array_params_[name] = IntArrayParameter(param, namespace_, name, default_val, description, node_);
return int_array_params_[name];
}
DoubleParameter& param(const std::string& name, double default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
double_params_[name] = DoubleParameter(nullptr, namespace_, name, default_val, description, node_);
return double_params_[name];
}
DoubleParameter& param(double* param, const std::string& name, double default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
double_params_[name] = DoubleParameter(param, namespace_, name, default_val, description, node_);
return double_params_[name];
}
DoubleArrayParameter& param(const std::string& name, const std::vector<double>& default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
double_array_params_[name] = DoubleArrayParameter(nullptr, namespace_, name, default_val, description, node_);
return double_array_params_[name];
}
DoubleArrayParameter& param(std::vector<double>* param, const std::string& name, const std::vector<double>& default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
double_array_params_[name] = DoubleArrayParameter(param, namespace_, name, default_val, description, node_);
return double_array_params_[name];
}
StringParameter& param(const std::string& name, const std::string& default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
string_params_[name] = StringParameter(nullptr, namespace_, name, default_val, description, node_);
return string_params_[name];
}
StringParameter& param(std::string* param, const std::string& name, const std::string& default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
string_params_[name] = StringParameter(param, namespace_, name, default_val, description, node_);
return string_params_[name];
}
StringArrayParameter& param(const std::string& name, const std::vector<std::string>& default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
string_array_params_[name] = StringArrayParameter(nullptr, namespace_, name, default_val, description, node_);
return string_array_params_[name];
}
StringArrayParameter& param(std::vector<std::string>* param, const std::string& name, const std::vector<std::string>& default_val, const std::string& description) {
std::scoped_lock lock(mutex_);
string_array_params_[name] = StringArrayParameter(param, namespace_, name, default_val, description, node_);
return string_array_params_[name];
}
void setCallback(std::function<void()> callback) {
user_callback_ = callback;
}
private:
rclcpp::Node::SharedPtr node_;
std::string namespace_;
bool verbose_param_;
int non_verbose_level_ = RCUTILS_LOG_SEVERITY_INFO;
rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr params_callback_handle_;
std::function<void()> user_callback_;
std::mutex mutex_;
std::unordered_map<std::string, BoolParameter> bool_params_;
std::unordered_map<std::string, BoolArrayParameter> bool_array_params_;
std::unordered_map<std::string, DoubleParameter> double_params_;
std::unordered_map<std::string, DoubleArrayParameter> double_array_params_;
std::unordered_map<std::string, SystemIntParameter> system_int_params_;
std::unordered_map<std::string, IntParameter> int_params_;
std::unordered_map<std::string, IntArrayParameter> int_array_params_;
std::unordered_map<std::string, StringParameter> string_params_;
std::unordered_map<std::string, StringArrayParameter> string_array_params_;
rcl_interfaces::msg::SetParametersResult parametersCallback(const std::vector<rclcpp::Parameter> ¶meters) {
rcl_interfaces::msg::SetParametersResult result;
// default to successful
// otherwise parameters that weren't created using this handler will print a warning
// any parameter created using this handler will be checked
result.successful = true;
result.reason = "success";
for (const auto ¶m: parameters) {
if (param.get_type() == rclcpp::ParameterType::PARAMETER_BOOL) {
auto bool_param = bool_params_.find(param.get_name());
if (bool_param != bool_params_.end()) {
if (!bool_param->second.update(param.as_bool(), true)) {
result.successful = false;
result.reason = "Failed to update parameter: " + bool_param->first;
}
}
}
else if (param.get_type() == rclcpp::ParameterType::PARAMETER_BOOL_ARRAY) {
auto bool_array_param = bool_array_params_.find(param.get_name());
if (bool_array_param != bool_array_params_.end()) {
if (!bool_array_param->second.update(param.as_bool_array(), true)) {
result.successful = false;
result.reason = "Failed to update parameter: " + bool_array_param->first;
}
}
}
else if (param.get_type() == rclcpp::ParameterType::PARAMETER_DOUBLE) {
auto double_param = double_params_.find(param.get_name());
if (double_param != double_params_.end()) {
if (!double_param->second.update(param.as_double(), true)) {
result.successful = false;
result.reason = "Failed to update parameter: " + double_param->first;
}
}
}
else if (param.get_type() == rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY) {
auto double_array_param = double_array_params_.find(param.get_name());
if (double_array_param != double_array_params_.end()) {
if (!double_array_param->second.update(param.as_double_array(), true)) {
result.successful = false;
result.reason = "Failed to update parameter: " + double_array_param->first;
}
}
}
else if (param.get_type() == rclcpp::ParameterType::PARAMETER_INTEGER) {
auto int_param = int_params_.find(param.get_name());
if (int_param != int_params_.end()) {
if (!int_param->second.update(param.as_int(), true)) {
result.successful = false;
result.reason = "Failed to update parameter: " + int_param->first;
}
} else {
// the parameter is not registered as int64_t, so we need to check if it's registered as system int
auto int_system_param = system_int_params_.find(param.get_name());
if (int_system_param != system_int_params_.end()) {
if (param.as_int() >= std::numeric_limits<int>::min() && param.as_int() <= std::numeric_limits<int>::max()) {
if (!int_system_param->second.update(static_cast<int>(param.as_int()), true)) {
result.successful = false;
result.reason = "Failed to update parameter: " + int_system_param->first;
}
} else {
// unsafe to cast to int
result.successful = false;
result.reason = "Failed to update parameter: " + int_system_param->first + " (value too large to cast from 'int64_t' to 'int')";
}
}
}
}
else if (param.get_type() == rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY) {
auto int_array_param = int_array_params_.find(param.get_name());
if (int_array_param != int_array_params_.end()) {
if (!int_array_param->second.update(param.as_integer_array(), true)) {
result.successful = false;
result.reason = "Failed to update parameter: " + int_array_param->first;
}
}
}
else if (param.get_type() == rclcpp::ParameterType::PARAMETER_STRING) {
auto string_param = string_params_.find(param.get_name());
if (string_param != string_params_.end()) {
if (!string_param->second.update(param.as_string(), true)) {
result.successful = false;
result.reason = "Failed to update parameter: " + string_param->first;
}
}
}
else if (param.get_type() == rclcpp::ParameterType::PARAMETER_STRING_ARRAY) {
auto string_array_param = string_array_params_.find(param.get_name());
if (string_array_param != string_array_params_.end()) {
if (!string_array_param->second.update(param.as_string_array(), true)) {
result.successful = false;
result.reason = "Failed to update parameter: " + string_array_param->first;
}
}
}
}
if (user_callback_) {
user_callback_();
}
if (!result.successful) {
RCLCPP_WARN_STREAM(node_->get_logger(), result.reason);
}
return result;
}
};
} // hatchbed_common