1#![no_std]
3use num_traits::{float::FloatCore};
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
9pub enum PidError {
10 LimitOutBound,
11}
12
13#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Debug)]
14#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
15pub struct Limits<T: FloatCore + core::default::Default> {
16 lower: T,
17 upper: T,
18}
19
20impl<T: FloatCore + core::default::Default> Limits<T> {
21 fn new() -> Self {
22 Limits{lower: T::neg_infinity(), upper: T::infinity()}
23 }
24
25 fn clamp(&self, val: T) -> T {
26 val.min(self.upper).max(self.lower)
27 }
28
29 pub fn set_limit(&mut self, val: T) -> &mut Self {
30 self.lower = -val.abs();
31 self.upper = val.abs();
32 self
33 }
34
35 pub fn try_set_upper(&mut self, val: T) -> Result<&mut Self, PidError> {
36 if self.lower <= val {
37 self.upper = val;
38 Ok(self)
39 }
40 else {
41 Err(PidError::LimitOutBound)
42 }
43 }
44
45 pub fn try_set_lower(&mut self, val: T) -> Result<&mut Self, PidError> {
46 if self.upper >= val {
47 self.lower = val;
48 Ok(self)
49 }
50 else {
51 Err(PidError::LimitOutBound)
52 }
53 }
54}
55
56impl<T: FloatCore + core::default::Default> Default for Limits<T> {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61
62#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Debug, Default)]
63#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
64pub struct KPTerm<T: FloatCore + core::default::Default> {
65 pub limits: Limits<T>,
66 scale: T,
67}
68
69impl<T:FloatCore + core::default::Default> KPTerm<T> {
70 pub fn new() -> Self {
71 KPTerm::default()
72 }
73 pub fn set_scale(&mut self, val: T) -> &mut Self {
74 self.scale = val;
75 self
76 }
77 pub fn step(&self, offset: T) -> T {
78 self.limits.clamp(self.scale * offset)
79 }
80}
81
82#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Debug, Default)]
83#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
84pub struct KITerm<T: FloatCore + core::default::Default> {
85 pub limits: Limits<T>,
86 scale: T,
87 pub accumulate: T
88}
89
90impl<T:FloatCore + core::default::Default> KITerm<T> {
91 pub fn new() -> Self {
92 KITerm::default()
93 }
94 pub fn set_scale(&mut self, val: T) -> &mut Self {
95 self.scale = val;
96 self
97 }
98 pub fn step(&mut self, offset: T, tdelta: T) -> T {
99 let i = self.limits.clamp(self.scale * offset * tdelta + self.accumulate);
100 self.accumulate = i;
101 i
102 }
103}
104
105#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Debug, Default)]
106#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
107pub struct KDTerm<T: FloatCore + core::default::Default> {
108 pub limits: Limits<T>,
109 scale: T,
110 pub prev_measurement: T
111}
112
113impl<T:FloatCore + core::default::Default> KDTerm<T> {
114 pub fn new() -> Self {
115 KDTerm::default()
116 }
117 pub fn set_scale(&mut self, val: T) -> &mut Self {
118 self.scale = val;
119 self
120 }
121 pub fn step(&mut self, measurement: T, tdelta: T) -> T {
122 let d = self.limits.clamp(self.scale * (self.prev_measurement - measurement) / tdelta);
123 self.prev_measurement = measurement;
124 d
125 }
126}
127
128#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Debug, Default)]
129#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
130pub struct PidCtrl <T: FloatCore + core::default::Default> {
131 pub kp: KPTerm<T>,
132 pub ki: KITerm<T>,
133 pub kd: KDTerm<T>,
134 pub limits: Limits<T>,
135
136 pub setpoint: T,
137}
138
139impl<T: FloatCore + core::default::Default> PidCtrl<T>
140 {
141 pub fn new() -> Self {
142 PidCtrl::default()
143 }
144
145 pub fn new_with_pid(p: T, i: T, d: T) -> Self {
146 Self{
147 kp: KPTerm{limits:Limits::new(), scale: p},
148 ki: KITerm{limits:Limits::new(), scale: i, accumulate:T::zero()},
149 kd: KDTerm{limits:Limits::new(), scale: d, prev_measurement:T::zero()},
150 limits: Limits::new(), setpoint: T::zero(),
151 }
152 }
153
154 pub fn init(&mut self, setpoint: T, prev_measurement: T) -> &mut Self {
155 self.setpoint = setpoint;
156 self.kd.prev_measurement = prev_measurement;
157 self
158 }
159
160 pub fn step(&mut self, input: PidIn<T>) -> PidOut<T> {
161 let offset = self.setpoint - input.measurement;
162 let p = self.kp.step(offset);
163 let i = self.ki.step(offset, input.tdelta);
164 let d = self.kd.step(input.measurement, input.tdelta);
165 PidOut::new(p, i, d, self.limits.clamp(p + i + d))
166 }
167 }
168
169#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Debug, Default)]
170#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
171pub struct PidIn <T: FloatCore + core::default::Default> {
172 measurement: T,
173 tdelta: T,
174}
175
176impl<T: FloatCore + core::default::Default> PidIn<T> {
177 pub fn new(measurement:T, tdelta:T) -> Self {
178 let tdelta_clamped = tdelta.min(T::infinity()).max(T::epsilon());
179 PidIn{measurement, tdelta: tdelta_clamped}
180 }
181 }
182
183#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Debug, Default)]
184#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
185pub struct PidOut <T: FloatCore + core::default::Default> {
186 pub p: T,
187 pub i: T,
188 pub d: T,
189 pub out: T,
190}
191
192impl<T: FloatCore + core::default::Default> PidOut<T> {
193 pub fn new(p:T, i:T, d:T, out:T) -> Self {
194 Self{p, i, d, out}
195 }
196 }
197
198#[cfg(test)]
199mod tests {
200 #[test]
201 fn limits_error() {
202 let mut pid = super::PidCtrl::new_with_pid(3.0, 2.0, 1.0);
203 pid.kp.limits.try_set_lower(10.0).unwrap();
204 assert_eq!(super::PidError::LimitOutBound, pid.kp.limits.try_set_upper(5.0).unwrap_err());
205 }
206
207 #[test]
208 fn kp() {
209 let kp = 0.2;
210 let measurement = 0.0;
211 let setpoint = 1.0;
212
213 let mut pid = super::PidCtrl::default();
214 pid.init(setpoint, 0.0);
215 pid.kp.set_scale(kp);
216
217 let kpterm = kp * (setpoint - measurement);
218
219 let inp = super::PidIn::new(measurement, 1.0);
220 assert_eq!(pid.step(inp), super::PidOut::new(kpterm, 0.0, 0.0, kpterm));
221 }
222
223 #[test]
224 fn ki() {
225 let ki = 1.0;
226 let measurement = 0.0;
227 let setpoint = 1.0;
228 let td = 1.0;
229
230 let mut pid = super::PidCtrl::default();
231 pid.init(setpoint, 0.0);
232 pid.ki.set_scale(ki);
233
234 let mut kiterm = 0.0;
235
236 kiterm += ki * (setpoint - measurement) * td;
237 let inp = super::PidIn::new(measurement, td);
238 assert_eq!(pid.step(inp), super::PidOut::new(0.0, kiterm, 0.0, kiterm));
239
240 kiterm += ki * (setpoint - measurement) * td;
241 let inp = super::PidIn::new(measurement, td);
242 assert_eq!(pid.step(inp), super::PidOut::new(0.0, kiterm, 0.0, kiterm));
243 }
244
245 #[test]
246 fn kd() {
247 let kd = 1.0;
248 let measurement = 0.0;
249 let setpoint = 1.0;
250 let td = 1.0;
251
252 let mut prev = 0.0;
253
254 let mut pid = super::PidCtrl::default();
255 pid.init(setpoint, prev);
256 pid.kd.set_scale(kd);
257
258 let mut kdterm = kd * (measurement - prev) / td;
259 prev = measurement;
260 let inp = super::PidIn::new(measurement, td);
261 assert_eq!(pid.step(inp), super::PidOut::new(0.0, 0.0, kdterm, kdterm));
262
263 kdterm = kd * (measurement - prev) / td;
264 let inp = super::PidIn::new(measurement, td);
265 assert_eq!(pid.step(inp), super::PidOut::new(0.0, 0.0, kdterm, kdterm));
266 }
267}