1use super::FloatType;
20use super::PidConfig;
21use super::PidController;
22
23#[derive(Debug, Clone)]
25pub struct Ipd {
26 config: PidConfig,
27 i_term: FloatType,
28 pre_actual: FloatType,
29}
30
31impl Default for Ipd {
32 fn default() -> Self {
34 Self::new(PidConfig::default())
35 }
36}
37
38impl PidController for Ipd {
39 fn new(config: PidConfig) -> Self {
41 Self {
42 config,
43 i_term: 0.0,
44 pre_actual: FloatType::NAN,
45 }
46 }
47
48 fn update(&mut self, set_point: FloatType, actual: FloatType, dt: FloatType) -> FloatType {
51 let error = set_point - actual;
52 self.i_term += error * dt;
53 let d_term = if self.pre_actual.is_nan() {
54 0.0
55 } else {
56 (actual - self.pre_actual) / dt
57 };
58 let output = self.config.gain.ki * self.i_term
59 - self.config.gain.kp * actual
60 - self.config.gain.kd * d_term;
61 self.pre_actual = actual;
62 output.clamp(self.config.min, self.config.max)
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_i_pd_controller_p() {
72 let gain = crate::PidGain {
73 kp: 1.0,
74 ki: 0.0,
75 kd: 0.0,
76 };
77 let mut pid = Ipd::new(gain.into());
78
79 let output = pid.update(1.0, 0.0, 1.0);
80 assert_eq!(output, 0.0);
81 let output = pid.update(1.0, 1.0, 1.0);
82 assert_eq!(output, -1.0);
83 }
84
85 #[test]
86 fn test_i_pd_controller_i() {
87 let gain = crate::PidGain {
88 kp: 0.0,
89 ki: 1.0,
90 kd: 0.0,
91 };
92 let mut pid = Ipd::new(gain.into());
93
94 let output = pid.update(1.0, 0.0, 1.0);
95 assert_eq!(output, 1.0);
96 let output = pid.update(1.0, 0.0, 1.0);
97 assert_eq!(output, 2.0);
98 let output = pid.update(1.0, 0.0, 1.0);
99 assert_eq!(output, 3.0);
100 }
101
102 #[test]
103 fn test_i_pd_controller_d() {
104 let gain = crate::PidGain {
105 kp: 0.0,
106 ki: 0.0,
107 kd: 1.0,
108 };
109 let mut pid = Ipd::new(gain.into());
110
111 let output = pid.update(0.0, 0.0, 1.0);
112 assert_eq!(output, 0.0);
113 let output = pid.update(1.0, 0.0, 1.0);
114 assert_eq!(output, 0.0);
115 let output = pid.update(1.0, 1.0, 1.0);
116 assert_eq!(output, -1.0);
117 }
118}