19#ifndef CONTROL_TOOLBOX__RATE_LIMITER_HPP_
20#define CONTROL_TOOLBOX__RATE_LIMITER_HPP_
59 T
min_value = std::numeric_limits<T>::quiet_NaN(),
60 T
max_value = std::numeric_limits<T>::quiet_NaN(),
125 T
min_value = std::numeric_limits<T>::quiet_NaN(),
126 T
max_value = std::numeric_limits<T>::quiet_NaN(),
136 bool has_value_limits_ =
true;
137 bool has_first_derivative_limits_ =
true;
138 bool has_second_derivative_limits_ =
true;
141 T min_value_ = std::numeric_limits<T>::quiet_NaN();
142 T max_value_ = std::numeric_limits<T>::quiet_NaN();
145 T min_first_derivative_neg_ = std::numeric_limits<T>::quiet_NaN();
146 T max_first_derivative_pos_ = std::numeric_limits<T>::quiet_NaN();
147 T min_first_derivative_pos_ = std::numeric_limits<T>::quiet_NaN();
148 T max_first_derivative_neg_ = std::numeric_limits<T>::quiet_NaN();
151 T min_second_derivative_ = std::numeric_limits<T>::quiet_NaN();
152 T max_second_derivative_ = std::numeric_limits<T>::quiet_NaN();
183 if (std::isnan(max_value_))
185 has_value_limits_ =
false;
187 if (std::isnan(min_value_))
189 min_value_ = -max_value_;
191 if (has_value_limits_ && min_value_ > max_value_)
193 throw std::invalid_argument(
"Invalid value limits");
196 if (std::isnan(max_first_derivative_pos_))
198 has_first_derivative_limits_ =
false;
200 if (std::isnan(min_first_derivative_neg_))
202 min_first_derivative_neg_ = -max_first_derivative_pos_;
204 if (has_first_derivative_limits_ && min_first_derivative_neg_ > max_first_derivative_pos_)
206 throw std::invalid_argument(
"Invalid first derivative limits");
208 if (has_first_derivative_limits_)
210 if (std::isnan(max_first_derivative_neg_))
212 max_first_derivative_neg_ = max_first_derivative_pos_;
214 if (std::isnan(min_first_derivative_pos_))
216 min_first_derivative_pos_ = min_first_derivative_neg_;
218 if (has_first_derivative_limits_ && min_first_derivative_pos_ > max_first_derivative_neg_)
220 throw std::invalid_argument(
"Invalid first derivative limits");
224 if (std::isnan(max_second_derivative_))
226 has_second_derivative_limits_ =
false;
228 if (std::isnan(min_second_derivative_))
230 min_second_derivative_ = -max_second_derivative_;
232 if (has_second_derivative_limits_ && min_second_derivative_ > max_second_derivative_)
234 throw std::invalid_argument(
"Invalid second derivative limits");
243 limit_second_derivative(
v, v0, v1,
dt);
244 limit_first_derivative(
v, v0,
dt);
247 return tmp !=
static_cast<T
>(0.0) ?
v /
tmp :
static_cast<T
>(1.0);
255 if (has_value_limits_)
257 v = std::clamp(
v, min_value_, max_value_);
260 return tmp !=
static_cast<T
>(0.0) ?
v /
tmp :
static_cast<T
>(1.0);
268 if (has_first_derivative_limits_)
271 if (v0 >
static_cast<T
>(0.0))
273 dv_max = max_first_derivative_pos_ *
dt;
274 dv_min = min_first_derivative_pos_ *
dt;
276 else if (v0 <
static_cast<T
>(0.0))
278 dv_min = min_first_derivative_neg_ *
dt;
279 dv_max = max_first_derivative_neg_ *
dt;
283 dv_min = min_first_derivative_neg_ *
dt;
284 dv_max = max_first_derivative_pos_ *
dt;
291 return tmp !=
static_cast<T
>(0.0) ?
v /
tmp :
static_cast<T
>(1.0);
299 if (has_second_derivative_limits_)
302 const T
dv0 = v0 - v1;
307 if ((
dv -
dv0) * (
v - v0) > 0)
311 const T
da_min = min_second_derivative_ *
dt2;
312 const T
da_max = max_second_derivative_ *
dt2;
320 return tmp !=
static_cast<T
>(0.0) ?
v /
tmp :
static_cast<T
>(1.0);