33#ifndef CONTROL_TOOLBOX__PID_HPP_
34#define CONTROL_TOOLBOX__PID_HPP_
42#include "fmt/format.h"
43#include "rclcpp/duration.hpp"
44#include "realtime_tools/realtime_thread_safe_box.hpp"
74 CONDITIONAL_INTEGRATION
79 i_max(std::numeric_limits<double>::infinity()),
80 i_min(-std::numeric_limits<double>::infinity()),
86 void set_type(
const std::string &
s)
88 if (
s ==
"back_calculation")
90 type = BACK_CALCULATION;
92 else if (
s ==
"conditional_integration")
94 type = CONDITIONAL_INTEGRATION;
103 throw std::invalid_argument(
104 "AntiWindupStrategy: Unknown antiwindup strategy : '" +
s +
105 "'. Valid strategies are: 'back_calculation', 'conditional_integration', "
110 void validate()
const
112 if (type == UNDEFINED)
114 throw std::invalid_argument(
"AntiWindupStrategy is UNDEFINED. Please set a valid type");
117 type == BACK_CALCULATION &&
120 throw std::invalid_argument(
121 "AntiWindupStrategy 'back_calculation' requires a valid positive tracking time constant "
122 "(tracking_time_constant)");
126 throw std::invalid_argument(
128 "PID requires i_min < i_max if limits are finite (i_min: {}, i_max: {})",
i_min,
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 operator std::string()
const {
return to_string(); }
140 constexpr bool operator==(Value
other)
const {
return type ==
other; }
141 constexpr bool operator!=(Value
other)
const {
return type !=
other; }
143 std::string to_string()
const
147 case BACK_CALCULATION:
148 return "back_calculation";
149 case CONDITIONAL_INTEGRATION:
150 return "conditional_integration";
159 Value type = UNDEFINED;
160 double i_max = std::numeric_limits<double>::infinity();
161 double i_min = -std::numeric_limits<double>::infinity();
168 std::numeric_limits<double>::epsilon();
172inline bool is_zero(T value, T
tolerance = std::numeric_limits<T>::epsilon())
276 double p,
double i,
double d,
double u_max,
double u_min,
289 throw std::invalid_argument(
"Gains: u_min and u_max must not be NaN");
293 std::cout <<
"Received invalid u_min and u_max values: " <<
"u_min: " <<
u_min
294 <<
", u_max: " <<
u_max <<
". Setting saturation to false." << std::endl;
295 u_max_ = std::numeric_limits<double>::infinity();
296 u_min_ = -std::numeric_limits<double>::infinity();
300 bool validate(std::string &
error_msg)
const
314 error_msg =
"Gains: u_min and u_max must not be NaN";
321 catch (
const std::exception & e)
323 error_msg = e.what();
341 std::numeric_limits<double>::infinity();
343 -std::numeric_limits<double>::infinity();
344 double u_max_ = std::numeric_limits<double>::infinity();
345 double u_min_ = -std::numeric_limits<double>::infinity();
364 double p = 0.0,
double i = 0.0,
double d = 0.0,
365 double u_max = std::numeric_limits<double>::infinity(),
366 double u_min = -std::numeric_limits<double>::infinity(),
396 double p,
double i,
double d,
double u_max,
double u_min,
431 double &
p,
double & i,
double &
d,
double &
u_max,
double &
u_min,
467 double p,
double i,
double d,
double u_max,
double u_min,
580 double error,
double error_dot,
const std::chrono::nanoseconds &
dt_ns);
612 gains_box_ =
source.gains_box_;
626 std::numeric_limits<double>::infinity(),
627 -std::numeric_limits<double>::infinity(),
633 double p_error_last_ = 0;