One Motor 0.5.1
RoboMaster全平台一站式电机驱动库
载入中...
搜索中...
未找到
PID.hpp
浏览该文件的文档.
1
7#ifndef PID_HPP
8#define PID_HPP
9#include <type_traits>
10
13
14namespace OneMotor::Control
15{
20 template <Util::Arithmetic ValueType_ = float>
22 {
23 ValueType_ Kp{1.0f};
24 ValueType_ Ki{0.0f};
25 ValueType_ Kd{0.0f};
26 ValueType_ MaxOutput{std::numeric_limits<ValueType_>::infinity()};
27 ValueType_ Deadband{0.0f};
28 ValueType_ IntegralLimit{std::numeric_limits<ValueType_>::infinity()};
29 ValueType_ DerivativeFilterRC{0.02f};
30 ValueType_ OutputFilterRC{0.02f};
31 };
32
37 {
38 };
39
44 {
45 };
46
47 // 特性标签
49 struct WithDeadband // 死区
50 {
51 };
52
54 struct WithIntegralLimit // 积分限幅
55 {
56 };
57
59 struct WithDerivativeOnMeasurement // 微分先行
60 {
61 };
62
64 struct WithDerivativeFilter // 微分项滤波
65 {
66 };
67
69 struct WithOutputFilter // 输出滤波
70 {
71 };
72
74 struct WithOutputLimit // 输出限幅
75 {
76 };
77
96 template <typename Algorithm = Positional, Util::Arithmetic ValueType = float, typename... Features>
98 {
99 // 特性检查
100 static constexpr bool PositionalPID = std::is_same_v<Algorithm, Positional>;
101 static constexpr bool HasDeadband = (std::is_same_v<Features, WithDeadband> || ...);
102 static constexpr bool HasIntegralLimit = (std::is_same_v<Features, WithIntegralLimit> || ...);
103 static constexpr bool HasDerivativeOnMeasurement =
104 (std::is_same_v<Features, WithDerivativeOnMeasurement> || ...);
105 static constexpr bool HasDerivativeFilter = (std::is_same_v<Features, WithDerivativeFilter> || ...);
106 static constexpr bool HasOutputFilter = (std::is_same_v<Features, WithOutputFilter> || ...);
107 static constexpr bool HasOutputLimit = (std::is_same_v<Features, WithOutputLimit> || ...);
108
109 // 状态变量
110 ValueType ITerm{};
111 ValueType prev_error{};
112 ValueType prev_prev_error{};
113 ValueType prev_ref{};
114 ValueType prev_measure{};
115 ValueType prev_derivative{};
116 ValueType prev_output{};
117 Util::DeltaT<ValueType> deltaT{};
118
119 public:
120 mutable ValueType MaxOutputVal;
121 mutable ValueType DeadbandVal;
122 mutable ValueType IntegralLimitVal;
123 mutable ValueType Kp;
124 mutable ValueType Ki;
125 mutable ValueType Kd;
126 mutable ValueType D_RC;
127 mutable ValueType O_RC;
128
133 explicit PIDController(const PID_Params<ValueType>& params) :
134 MaxOutputVal(params.MaxOutput), DeadbandVal(params.Deadband), IntegralLimitVal(params.IntegralLimit),
135 Kp(params.Kp), Ki(params.Ki), Kd(params.Kd),
136 D_RC(params.DerivativeFilterRC), O_RC(params.OutputFilterRC)
137 {
138 }
139
146 ValueType compute(ValueType ref, ValueType measure)
147 {
148 const ValueType error = ref - measure;
149 if constexpr (HasDeadband)
150 {
151 if (std::abs(error) <= DeadbandVal)
152 {
153 return prev_output;
154 }
155 }
156 ValueType dt = deltaT.getDeltaMS();
157 ValueType P, I{}, D, output;
158 if constexpr (PositionalPID)
159 {
160 P = Kp * error;
161 ITerm = Ki * error * dt;
162 }
163 else
164 {
165 P = Kp * (error - prev_error);
166 ITerm = Ki * error * dt;
167 }
168
169 D = [&]
170 {
171 if constexpr (HasDerivativeOnMeasurement)
172 {
173 ValueType meas_deriv = -(measure - prev_measure) / dt;
174 prev_measure = measure;
175 return meas_deriv;
176 }
177 else if constexpr (PositionalPID)
178 {
179 return (error - prev_error) / dt;
180 }
181 else
182 {
183 return (error - 2 * prev_error + prev_prev_error) / dt;
184 }
185 }();
186 D *= Kd;
187
188 // 应用微分滤波
189 if constexpr (HasDerivativeFilter)
190 {
191 D = D * dt / (D_RC + dt) + prev_derivative * D_RC / (D_RC + dt);
192 }
193 // 应用积分限幅
194 if constexpr (HasIntegralLimit)
195 {
196 ValueType temp_Iout = I + ITerm;
197 if (const ValueType temp_Output = P + I + D; abs(temp_Output) > MaxOutputVal)
198 {
199 if (error * I > 0)
200 {
201 ITerm = 0;
202 }
203 }
204 if (temp_Iout > IntegralLimitVal)
205 {
206 ITerm = 0;
208 }
209 if (temp_Iout < -IntegralLimitVal)
210 {
211 ITerm = 0;
212 I = -IntegralLimitVal;
213 }
214 }
215
216 I += ITerm;
217 output = P + I + D;
218
219 // 应用输出滤波
220 if constexpr (HasOutputFilter)
221 {
222 output = output * dt / (O_RC + dt) + prev_output * O_RC / (O_RC + dt);
223 }
224
225 // 应用输出限幅
226 if constexpr (HasOutputLimit)
227 {
228 output = std::clamp(output, -MaxOutputVal, MaxOutputVal);
229 }
230
231 prev_ref = ref;
232 prev_derivative = D;
233 prev_output = output;
234 prev_error = error;
235
236 return output;
237 }
238
243 void reset()
244 {
245 ITerm = ValueType{};
246 prev_error = ValueType{};
247 prev_prev_error = ValueType{};
248 prev_ref = ValueType{};
249 prev_measure = ValueType{};
250 prev_derivative = ValueType{};
251 prev_output = ValueType{};
252
253 deltaT.reset();
254 }
255 };
256}
257
258#endif //PID_HPP
定义了一个C++20概念,用于约束模板参数必须为算术类型。
提供一个工具类来计算两次调用之间的时间差。
ValueType compute(ValueType ref, ValueType measure)
计算PID输出。
定义 PID.hpp:146
void reset()
重置PID控制器的内部状态。
定义 PID.hpp:243
PIDController(const PID_Params< ValueType > &params)
PID控制器的构造函数。
定义 PID.hpp:133
一个用于计算时间增量 (delta time) 的工具类。
定义 DeltaT.hpp:28
约束一个类型 T 必须是整数类型或浮点数类型。
定义 Arithmetic.hpp:20
增量式PID算法标签。
定义 PID.hpp:44
PID控制器的参数。
定义 PID.hpp:22
ValueType_ DerivativeFilterRC
微分项滤波器的时间常数 (RC)
定义 PID.hpp:29
ValueType_ OutputFilterRC
输出滤波器的时间常数 (RC)
定义 PID.hpp:30
ValueType_ Ki
积分增益
定义 PID.hpp:24
ValueType_ Kd
微分增益
定义 PID.hpp:25
ValueType_ Kp
比例增益
定义 PID.hpp:23
ValueType_ IntegralLimit
积分项限幅
定义 PID.hpp:28
ValueType_ MaxOutput
最大输出值
定义 PID.hpp:26
ValueType_ Deadband
死区范围
定义 PID.hpp:27
位置式PID算法标签。
定义 PID.hpp:37
死区特性标签。如果误差的绝对值小于死区值,则PID输出保持不变。
定义 PID.hpp:50
微分项滤波特性标签。为微分项添加一个低通滤波器。
定义 PID.hpp:65
微分先行特性标签 (Derivative on Measurement)。微分项基于测量值的变化率,而不是误差的变化率。
定义 PID.hpp:60
积分限幅特性标签。限制积分项的累积范围。
定义 PID.hpp:55
输出滤波特性标签。为最终输出添加一个低通滤波器。
定义 PID.hpp:70
输出限幅特性标签。限制PID控制器的最终输出范围。
定义 PID.hpp:75