Program Listing for File imu_control_parameters.cpp

Return to documentation for file (src/imu_control_parameters.cpp)

/*******************************************************************************
 *   @file   imu_control_parameters.cpp
 *   @brief  Set ros parameter in libiio - implementation
 *   @author Vasile Holonec (Vasile.Holonec@analog.com)
*******************************************************************************/
// Copyright 2023 Analog Devices, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "adi_imu/imu_control_parameters.h"

#include <inttypes.h>

#include <map>
#include <string>
#include <thread>

namespace adi_imu
{

ImuControlParameters::ImuControlParameters(
  std::shared_ptr<rclcpp::Node> & node, std::shared_ptr<ADISRegisterMap> & device_descriptor)
{
  m_node = node;
  m_device_descriptor = device_descriptor;

  declareAdisAttributes();
  mapIIOUpdateFunctionsInt32();
  mapIIOGetFunctionsInt32();
  mapIIOUpdateFunctionsUint32();
  mapIIOGetFunctionsUint32();
  mapIIOUpdateFunctionsDouble();
  mapIIOGetFunctionsDouble();
  mapIIOCommandFunctions();
  declareParameterDescription();
  declareParameters();
}

ImuControlParameters::~ImuControlParameters() {}

void ImuControlParameters::declareAdisAttributes()
{
  m_attr_current_device.push_back("anglvel_calibbias_x");
  m_attr_current_device.push_back("anglvel_calibbias_y");
  m_attr_current_device.push_back("anglvel_calibbias_z");
  m_attr_current_device.push_back("accel_calibbias_x");
  m_attr_current_device.push_back("accel_calibbias_y");
  m_attr_current_device.push_back("accel_calibbias_z");

  if (m_device_descriptor->has(ADISRegister::HAS_CALIB_SCALE)) {
    m_attr_current_device.push_back("anglvel_calibscale_x");
    m_attr_current_device.push_back("anglvel_calibscale_y");
    m_attr_current_device.push_back("anglvel_calibscale_z");
    m_attr_current_device.push_back("accel_calibscale_x");
    m_attr_current_device.push_back("accel_calibscale_y");
    m_attr_current_device.push_back("accel_calibscale_z");
  }

  if (m_device_descriptor->has(ADISRegister::SENS_BW)) {
    m_attr_current_device.push_back("internal_sensor_bandwidth");
  }

  if (m_device_descriptor->has(ADISRegister::PT_OF_PERC_REG_ADDR)) {
    m_attr_current_device.push_back("point_of_percussion_alignment");
  }

  if (m_device_descriptor->has(ADISRegister::MSC_CTRL_ADDR)) {
    m_attr_current_device.push_back("linear_acceleration_compensation");
  }
  if (m_device_descriptor->has(ADISRegister::NULL_CNFG_ADDR)) {
    m_attr_current_device.push_back("bias_correction_time_base_control");
    m_attr_current_device.push_back("x_axis_gyroscope_bias_correction_enable");
    m_attr_current_device.push_back("y_axis_accelerometer_bias_correction_enable");
    m_attr_current_device.push_back("z_axis_accelerometer_bias_correction_enable");
    m_attr_current_device.push_back("x_axis_accelerometer_bias_correction_enable");
    m_attr_current_device.push_back("y_axis_gyroscope_bias_correction_enable");
    m_attr_current_device.push_back("z_axis_gyroscope_bias_correction_enable");
  }

  if (
    m_device_descriptor->getDeviceFamily() == "adis1654x" ||
    m_device_descriptor->getDeviceFamily() == "adis1655x") {
    m_attr_current_device.push_back("angvel_x_filter_low_pass_3db");
    m_attr_current_device.push_back("angvel_y_filter_low_pass_3db");
    m_attr_current_device.push_back("angvel_z_filter_low_pass_3db");
    m_attr_current_device.push_back("accel_x_filter_low_pass_3db");
    m_attr_current_device.push_back("accel_y_filter_low_pass_3db");
    m_attr_current_device.push_back("accel_z_filter_low_pass_3db");
  } else {
    m_attr_current_device.push_back("filter_low_pass_3db_frequency");
  }

  m_attr_current_device.push_back("sampling_frequency");
}

void ImuControlParameters::mapIIOUpdateFunctionsInt32()
{
  m_func_map_update_int32_params["accel_calibbias_x"] = &IIOWrapper::update_accel_calibbias_x;
  m_func_map_update_int32_params["accel_calibbias_y"] = &IIOWrapper::update_accel_calibbias_y;
  m_func_map_update_int32_params["accel_calibbias_z"] = &IIOWrapper::update_accel_calibbias_z;
  m_func_map_update_int32_params["anglvel_calibbias_x"] = &IIOWrapper::update_anglvel_calibbias_x;
  m_func_map_update_int32_params["anglvel_calibbias_y"] = &IIOWrapper::update_anglvel_calibbias_y;
  m_func_map_update_int32_params["anglvel_calibbias_z"] = &IIOWrapper::update_anglvel_calibbias_z;

  if (m_device_descriptor->has(ADISRegister::HAS_CALIB_SCALE)) {
    m_func_map_update_int32_params["accel_calibscale_x"] = &IIOWrapper::update_accel_calibscale_x;
    m_func_map_update_int32_params["accel_calibscale_y"] = &IIOWrapper::update_accel_calibscale_y;
    m_func_map_update_int32_params["accel_calibscale_z"] = &IIOWrapper::update_accel_calibscale_z;
    m_func_map_update_int32_params["anglvel_calibscale_x"] =
      &IIOWrapper::update_anglvel_calibscale_x;
    m_func_map_update_int32_params["anglvel_calibscale_y"] =
      &IIOWrapper::update_anglvel_calibscale_y;
    m_func_map_update_int32_params["anglvel_calibscale_z"] =
      &IIOWrapper::update_anglvel_calibscale_z;
  }

  if (
    m_device_descriptor->getDeviceFamily() == "adis1654x" ||
    m_device_descriptor->getDeviceFamily() == "adis1655x") {
    m_func_map_update_uint32_params["angvel_x_filter_low_pass_3db"] =
      &IIOWrapper::update_angvel_x_filter_low_pass_3db;
    m_func_map_update_uint32_params["angvel_y_filter_low_pass_3db"] =
      &IIOWrapper::update_angvel_y_filter_low_pass_3db;
    m_func_map_update_uint32_params["angvel_z_filter_low_pass_3db"] =
      &IIOWrapper::update_angvel_z_filter_low_pass_3db;
    m_func_map_update_uint32_params["accel_x_filter_low_pass_3db"] =
      &IIOWrapper::update_accel_x_filter_low_pass_3db;
    m_func_map_update_uint32_params["accel_y_filter_low_pass_3db"] =
      &IIOWrapper::update_accel_y_filter_low_pass_3db;
    m_func_map_update_uint32_params["accel_z_filter_low_pass_3db"] =
      &IIOWrapper::update_accel_z_filter_low_pass_3db;
  } else {
    m_func_map_update_uint32_params["filter_low_pass_3db_frequency"] =
      &IIOWrapper::update_filter_low_pass_3db_frequency;
  }
}

void ImuControlParameters::mapIIOGetFunctionsInt32()
{
  m_func_map_get_int32_params["accel_calibbias_x"] = &IIOWrapper::accel_x_calibbias;
  m_func_map_get_int32_params["accel_calibbias_y"] = &IIOWrapper::accel_y_calibbias;
  m_func_map_get_int32_params["accel_calibbias_z"] = &IIOWrapper::accel_z_calibbias;
  m_func_map_get_int32_params["anglvel_calibbias_x"] = &IIOWrapper::anglvel_x_calibbias;
  m_func_map_get_int32_params["anglvel_calibbias_y"] = &IIOWrapper::anglvel_y_calibbias;
  m_func_map_get_int32_params["anglvel_calibbias_z"] = &IIOWrapper::anglvel_z_calibbias;

  if (m_device_descriptor->has(ADISRegister::HAS_CALIB_SCALE)) {
    m_func_map_get_int32_params["accel_calibscale_x"] = &IIOWrapper::accel_x_calibscale;
    m_func_map_get_int32_params["accel_calibscale_y"] = &IIOWrapper::accel_y_calibscale;
    m_func_map_get_int32_params["accel_calibscale_z"] = &IIOWrapper::accel_z_calibscale;
    m_func_map_get_int32_params["anglvel_calibscale_x"] = &IIOWrapper::anglvel_x_calibscale;
    m_func_map_get_int32_params["anglvel_calibscale_y"] = &IIOWrapper::anglvel_y_calibscale;
    m_func_map_get_int32_params["anglvel_calibscale_z"] = &IIOWrapper::anglvel_z_calibscale;
  }

  if (
    m_device_descriptor->getDeviceFamily() == "adis1654x" ||
    m_device_descriptor->getDeviceFamily() == "adis1655x") {
    m_func_map_get_uint32_params["angvel_x_filter_low_pass_3db"] =
      &IIOWrapper::angvel_x_filter_low_pass_3db;
    m_func_map_get_uint32_params["angvel_y_filter_low_pass_3db"] =
      &IIOWrapper::angvel_y_filter_low_pass_3db;
    m_func_map_get_uint32_params["angvel_z_filter_low_pass_3db"] =
      &IIOWrapper::angvel_z_filter_low_pass_3db;
    m_func_map_get_uint32_params["accel_x_filter_low_pass_3db"] =
      &IIOWrapper::accel_x_filter_low_pass_3db;
    m_func_map_get_uint32_params["accel_y_filter_low_pass_3db"] =
      &IIOWrapper::accel_y_filter_low_pass_3db;
    m_func_map_get_uint32_params["accel_z_filter_low_pass_3db"] =
      &IIOWrapper::accel_z_filter_low_pass_3db;
  } else {
    m_func_map_get_uint32_params["filter_low_pass_3db_frequency"] =
      &IIOWrapper::filter_low_pass_3db_frequency;
  }
}

void ImuControlParameters::mapIIOUpdateFunctionsUint32()
{
  if (m_device_descriptor->has(ADISRegister::SENS_BW)) {
    m_func_map_update_uint32_params["internal_sensor_bandwidth"] =
      &IIOWrapper::update_internal_sensor_bandwidth;
  }

  if (m_device_descriptor->has(ADISRegister::PT_OF_PERC_ALGNMNT)) {
    m_func_map_update_uint32_params["point_of_percussion_alignment"] =
      &IIOWrapper::update_point_of_percussion_alignment;
  }

  if (m_device_descriptor->has(ADISRegister::MSC_CTRL_ADDR)) {
    m_func_map_update_uint32_params["linear_acceleration_compensation"] =
      &IIOWrapper::update_linear_acceleration_compensation;
  }

  if (m_device_descriptor->has(ADISRegister::NULL_CNFG_ADDR)) {
    m_func_map_update_uint32_params["bias_correction_time_base_control"] =
      &IIOWrapper::update_bias_correction_time_base_control;
    m_func_map_update_uint32_params["x_axis_gyroscope_bias_correction_enable"] =
      &IIOWrapper::update_x_axis_gyroscope_bias_correction_enable;
    m_func_map_update_uint32_params["y_axis_gyroscope_bias_correction_enable"] =
      &IIOWrapper::update_y_axis_gyroscope_bias_correction_enable;
    m_func_map_update_uint32_params["z_axis_gyroscope_bias_correction_enable"] =
      &IIOWrapper::update_z_axis_gyroscope_bias_correction_enable;
    m_func_map_update_uint32_params["x_axis_accelerometer_bias_correction_enable"] =
      &IIOWrapper::update_x_axis_accelerometer_bias_correction_enable;
    m_func_map_update_uint32_params["y_axis_accelerometer_bias_correction_enable"] =
      &IIOWrapper::update_y_axis_accelerometer_bias_correction_enable;
    m_func_map_update_uint32_params["z_axis_accelerometer_bias_correction_enable"] =
      &IIOWrapper::update_z_axis_accelerometer_bias_correction_enable;
  }
}

void ImuControlParameters::mapIIOGetFunctionsUint32()
{
  if (m_device_descriptor->has(ADISRegister::SENS_BW)) {
    m_func_map_get_uint32_params["internal_sensor_bandwidth"] =
      &IIOWrapper::internal_sensor_bandwidth;
  }

  if (m_device_descriptor->has(ADISRegister::PT_OF_PERC_REG_ADDR)) {
    m_func_map_get_uint32_params["point_of_percussion_alignment"] =
      &IIOWrapper::point_of_percussion_alignment;
  }

  if (m_device_descriptor->has(ADISRegister::MSC_CTRL_ADDR)) {
    m_func_map_get_uint32_params["linear_acceleration_compensation"] =
      &IIOWrapper::linear_acceleration_compensation;
  }

  if (m_device_descriptor->has(ADISRegister::NULL_CNFG_ADDR)) {
    m_func_map_get_uint32_params["bias_correction_time_base_control"] =
      &IIOWrapper::bias_correction_time_base_control;
    m_func_map_get_uint32_params["x_axis_gyroscope_bias_correction_enable"] =
      &IIOWrapper::x_axis_gyroscope_bias_correction_enable;
    m_func_map_get_uint32_params["y_axis_gyroscope_bias_correction_enable"] =
      &IIOWrapper::y_axis_gyroscope_bias_correction_enable;
    m_func_map_get_uint32_params["z_axis_gyroscope_bias_correction_enable"] =
      &IIOWrapper::z_axis_gyroscope_bias_correction_enable;
    m_func_map_get_uint32_params["x_axis_accelerometer_bias_correction_enable"] =
      &IIOWrapper::x_axis_accelerometer_bias_correction_enable;
    m_func_map_get_uint32_params["y_axis_accelerometer_bias_correction_enable"] =
      &IIOWrapper::y_axis_accelerometer_bias_correction_enable;
    m_func_map_get_uint32_params["z_axis_accelerometer_bias_correction_enable"] =
      &IIOWrapper::z_axis_accelerometer_bias_correction_enable;
  }
}

void ImuControlParameters::mapIIOUpdateFunctionsDouble()
{
  m_func_map_update_double_params["sampling_frequency"] = &IIOWrapper::update_sampling_frequency;
}

void ImuControlParameters::mapIIOGetFunctionsDouble()
{
  m_func_map_get_double_params["sampling_frequency"] = &IIOWrapper::sampling_frequency;
}

void ImuControlParameters::mapIIOCommandFunctions()
{
  m_func_map_execute_commands["software_reset"] = &IIOWrapper::software_reset;

  if (m_device_descriptor->has(ADISRegister::FLASH_MEMORY_TEST)) {
    m_func_map_execute_commands["flash_memory_test"] = &IIOWrapper::flash_memory_test;
  }
  m_func_map_execute_commands["flash_memory_update"] = &IIOWrapper::flash_memory_update;
  m_func_map_execute_commands["sensor_self_test"] = &IIOWrapper::sensor_self_test;
  m_func_map_execute_commands["factory_calibration_restore"] =
    &IIOWrapper::factory_calibration_restore;

  if (m_device_descriptor->has(ADISRegister::BIAS_CORRECTION_UPDATE)) {
    m_func_map_execute_commands["bias_correction_update"] = &IIOWrapper::bias_correction_update;
  }
}

void ImuControlParameters::declareParameterDescription()
{
  auto param_range_calibbias = rcl_interfaces::msg::IntegerRange{};
  param_range_calibbias.from_value = -2147483648;
  param_range_calibbias.to_value = 2147483647;
  param_range_calibbias.step = 1;

  auto param_range_0_720 = rcl_interfaces::msg::IntegerRange{};
  auto param_range_100_300 = rcl_interfaces::msg::IntegerRange{};
  if (m_device_descriptor->getDeviceFamily() != "adis1654x") {
    param_range_0_720.from_value = 0;
    param_range_0_720.to_value = 720;
  } else {
    param_range_100_300.from_value = 0;
    param_range_100_300.to_value = 300;
  }

  auto param_range_01 = rcl_interfaces::msg::IntegerRange{};
  param_range_01.from_value = 0;
  param_range_01.to_value = 1;
  param_range_01.step = 1;

  auto param_range_03 = rcl_interfaces::msg::IntegerRange{};
  if (m_device_descriptor->has(ADISRegister::HAS_DELTA_BURST)) {
    param_range_03.from_value = 0;
  } else {
    param_range_03.from_value = 1;
  }

  param_range_03.to_value = 3;
  param_range_03.step = 1;

  m_param_description["anglvel_calibbias_x"] = "x-axis angular velocity offset correction";
  m_param_constraints_integer["anglvel_calibbias_x"] = param_range_calibbias;

  m_param_description["anglvel_calibbias_y"] = "y-axis angular velocity offset correction";
  m_param_constraints_integer["anglvel_calibbias_y"] = param_range_calibbias;

  m_param_description["anglvel_calibbias_z"] = "z-axis angular velocity offset correction";
  m_param_constraints_integer["anglvel_calibbias_z"] = param_range_calibbias;

  m_param_description["accel_calibbias_x"] = "x-axis acceleration offset correction";
  m_param_constraints_integer["accel_calibbias_x"] = param_range_calibbias;

  m_param_description["accel_calibbias_y"] = "y-axis acceleration offset correction";
  m_param_constraints_integer["accel_calibbias_y"] = param_range_calibbias;

  m_param_description["accel_calibbias_z"] = "z-axis acceleration offset correction";
  m_param_constraints_integer["accel_calibbias_z"] = param_range_calibbias;

  if (m_device_descriptor->getDeviceFamily() == "adis1654x") {
    m_param_description["angvel_x_filter_low_pass_3db"] =
      "X angular velocity low pass 3db frequency";
    m_param_constraints_integer["angvel_x_filter_low_pass_3db"] = param_range_100_300;

    m_param_description["angvel_y_filter_low_pass_3db"] =
      "Y angular velocity low pass 3db frequency";
    m_param_constraints_integer["angvel_y_filter_low_pass_3db"] = param_range_100_300;

    m_param_description["angvel_z_filter_low_pass_3db"] =
      "Z angular velocity low pass 3db frequency";
    m_param_constraints_integer["angvel_z_filter_low_pass_3db"] = param_range_100_300;

    m_param_description["accel_x_filter_low_pass_3db"] = "X acceleration low pass 3db frequency";
    m_param_constraints_integer["accel_x_filter_low_pass_3db"] = param_range_100_300;

    m_param_description["accel_y_filter_low_pass_3db"] = "Y acceleration low pass 3db frequency";
    m_param_constraints_integer["accel_y_filter_low_pass_3db"] = param_range_100_300;

    m_param_description["accel_z_filter_low_pass_3db"] = "Z acceleration low pass 3db frequency";
    m_param_constraints_integer["accel_z_filter_low_pass_3db"] = param_range_100_300;
  } else {
    m_param_description["filter_low_pass_3db_frequency"] = "Low pass 3db frequency";
    m_param_constraints_integer["filter_low_pass_3db_frequency"] = param_range_0_720;
  }

  if (m_device_descriptor->has(ADISRegister::HAS_CALIB_SCALE)) {
    m_param_description["anglvel_calibscale_x"] = "x-axis angular velocity scale correction";
    m_param_constraints_integer["anglvel_calibscale_x"] = param_range_calibbias;

    m_param_description["anglvel_calibscale_y"] = "y-axis angular velocity scale correction";
    m_param_constraints_integer["anglvel_calibscale_y"] = param_range_calibbias;

    m_param_description["anglvel_calibscale_z"] = "z-axis angular velocity scale correction";
    m_param_constraints_integer["anglvel_calibscale_z"] = param_range_calibbias;

    m_param_description["accel_calibscale_x"] = "x-axis acceleration scale correction";
    m_param_constraints_integer["accel_calibscale_x"] = param_range_calibbias;

    m_param_description["accel_calibscale_y"] = "y-axis acceleration scale correction";
    m_param_constraints_integer["accel_calibscale_y"] = param_range_calibbias;

    m_param_description["accel_calibscale_z"] = "z-axis acceleration scale correction";
    m_param_constraints_integer["accel_calibscale_z"] = param_range_calibbias;
  }

  if (m_device_descriptor->has(ADISRegister::SENS_BW)) {
    m_param_description["internal_sensor_bandwidth"] =
      "\n0: wide bandwidth"
      "\n1: 370 Hz";
    m_param_constraints_integer["internal_sensor_bandwidth"] = param_range_01;
  }
  if (m_device_descriptor->has(ADISRegister::PT_OF_PERC_REG_ADDR)) {
    m_param_description["point_of_percussion_alignment"] =
      "\n0: point of percussion alignment disable"
      "\n1: point of percussion alignment enable";
    m_param_constraints_integer["point_of_percussion_alignment"] = param_range_01;
  }
  if (m_device_descriptor->has(ADISRegister::MSC_CTRL_ADDR)) {
    m_param_description["linear_acceleration_compensation"] =
      "\n0: linear acceleration compensation disable"
      "\n1: linear acceleration compensation enable";
    m_param_constraints_integer["linear_acceleration_compensation"] = param_range_01;
  }
  if (m_device_descriptor->has(ADISRegister::NULL_CNFG_ADDR)) {
    auto param_range_0_12 = rcl_interfaces::msg::IntegerRange{};
    param_range_0_12.from_value = 0;
    param_range_0_12.to_value = 12;
    param_range_0_12.step = 1;

    m_param_description["bias_correction_time_base_control"] = "Time base control";
    m_param_constraints_integer["bias_correction_time_base_control"] = param_range_0_12;

    m_param_description["x_axis_gyroscope_bias_correction_enable"] =
      "\n0: x-axis gyroscope bias correction disabled"
      "\n1: x-axis gyroscope bias correction enabled";
    m_param_constraints_integer["x_axis_gyroscope_bias_correction_enable"] = param_range_01;

    m_param_description["y_axis_gyroscope_bias_correction_enable"] =
      "\n0: y-axis gyroscope bias correction disabled"
      "\n1: y-axis gyroscope bias correction enabled";
    m_param_constraints_integer["y_axis_gyroscope_bias_correction_enable"] = param_range_01;

    m_param_description["z_axis_gyroscope_bias_correction_enable"] =
      "\n0: z-axis gyroscope bias correction disabled"
      "\n1: z-axis gyroscope bias correction enabled";
    m_param_constraints_integer["z_axis_gyroscope_bias_correction_enable"] = param_range_01;

    m_param_description["x_axis_accelerometer_bias_correction_enable"] =
      "\n0: x-axis accelerometer bias correction disabled"
      "\n1: x-axis accelerometer bias correction enabled";
    m_param_constraints_integer["x_axis_accelerometer_bias_correction_enable"] = param_range_01;

    m_param_description["y_axis_accelerometer_bias_correction_enable"] =
      "\n0: y-axis accelerometer bias correction disabled"
      "\n1: z-axis accelerometer bias correction enabled";
    m_param_constraints_integer["y_axis_accelerometer_bias_correction_enable"] = param_range_01;

    m_param_description["z_axis_accelerometer_bias_correction_enable"] =
      "\n0: z-axis accelerometer bias correction disabled"
      "\n1: z-axis accelerometer bias correction enabled";
    m_param_constraints_integer["z_axis_accelerometer_bias_correction_enable"] = param_range_01;
  }

  m_param_description["measured_data_topic_selection"] = "\nmeasured_data_topic_selection values:";

  if (m_device_descriptor->has(ADISRegister::HAS_DELTA_BURST)) {
    m_param_description["measured_data_topic_selection"].append(
      "\n0: measured data is published on /velangtempdata topic");
  }

  m_param_description["measured_data_topic_selection"].append(
    "\n1: measured data is published on /accelgyrotempdata topic");

  m_param_description["measured_data_topic_selection"].append(
    "\n2: measured data is published on /imu topic"
    "\n3: measured data is published on /imufullmeasureddata topic "
    "(default)");

  m_param_constraints_integer["measured_data_topic_selection"] = param_range_03;

  auto param_range_float = rcl_interfaces::msg::FloatingPointRange{};
  param_range_float.from_value = 1.0;
  param_range_float.to_value =
    static_cast<double>(m_device_descriptor->get(ADISRegister::MAX_SAMP_FREQ));
  m_param_description["sampling_frequency"] = "Device sampling frequency";
  m_param_constraints_floating["sampling_frequency"] = param_range_float;
}

void ImuControlParameters::declareParameters()
{
  uint32_t u32Param = 0;
  int64_t i64Param = 0;
  int32_t i32Param = 0;
  double dParam = 0;

  for (const std::string & key : m_attr_current_device) {
    if (m_func_map_get_int32_params.find(key) != m_func_map_get_int32_params.end()) {
      (m_iio_wrapper.*(m_func_map_get_int32_params[key]))(i32Param);

      auto param_desc = rcl_interfaces::msg::ParameterDescriptor{};
      param_desc.description = m_param_description[key];
      param_desc.integer_range.push_back(m_param_constraints_integer[key]);

      m_node->declare_parameter(key, i32Param, param_desc);
      m_int32_current_params[key] = i32Param;
    } else if (m_func_map_get_uint32_params.find(key) != m_func_map_get_uint32_params.end()) {
      (m_iio_wrapper.*(m_func_map_get_uint32_params[key]))(u32Param);
      i64Param = u32Param;

      auto param_desc = rcl_interfaces::msg::ParameterDescriptor{};
      param_desc.description = m_param_description[key];
      param_desc.integer_range.push_back(m_param_constraints_integer[key]);

      m_node->declare_parameter(key, i64Param, param_desc);
      m_uint32_current_params[key] = i64Param;
    } else if (m_func_map_get_double_params.find(key) != m_func_map_get_double_params.end()) {
      (m_iio_wrapper.*(m_func_map_get_double_params[key]))(&dParam);

      auto param_desc = rcl_interfaces::msg::ParameterDescriptor{};
      param_desc.description = m_param_description[key];
      param_desc.floating_point_range.push_back(m_param_constraints_floating[key]);

      m_node->declare_parameter(key, dParam, param_desc);
      m_double_current_params[key] = dParam;
    } else {
      // do nothing
    }
  }

  auto param_desc_topic = rcl_interfaces::msg::ParameterDescriptor{};
  param_desc_topic.description = m_param_description["measured_data_topic_selection"];
  param_desc_topic.integer_range.push_back(
    m_param_constraints_integer["measured_data_topic_selection"]);
  m_node->declare_parameter("measured_data_topic_selection", FULL_MEASURED_DATA, param_desc_topic);

  auto param_desc = rcl_interfaces::msg::ParameterDescriptor{};
  param_desc.description =
    "\ncommand_to_execute values:"
    "\nsoftware_reset: performs a software reset on the device";
  if (m_device_descriptor->has(ADISRegister::FLASH_MEMORY_TEST)) {
    param_desc.description.append(
      "\nflash_memory_test: performs a flash memory test on the device");
  }
  param_desc.description.append(
    "\nflash_memory_update: performs a flash memory update on the device"
    "\nsensor_self_test: performs a sensor self test on the device"
    "\nfactory_calibration_restore: performs a factory calibration "
    "restore on the device");
  if (m_device_descriptor->has(ADISRegister::BIAS_CORRECTION_UPDATE)) {
    param_desc.description.append(
      "\nbias_correction_update: triggers a bias correction, using the bias "
      "correction factors");
  }
  m_node->declare_parameter("command_to_execute", "no_command", param_desc);
}

void ImuControlParameters::updateParamsFromHardware()
{
  double doubleDriverParam = 0;
  double doubleCurrentParam = 0;
  int32_t int32DriverParam = 0;
  int32_t int32CurrentParam = 0;

  uint32_t u32DriverParam = 0;
  int64_t int64DriverParam = 0;
  int64_t int64CurrentParam = 0;

  for (const std::string & key : m_attr_current_device) {
    const char * ckey = key.c_str();
    if (m_func_map_get_double_params.find(key) != m_func_map_get_double_params.end()) {
      (m_iio_wrapper.*(m_func_map_get_double_params[key]))(&doubleDriverParam);
      doubleCurrentParam = m_node->get_parameter(key).get_parameter_value().get<double>();
      if (doubleDriverParam != doubleCurrentParam) {
        m_node->set_parameter(rclcpp::Parameter(ckey, doubleDriverParam));
        RCLCPP_INFO(
          rclcpp::get_logger("rclcpp_imucontrolparameter"), "ros parameter new values %s: %f", ckey,
          doubleDriverParam);
      }
    } else if (m_func_map_get_int32_params.find(key) != m_func_map_get_int32_params.end()) {
      (m_iio_wrapper.*(m_func_map_get_int32_params[key]))(int32DriverParam);
      int32CurrentParam = m_node->get_parameter(key).get_parameter_value().get<int32_t>();
      if (int32DriverParam != int32CurrentParam) {
        m_node->set_parameter(rclcpp::Parameter(ckey, int32DriverParam));
        RCLCPP_INFO(
          rclcpp::get_logger("rclcpp_imucontrolparameter"), "ros parameter new values %s: %d", ckey,
          int32DriverParam);
      }
    } else if (m_func_map_get_uint32_params.find(key) != m_func_map_get_uint32_params.end()) {
      (m_iio_wrapper.*(m_func_map_get_uint32_params[key]))(u32DriverParam);
      int64CurrentParam = m_node->get_parameter(key).get_parameter_value().get<int64_t>();
      if (u32DriverParam != (uint32_t)int64CurrentParam) {
        int64DriverParam = u32DriverParam;
        m_node->set_parameter(rclcpp::Parameter(ckey, int64DriverParam));
        RCLCPP_INFO(
          rclcpp::get_logger("rclcpp_imucontrolparameter"), "ros parameter new values %s: %d", ckey,
          u32DriverParam);
      }
    } else {
      // do nothing
    }
  }
}

void ImuControlParameters::handleDoubleParamChange()
{
  double requestedValue = 0;
  double dDriverParam = 0;

  for (const std::string & key : m_attr_current_device) {
    if (m_func_map_get_double_params.find(key) != m_func_map_get_double_params.end()) {
      requestedValue = m_node->get_parameter(key).get_parameter_value().get<double>();

      if (requestedValue != m_double_current_params[key]) {
        // update value in hardware
        const char * ckey = key.c_str();
        if (!(m_iio_wrapper.*(m_func_map_update_double_params[key]))(requestedValue)) {
          RCLCPP_INFO(
            rclcpp::get_logger("rclcpp_imucontrolparameter"),
            "error on set parameter %s with %f value; current value "
            "remained %f",
            ckey, requestedValue, m_double_current_params[key]);
        } else {
          // readback value from hardware
          if (!(m_iio_wrapper.*(m_func_map_get_double_params[key]))(&dDriverParam)) {
            RCLCPP_INFO(
              rclcpp::get_logger("rclcpp_imucontrolparameter"),
              "error on read-back parameter %s, cannot validate if the parameter has been set \
              successfully, please retry",
              ckey);
          } else {
            if (dDriverParam != requestedValue) {
              RCLCPP_INFO(
                rclcpp::get_logger("rclcpp_imucontrolparameter"),
                "Trying to set parameter %s: old value = %f "
                "requested value = %f. "
                "Requested value could not be set in hardware, "
                "instead the following value was set: %f",
                ckey, m_double_current_params[key], requestedValue, dDriverParam);
              m_node->set_parameter(rclcpp::Parameter(ckey, dDriverParam));
            } else {
              RCLCPP_INFO(
                rclcpp::get_logger("rclcpp_imucontrolparameter"),
                "successfully set parameter %s: old "
                "value = %f new value = %f",
                ckey, m_double_current_params[key], requestedValue);
            }
            m_double_current_params[key] = dDriverParam;
          }
        }
      }
    }
  }
}

void ImuControlParameters::handleInt32ParamChange()
{
  int32_t requestedValue = 0;
  int32_t i32DriverParam = 0;

  for (const std::string & key : m_attr_current_device) {
    if (m_func_map_get_int32_params.find(key) != m_func_map_get_int32_params.end()) {
      requestedValue = m_node->get_parameter(key).get_parameter_value().get<int32_t>();

      if (requestedValue != m_int32_current_params[key]) {
        // update value in hardware
        const char * ckey = key.c_str();
        if (!(m_iio_wrapper.*(m_func_map_update_int32_params[key]))(requestedValue)) {
          RCLCPP_INFO(
            rclcpp::get_logger("rclcpp_imucontrolparameter"),
            "error on set parameter %s with %d value; current value "
            "remained %d",
            ckey, requestedValue, m_int32_current_params[key]);
        } else {
          // readback value from hardware
          if (!(m_iio_wrapper.*(m_func_map_get_int32_params[key]))(i32DriverParam)) {
            RCLCPP_INFO(
              rclcpp::get_logger("rclcpp_imucontrolparameter"),
              "error on read-back parameter %s, cannot validate if the parameter has been set \
              successfully, please retry",
              ckey);
          } else {
            if (i32DriverParam != requestedValue) {
              RCLCPP_INFO(
                rclcpp::get_logger("rclcpp_imucontrolparameter"),
                "Trying to set parameter %s: old value = %d "
                "requested value = %d. "
                "Requested value could not be set in hardware, "
                "instead the following value was set: %d",
                ckey, m_int32_current_params[key], requestedValue, i32DriverParam);
              m_node->set_parameter(rclcpp::Parameter(ckey, i32DriverParam));
            } else {
              RCLCPP_INFO(
                rclcpp::get_logger("rclcpp_imucontrolparameter"),
                "successfully set parameter %s: old "
                "value = %d new value = %d",
                ckey, m_int32_current_params[key], requestedValue);
            }
            m_int32_current_params[key] = i32DriverParam;
          }
        }
      }
    }
  }
}

void ImuControlParameters::handleUint32ParamChange()
{
  int64_t requestedValue = 0;
  int64_t i64DriverParam = 0;
  uint32_t u32DriverParam = 0;

  for (const std::string & key : m_attr_current_device) {
    if (m_func_map_get_uint32_params.find(key) != m_func_map_get_uint32_params.end()) {
      requestedValue = m_node->get_parameter(key).get_parameter_value().get<int64_t>();

      if (requestedValue != m_uint32_current_params[key]) {
        // update value in hardware
        const char * ckey = key.c_str();
        if (!(m_iio_wrapper.*(m_func_map_update_uint32_params[key]))(requestedValue)) {
          RCLCPP_INFO(
            rclcpp::get_logger("rclcpp_imucontrolparameter"),
            "error on set parameter %s with %" PRId64 " value; current value remained %" PRId64,
            ckey, requestedValue, m_uint32_current_params[key]);
        } else {
          // readback value from hardware
          if (!(m_iio_wrapper.*(m_func_map_get_uint32_params[key]))(u32DriverParam)) {
            RCLCPP_INFO(
              rclcpp::get_logger("rclcpp_imucontrolparameter"),
              "error on read-back parameter %s, cannot validate if the parameter has been set \
              successfully, please retry",
              ckey);
          } else {
            i64DriverParam = u32DriverParam;
            if (i64DriverParam != requestedValue) {
              RCLCPP_INFO(
                rclcpp::get_logger("rclcpp_imucontrolparameter"),
                "Trying to set parameter %s: old value = "
                "%" PRId64 " requested value = %" PRId64
                ". "
                "Requested value could not be set in hardware, "
                "instead the following value was set: %" PRId64,
                ckey, m_uint32_current_params[key], requestedValue, i64DriverParam);
              m_node->set_parameter(rclcpp::Parameter(ckey, i64DriverParam));
            } else {
              RCLCPP_INFO(
                rclcpp::get_logger("rclcpp_imucontrolparameter"),
                "successfully set parameter %s: old "
                "value = %" PRId64 " new value = %" PRId64,
                ckey, m_uint32_current_params[key], requestedValue);
            }
            m_uint32_current_params[key] = i64DriverParam;
          }
        }
      }
    }
  }
}

void ImuControlParameters::handleCommands()
{
  std::string requestedCommand =
    m_node->get_parameter("command_to_execute").get_parameter_value().get<std::string>();

  if (m_func_map_execute_commands.find(requestedCommand) != m_func_map_execute_commands.end()) {
    m_iio_wrapper.stopBufferAcquisition();
    if (!(m_iio_wrapper.*(m_func_map_execute_commands[requestedCommand]))()) {
      RCLCPP_INFO(
        rclcpp::get_logger("rclcpp_imucontrolparameter"), "error on executing command %s",
        requestedCommand.c_str());
    } else {
      RCLCPP_INFO(
        rclcpp::get_logger("rclcpp_imucontrolparameter"), "executed command %s",
        requestedCommand.c_str());
      // update the rest of parameters based on new changes in hardware
      updateParamsFromHardware();
      m_node->set_parameter(rclcpp::Parameter("command_to_execute", "no_command"));
    }
  } else if (requestedCommand != "no_command") {
    RCLCPP_INFO(
      rclcpp::get_logger("rclcpp_imucontrolparameter"), "could not find command %s",
      requestedCommand.c_str());
    m_node->set_parameter(rclcpp::Parameter("command_to_execute", "no_command"));
  }
}

void ImuControlParameters::handleControlParams()
{
  handleCommands();
  handleInt32ParamChange();
  handleUint32ParamChange();
  handleDoubleParamChange();
}

}  // namespace adi_imu