29#ifndef CONTROL_TOOLBOX__PID_HPP_
30#define CONTROL_TOOLBOX__PID_HPP_
38#include "fmt/format.h"
39#include "rclcpp/duration.hpp"
40#include "realtime_tools/realtime_thread_safe_box.hpp"
70 CONDITIONAL_INTEGRATION
75 i_max(std::numeric_limits<double>::infinity()),
76 i_min(-std::numeric_limits<double>::infinity()),
82 void set_type(
const std::string & s)
84 if (s ==
"back_calculation")
86 type = BACK_CALCULATION;
88 else if (s ==
"conditional_integration")
90 type = CONDITIONAL_INTEGRATION;
99 throw std::invalid_argument(
100 "AntiWindupStrategy: Unknown antiwindup strategy : '" + s +
101 "'. Valid strategies are: 'back_calculation', 'conditional_integration', "
106 void validate()
const
108 if (type == UNDEFINED)
110 throw std::invalid_argument(
"AntiWindupStrategy is UNDEFINED. Please set a valid type");
113 type == BACK_CALCULATION &&
116 throw std::invalid_argument(
117 "AntiWindupStrategy 'back_calculation' requires a valid positive tracking time constant "
118 "(tracking_time_constant)");
122 throw std::invalid_argument(
123 fmt::format(
"PID requires i_min to be smaller or equal to 0 (i_min: {})",
i_min));
127 throw std::invalid_argument(
128 fmt::format(
"PID requires i_max to be greater or equal to 0 (i_max: {})",
i_max));
131 type != NONE && type != UNDEFINED && type != BACK_CALCULATION &&
132 type != CONDITIONAL_INTEGRATION)
134 throw std::invalid_argument(
"AntiWindupStrategy has an invalid type");
138 void print()
const { std::cout << string() << std::endl; }
140 std::string string()
const
143 "antiwindup_strat: {}\ti_max: {}\ti_min: {}\ttracking_time_constant: {}\terror_deadband: {}",
147 operator std::string()
const {
return to_string(); }
149 constexpr bool operator==(Value other)
const {
return type == other; }
150 constexpr bool operator!=(Value other)
const {
return type != other; }
152 std::string to_string()
const
156 case BACK_CALCULATION:
157 return "back_calculation";
158 case CONDITIONAL_INTEGRATION:
159 return "conditional_integration";
168 Value type = UNDEFINED;
169 double i_max = std::numeric_limits<double>::infinity();
170 double i_min = -std::numeric_limits<double>::infinity();
177 std::numeric_limits<double>::epsilon();
181inline bool is_zero(T value, T tolerance = std::numeric_limits<T>::epsilon())
183 return std::abs(value) <= tolerance;
285 double p,
double i,
double d,
double u_max,
double u_min,
296 bool validate(std::string & error_msg)
const
300 error_msg = fmt::format(
"Gains: u_min ({}) must be less than u_max ({})",
u_min_,
u_max_);
305 error_msg =
"Gains: u_min and u_max must not be NaN";
312 catch (
const std::exception & e)
314 error_msg = e.what();
320 void print()
const { std::cout << string() << std::endl; }
322 std::string string()
const
325 "Gains(p: {}, i: {}, d: {}, u_max: {}, u_min: {}, antiwindup_strat: '{}')",
p_gain_,
332 double u_max_ = std::numeric_limits<double>::infinity();
333 double u_min_ = -std::numeric_limits<double>::infinity();
352 double p = 0.0,
double i = 0.0,
double d = 0.0,
353 double u_max = std::numeric_limits<double>::infinity(),
354 double u_min = -std::numeric_limits<double>::infinity(),
384 double p,
double i,
double d,
double u_max,
double u_min,
398 void reset(
bool save_i_term);
419 double & p,
double & i,
double & d,
double & u_max,
double & u_min,
455 double p,
double i,
double d,
double u_max,
double u_min,
478 [[nodiscard]]
double compute_command(
double error,
const double & dt_s);
490 [[nodiscard]]
double compute_command(
double error,
const rcl_duration_value_t & dt_ns);
502 [[nodiscard]]
double compute_command(
double error,
const rclcpp::Duration & dt);
514 [[nodiscard]]
double compute_command(
double error,
const std::chrono::nanoseconds & dt_ns);
527 [[nodiscard]]
double compute_command(
double error,
double error_dot,
const double & dt_s);
541 double error,
double error_dot,
const rcl_duration_value_t & dt_ns);
554 [[nodiscard]]
double compute_command(
double error,
double error_dot,
const rclcpp::Duration & dt);
568 double error,
double error_dot,
const std::chrono::nanoseconds & dt_ns);
600 gains_box_ = source.gains_box_;
614 std::numeric_limits<double>::infinity(),
615 -std::numeric_limits<double>::infinity(),
621 double p_error_last_ = 0;