One Motor 0.6.0
RoboMaster全平台一站式电机驱动库
载入中...
搜索中...
未找到
PID.hpp
浏览该文件的文档.
1
7#ifndef PID_HPP
8#define PID_HPP
9#include <type_traits>
10#include <limits>
11#include <cmath>
12#include <algorithm>
13
16
17namespace OneMotor::Control
18{
23 template <Arithmetic ValueType_ = float>
25 {
26 ValueType_ Kp{};
27 ValueType_ Ki{};
28 ValueType_ Kd{};
29#ifdef ONE_MOTOR_LINUX
30 ValueType_ MaxOutput{std::numeric_limits<ValueType_>::infinity()};
31#else
32 //TODO: 等Zephyr SDK更新看能不能修bug
33 ValueType_ MaxOutput{};
34#endif
35
36 ValueType_ Deadband{};
37#ifdef ONE_MOTOR_LINUX
38 ValueType_ IntegralLimit{std::numeric_limits<ValueType_>::infinity()};
39#else
40 ValueType_ IntegralLimit{};
41#endif
42 ValueType_ DerivativeFilterRC{};
43 ValueType_ OutputFilterRC{};
44 };
45
50 {
51 };
52
57 {
58 };
59
60 // 特性标签
62 struct WithDeadband // 死区
63 {
64 };
65
67 struct WithIntegralLimit // 积分限幅
68 {
69 };
70
72 struct WithDerivativeOnMeasurement // 微分先行
73 {
74 };
75
77 struct WithDerivativeFilter // 微分项滤波
78 {
79 };
80
82 struct WithOutputFilter // 输出滤波
83 {
84 };
85
87 struct WithOutputLimit // 输出限幅
88 {
89 };
90
95 template <typename... Fs>
97 {
98 };
99
100 namespace Detail
101 {
107 template <typename Target, typename T>
108 struct HasFeatureCheck : std::is_same<Target, T>
109 {
110 };
111
112 // 特化:如果当前类型是 FeaturePack,则递归检查包内的所有类型
113 template <typename Target, typename... Fs>
114 struct HasFeatureCheck<Target, FeaturePack<Fs...>>
115 {
116 // 使用折叠表达式递归展开
117 static constexpr bool value = (HasFeatureCheck<Target, Fs>::value || ...);
118 };
119 }
120
139 template <typename Algorithm = Positional, Arithmetic ValueType = float, typename... Features>
141 {
142 template <typename TargetFeature>
143 static constexpr bool Check = (Detail::HasFeatureCheck<TargetFeature, Features>::value || ...);
144
145 // 特性检查
146 static constexpr bool PositionalPID = std::is_same_v<Algorithm, Positional>;
147
148 static constexpr bool HasDeadband = Check<WithDeadband>;
149 static constexpr bool HasIntegralLimit = Check<WithIntegralLimit>;
150 static constexpr bool HasDerivativeOnMeasurement = Check<WithDerivativeOnMeasurement>;
151 static constexpr bool HasDerivativeFilter = Check<WithDerivativeFilter>;
152 static constexpr bool HasOutputFilter = Check<WithOutputFilter>;
153 static constexpr bool HasOutputLimit = Check<WithOutputLimit>;
154
155 // 状态变量
156 ValueType ITerm{};
157 ValueType prev_error{};
158 ValueType prev_prev_error{};
159 ValueType prev_ref{};
160 ValueType prev_measure{};
161 ValueType prev_derivative{};
162 ValueType prev_output{};
163 DeltaT<ValueType> deltaT{};
164
165 public:
166 using ParamsType = PID_Params<ValueType>;
167 using ValType = ValueType;
168 mutable ValueType MaxOutputVal;
169 mutable ValueType DeadbandVal;
170 mutable ValueType IntegralLimitVal;
171 mutable ValueType Kp;
172 mutable ValueType Ki;
173 mutable ValueType Kd;
174 mutable ValueType D_RC;
175 mutable ValueType O_RC;
176
181 explicit PIDController(const PID_Params<ValueType>& params) :
182 MaxOutputVal(params.MaxOutput), DeadbandVal(params.Deadband), IntegralLimitVal(params.IntegralLimit),
183 Kp(params.Kp), Ki(params.Ki), Kd(params.Kd),
184 D_RC(params.DerivativeFilterRC), O_RC(params.OutputFilterRC)
185 {
186 }
187
194 ValueType compute(ValueType ref, ValueType measure)
195 {
196 const ValueType error = ref - measure;
197 if constexpr (HasDeadband)
198 {
199 if (std::abs(error) <= DeadbandVal)
200 {
201 return prev_output;
202 }
203 }
204 ValueType dt = deltaT.getDeltaMS();
205 ValueType P, I{}, D, output;
206 if constexpr (PositionalPID)
207 {
208 P = Kp * error;
209 ITerm = Ki * error * dt;
210 }
211 else
212 {
213 P = Kp * (error - prev_error);
214 ITerm = Ki * error * dt;
215 }
216
217 D = [&]
218 {
219 if constexpr (HasDerivativeOnMeasurement)
220 {
221 ValueType meas_deriv = -(measure - prev_measure) / dt;
222 prev_measure = measure;
223 return meas_deriv;
224 }
225 else if constexpr (PositionalPID)
226 {
227 return (error - prev_error) / dt;
228 }
229 else
230 {
231 return (error - 2 * prev_error + prev_prev_error) / dt;
232 }
233 }();
234 D *= Kd;
235
236 // 应用微分滤波
237 if constexpr (HasDerivativeFilter)
238 {
239 D = D * dt / (D_RC + dt) + prev_derivative * D_RC / (D_RC + dt);
240 }
241 // 应用积分限幅
242 if constexpr (HasIntegralLimit)
243 {
244 ValueType temp_Iout = I + ITerm;
245 if (const ValueType temp_Output = P + I + D; abs(temp_Output) > MaxOutputVal)
246 {
247 if (error * I > 0)
248 {
249 ITerm = 0;
250 }
251 }
252 if (temp_Iout > IntegralLimitVal)
253 {
254 ITerm = 0;
256 }
257 if (temp_Iout < -IntegralLimitVal)
258 {
259 ITerm = 0;
260 I = -IntegralLimitVal;
261 }
262 }
263
264 I += ITerm;
265 output = P + I + D;
266
267 // 应用输出滤波
268 if constexpr (HasOutputFilter)
269 {
270 output = output * dt / (O_RC + dt) + prev_output * O_RC / (O_RC + dt);
271 }
272
273 // 应用输出限幅
274 if constexpr (HasOutputLimit)
275 {
276 output = std::clamp(output, -MaxOutputVal, MaxOutputVal);
277 }
278
279 prev_ref = ref;
280 prev_derivative = D;
281 prev_output = output;
282 prev_error = error;
283
284 return output;
285 }
286
291 void reset()
292 {
293 ITerm = ValueType{};
294 prev_error = ValueType{};
295 prev_prev_error = ValueType{};
296 prev_ref = ValueType{};
297 prev_measure = ValueType{};
298 prev_derivative = ValueType{};
299 prev_output = ValueType{};
300
301 deltaT.reset();
302 }
303 };
304}
305
306#endif //PID_HPP
定义了一个C++20概念,用于约束模板参数必须为算术类型。
提供一个工具类来计算两次调用之间的时间差。
ValueType compute(ValueType ref, ValueType measure)
计算PID输出。
定义 PID.hpp:194
void reset()
重置PID控制器的内部状态。
定义 PID.hpp:291
PIDController(const PID_Params< ValueType > &params)
PID控制器的构造函数。
定义 PID.hpp:181
一个用于计算时间增量 (delta time) 的工具类。
定义 DeltaT.hpp:30
约束一个类型 T 必须是整数类型或浮点数类型。
定义 Arithmetic.hpp:20
递归检查特性是否存在。
定义 PID.hpp:109
特性包容器,用于将多个特性打包成一个类型。
定义 PID.hpp:97
增量式PID算法标签。
定义 PID.hpp:57
PID控制器的参数。
定义 PID.hpp:25
ValueType_ DerivativeFilterRC
定义 PID.hpp:42
ValueType_ OutputFilterRC
定义 PID.hpp:43
ValueType_ Deadband
定义 PID.hpp:36
位置式PID算法标签。
定义 PID.hpp:50
死区特性标签。如果误差的绝对值小于死区值,则PID输出保持不变。
定义 PID.hpp:63
微分项滤波特性标签。为微分项添加一个低通滤波器。
定义 PID.hpp:78
微分先行特性标签 (Derivative on Measurement)。微分项基于测量值的变化率,而不是误差的变化率。
定义 PID.hpp:73
积分限幅特性标签。限制积分项的累积范围。
定义 PID.hpp:68
输出滤波特性标签。为最终输出添加一个低通滤波器。
定义 PID.hpp:83
输出限幅特性标签。限制PID控制器的最终输出范围。
定义 PID.hpp:88