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_error: 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_error: 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_error.is_nan() {
54 0.0
55 } else {
56 (error - self.pre_error) / dt
57 };
58 let output = self.config.gain.kp * error
59 + self.config.gain.ki * self.i_term
60 + self.config.gain.kd * d_term;
61 self.pre_error = error;
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_pid_controller_p() {
72 let gain = crate::PidGain {
73 kp: 1.0,
74 ki: 0.0,
75 kd: 0.0,
76 };
77 let mut pid = Pid::new(gain.into());
78
79 let output = pid.update(1.0, 0.0, 1.0);
80 assert_eq!(output, 1.0);
81 }
82
83 #[test]
84 fn test_pid_controller_i() {
85 let gain = crate::PidGain {
86 kp: 0.0,
87 ki: 1.0,
88 kd: 0.0,
89 };
90 let mut pid = Pid::new(gain.into());
91
92 let output = pid.update(1.0, 0.0, 1.0);
93 assert_eq!(output, 1.0);
94 let output = pid.update(1.0, 0.0, 1.0);
95 assert_eq!(output, 2.0);
96 let output = pid.update(1.0, 0.0, 1.0);
97 assert_eq!(output, 3.0);
98 }
99
100 #[test]
101 fn test_pid_controller_d() {
102 let gain = crate::PidGain {
103 kp: 0.0,
104 ki: 0.0,
105 kd: 1.0,
106 };
107 let mut pid = Pid::new(gain.into());
108
109 let output = pid.update(1.0, 0.0, 1.0);
110 assert_eq!(output, 0.0);
111 let output = pid.update(1.0, 1.0, 1.0);
112 assert_eq!(output, -1.0);
113 }
114
115 #[test]
116 fn test_pid_controller_limits() {
117 let config = PidConfig::new(1.0, 0.0, 0.0).with_limits(-0.5, 0.5);
118 let mut pid = Pid::new(config);
119
120 let output = pid.update(1.0, 0.0, 1.0);
121 assert_eq!(output, 0.5);
122 let output = pid.update(-1.0, 0.0, 1.0);
123 assert_eq!(output, -0.5);
124 }
125}