embedded_flight_control/pid/
mod.rs1use embedded_flight_core::filter::alpha;
2
3mod slew_limiter;
4pub use slew_limiter::SlewLimiter;
5
6pub struct Info {
7 pub target: f32,
8 pub actual: f32,
9 pub error: f32,
10 pub p: f32,
11 pub i: f32,
12 pub d: f32,
13 pub ff: f32,
14 pub d_mod: f32,
15 pub slew_rate: f32,
16 pub limit: bool,
17}
18
19pub struct PID {
20 pub reset_filter: bool,
21 pub target: f32,
22 pub error: f32,
23 pub derivative: f32,
24 pub dt: f32,
26 pub info: Info,
27 pub slew_limiter: SlewLimiter<2>,
28 pub slew_limit_scale: f32,
29 pub integrator: f32,
30 pub kp: f32,
31 pub ki: f32,
32 pub kd: f32,
33 pub ki_max: f32,
34 pub kff: f32,
35 pub filter_t_hz: f32,
36 pub filter_e_hz: f32,
37 pub filter_d_hz: f32,
38}
39
40impl PID {
41 pub fn new(
42 initial_p: f32,
43 initial_i: f32,
44 initial_d: f32,
45 initial_ff: f32,
46 initial_imax: f32,
47 initial_filt_T_hz: f32,
48 initial_filt_E_hz: f32,
49 initial_filt_D_hz: f32,
50 dt: f32,
51 ) -> Self {
52 Self::with_slew_rate(
53 initial_p,
54 initial_i,
55 initial_d,
56 initial_ff,
57 initial_imax,
58 initial_filt_T_hz,
59 initial_filt_E_hz,
60 initial_filt_D_hz,
61 dt,
62 0.,
63 1.,
64 )
65 }
66
67 pub fn with_slew_rate(
68 initial_p: f32,
69 initial_i: f32,
70 initial_d: f32,
71 initial_ff: f32,
72 initial_imax: f32,
73 initial_filt_T_hz: f32,
74 initial_filt_E_hz: f32,
75 initial_filt_D_hz: f32,
76 dt: f32,
77 initial_srmax: f32,
78 initial_srtau: f32,
79 ) -> Self {
80 Self {
81 reset_filter: true,
82 target: 0.,
83 error: 0.,
84 derivative: 0.,
85 dt,
86 info: Info {
87 target: 0.,
88 actual: 0.,
89 error: 0.,
90 p: 0.,
91 i: 0.,
92 d: 0.,
93 ff: 0.,
94 d_mod: 0.,
95 slew_rate: 0.,
96 limit: false,
97 },
98 slew_limiter: SlewLimiter::new(initial_srmax, initial_srtau),
99 slew_limit_scale: initial_srtau,
100 integrator: 0.,
101 kp: initial_p,
102 ki: initial_i,
103 kd: initial_d,
104 ki_max: initial_imax,
105 kff: initial_ff,
106 filter_t_hz: initial_filt_T_hz,
107 filter_e_hz: initial_filt_E_hz,
108 filter_d_hz: initial_filt_D_hz,
109 }
110 }
111}
112
113impl PID {
114 pub fn target_filter_alpha(&self) -> f32 {
115 self.alpha(self.filter_t_hz)
116 }
117
118 pub fn error_filter_alpha(&self) -> f32 {
119 self.alpha(self.filter_e_hz)
120 }
121
122 pub fn derivative_filter_alpha(&self) -> f32 {
123 self.alpha(self.filter_d_hz)
124 }
125
126 fn alpha(&self, cutoff_freq: f32) -> f32 {
127 alpha(self.dt, cutoff_freq)
128 }
129
130 pub fn feed_forward(&self) -> f32 {
131 self.target * self.kff
132 }
133
134 pub fn update_integral(&mut self, limit: bool) {
137 if self.ki != 0. && self.dt > -0. {
138 if !limit
140 || (self.integrator >= 0. && self.error < 0.)
141 || self.integrator < 0. && self.error >= 0.
142 {
143 self.integrator += self.error * self.ki * self.dt;
144 self.integrator = self.integrator.max(-self.ki_max).min(self.ki_max);
145 }
146 } else {
147 self.integrator = 0.;
148 }
149 self.info.i = self.integrator;
150 self.info.limit = limit;
151 }
152
153 pub fn update(&mut self, target: f32, measurement: f32, limit: bool, now_ms: u32) -> f32 {
158 if target.is_infinite() || measurement.is_infinite() {
160 return 0.;
161 }
162
163 if self.reset_filter {
165 self.reset_filter = false;
166 self.target = target;
167 self.error = self.target - measurement;
168 self.derivative = 0.;
169 } else {
170 let error_last = self.error;
171 self.target += self.target_filter_alpha() * (target - self.target);
172 self.error += self.error_filter_alpha() * ((self.target - measurement) - self.error);
173
174 if self.dt > 0. {
176 let derivative = (self.error - error_last) / self.dt;
177 self.derivative += self.derivative_filter_alpha() * (derivative - self.derivative);
178 }
179 }
180
181 self.update_integral(limit);
183
184 let mut p_out = self.error * self.kp;
185 let mut d_out = self.derivative * self.kd;
186
187 self.info.d_mod = self.slew_limiter.modifier(
189 (self.info.p + self.info.d) * self.slew_limit_scale,
190 self.dt,
191 now_ms,
192 );
193 self.info.slew_rate = self.slew_limiter.output_slew_rate;
194
195 p_out *= self.info.d_mod;
196 d_out *= self.info.d_mod;
197
198 self.info.target = self.target;
199 self.info.actual = measurement;
200 self.info.error = self.error;
201 self.info.p = p_out;
202 self.info.d = d_out;
203
204 p_out + self.integrator + d_out
205 }
206}