Program Listing for File utils.hpp

Return to documentation for file (/tmp/ws/src/ublox/ublox_gps/include/ublox_gps/utils.hpp)

#ifndef UBLOX_GPS_UTILS_HPP
#define UBLOX_GPS_UTILS_HPP

#include <ctime>
#include <limits>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>

#include <rcl_interfaces/msg/parameter_descriptor.hpp>
#include <rclcpp/rclcpp.hpp>

#include <ublox_gps/mkgmtime.h>

namespace ublox_node {

template<typename NavPVT>
time_t toUtcSeconds(const NavPVT& msg) {
  // Create TM struct for mkgmtime
  struct tm time{};
  time.tm_year = msg.year - 1900;
  time.tm_mon = msg.month - 1;
  time.tm_mday = msg.day;
  time.tm_hour = msg.hour;
  time.tm_min = msg.min;
  time.tm_sec = msg.sec;
  // C++ STL doesn't have a mkgmtime (though other libraries do)
  // STL mktime converts date/time to seconds in local time
  // A modified version of code external library is used for mkgmtime
  return mkgmtime(&time);
}

template <typename V, typename T>
void checkMin(V val, T min, const std::string & name) {
  if (val < min) {
    std::stringstream oss;
    oss << "Invalid settings: " << name << " must be > " << min;
    throw std::runtime_error(oss.str());
  }
}

template <typename V, typename T>
void checkRange(V val, T min, T max, const std::string & name) {
  if (val < min || val > max) {
    std::stringstream oss;
    oss << "Invalid settings: " << name << " must be in range [" << min <<
        ", " << max << "].";
    throw std::runtime_error(oss.str());
  }
}

template <typename V, typename T>
void checkRange(std::vector<V> val, T min, T max, const std::string & name) {
  for (size_t i = 0; i < val.size(); i++)  {
    std::stringstream oss;
    oss << name << "[" << i << "]";
    checkRange(val[i], min, max, oss.str());
  }
}

template <typename U>
bool getRosUint(rclcpp::Node* node, const std::string& key, U &u) {
  rclcpp::Parameter parameter;
  if (!node->get_parameter(key, parameter)) {
    return false;
  }
  U param = parameter.get_value<U>();
  // Check the bounds
  U min = std::numeric_limits<U>::lowest();
  U max = std::numeric_limits<U>::max();
  checkRange(param, min, max, key);
  // set the output
  u = static_cast<U>(param);
  return true;
}

template <typename U, typename V>
void getRosUint(rclcpp::Node* node, const std::string& key, U &u, V default_val) {
  if (!getRosUint(node, key, u)) {
    u = default_val;
  }
}

template <typename U>
bool getRosUint(rclcpp::Node* node, const std::string& key, std::vector<U> &u) {
  std::vector<U> param;
  if (!node->get_parameter(key, param)) {
    return false;
  }

  // Check the bounds
  U min = std::numeric_limits<U>::lowest();
  U max = std::numeric_limits<U>::max();
  checkRange(param, min, max, key);

  // set the output
  u.insert(u.begin(), param.begin(), param.end());
  return true;
}

static inline bool getRosBoolean(rclcpp::Node* node, const std::string &name)
{
  bool ret;
  if (!node->get_parameter(name, ret)) {
    // Note that if this is used after declare_parameter, this should never happen.
    throw std::runtime_error("Required parameter '" + name + "' has not been declared");
  }

  return ret;
}

template <typename T>
T declareRosIntParameter(rclcpp::Node* node, const std::string& name, int64_t default_value)
{
  rcl_interfaces::msg::ParameterDescriptor param_desc;
  param_desc.name = name;
  param_desc.type = rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER;
  param_desc.description = name;
  rcl_interfaces::msg::IntegerRange range;
  range.from_value = std::numeric_limits<T>::lowest();
  range.to_value = std::numeric_limits<T>::max();
  param_desc.integer_range.push_back(range);
  return node->declare_parameter(name, default_value, param_desc);
}

static inline bool isRosParameterSet(rclcpp::Node* node, const std::string& name)
{
  rclcpp::Parameter param;
  node->get_parameter(name, param);
  return param.get_type() != rcl_interfaces::msg::ParameterType::PARAMETER_NOT_SET;
}

}  // namespace ublox_node

#endif  // UBLOX_GPS_UTILS_HPP