1use super::FloatType;
20use super::PidConfig;
21use super::PidController;
22
23#[derive(Debug, Clone)]
25pub struct PiD {
26 config: PidConfig,
27 i_term: FloatType,
28 pre_actual: FloatType,
29}
30
31impl Default for PiD {
32 fn default() -> Self {
34 Self::new(PidConfig::default())
35 }
36}
37
38impl PidController for PiD {
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.kp * error + self.config.gain.ki * self.i_term
59 - self.config.gain.kd * d_term;
60 self.pre_actual = actual;
61 output.clamp(self.config.min, self.config.max)
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn test_pi_d_controller_p() {
71 let gain = crate::PidGain {
72 kp: 1.0,
73 ki: 0.0,
74 kd: 0.0,
75 };
76 let mut pid = PiD::new(gain.into());
77
78 let output = pid.update(1.0, 0.0, 1.0);
79 assert_eq!(output, 1.0);
80 }
81
82 #[test]
83 fn test_pi_d_controller_i() {
84 let gain = crate::PidGain {
85 kp: 0.0,
86 ki: 1.0,
87 kd: 0.0,
88 };
89 let mut pid = PiD::new(gain.into());
90
91 let output = pid.update(1.0, 0.0, 1.0);
92 assert_eq!(output, 1.0);
93 let output = pid.update(1.0, 0.0, 1.0);
94 assert_eq!(output, 2.0);
95 let output = pid.update(1.0, 0.0, 1.0);
96 assert_eq!(output, 3.0);
97 }
98
99 #[test]
100 fn test_pi_d_controller_d() {
101 let gain = crate::PidGain {
102 kp: 0.0,
103 ki: 0.0,
104 kd: 1.0,
105 };
106 let mut pid = PiD::new(gain.into());
107
108 let output = pid.update(0.0, 0.0, 1.0);
109 assert_eq!(output, 0.0);
110 let output = pid.update(1.0, 0.0, 1.0);
111 assert_eq!(output, 0.0);
112 let output = pid.update(1.0, 1.0, 1.0);
113 assert_eq!(output, -1.0);
114 }
115}