1use std::ops::{Add, Div, Mul, Sub};
2
3use num_traits::One;
4
5#[derive(Clone, Copy, Debug)]
6
7pub struct P<T> {
9 pub kp: T,
10}
11
12impl<T: One> Default for P<T> {
13 fn default() -> Self {
14 Self { kp: T::one() }
15 }
16}
17
18impl<T> P<T> {
19 pub fn new(damping_ratio: T, time_constant: T) -> Self
21 where
22 T: One + Add<Output = T> + Div<Output = T> + Copy,
23 {
24 let kp = (T::one() / (time_constant * time_constant))
25 * (T::one() + (T::one() + T::one()) * damping_ratio);
26 Self { kp }
27 }
28
29 pub fn control<U>(self, target: U, actual: U) -> T::Output
30 where
31 T: Mul<U> + Clone,
32 U: Sub<Output = U>,
33 {
34 let error = error(target, actual);
35 self.control_with_error(error)
36 }
37
38 pub fn control_with_error<U>(&self, error: U) -> T::Output
39 where
40 T: Mul<U> + Clone,
41 {
42 self.kp.clone() * error
43 }
44}
45
46#[derive(Clone, Debug)]
47pub struct PD<T> {
48 pub p: P<T>,
49 pub kd: T,
50}
51
52impl<T> PD<T> {
53 pub fn new(damping_ratio: T, time_constant: T) -> Self
54 where
55 T: One + Add<Output = T> + Div<Output = T> + Copy,
56 {
57 let kd = (T::one() / time_constant)
58 * (T::one() + (T::one() + T::one()) * time_constant * time_constant);
59 Self {
60 p: P::new(damping_ratio, time_constant),
61 kd,
62 }
63 }
64
65 pub fn control<U>(&self, target: U, target_dot: U, actual: U, actual_dot: U) -> U
66 where
67 T: Mul<U, Output = U> + Sub<Output = T> + Clone,
68 U: Add<Output = U> + Sub<Output = U>,
69 {
70 let p = self.p.clone().control(target, actual);
71 self.control_with_p(p, target_dot, actual_dot)
72 }
73
74 pub fn control_with_p<U>(&self, p: U, target_dot: U, actual_dot: U) -> U
75 where
76 T: Mul<U, Output = U> + Clone,
77 U: Add<Output = U> + Sub<Output = U>,
78 {
79 self.kd.clone() * (target_dot - actual_dot) + p
80 }
81}
82
83pub fn error<T>(target: T, actual: T) -> T
84where
85 T: Sub<Output = T>,
86{
87 target - actual
88}
89
90#[derive(Clone, Debug)]
91pub struct PID {
92 pub pd: PD<f32>,
93 pub ki: f32,
94 pub integrated_error: f32,
95}
96
97impl PID {
98 pub fn new(damping_ratio: f32, time_constant: f32) -> Self {
99 let ki = 1. / time_constant.powi(3);
100 Self {
101 pd: PD::new(damping_ratio, time_constant),
102 ki,
103 integrated_error: 0.,
104 }
105 }
106
107 pub fn control(
108 &mut self,
109 target: f32,
110 target_dot: f32,
111 actual: f32,
112 actual_dot: f32,
113 dt: f32,
114 ) -> f32 {
115 let error = error(target, actual);
116 self.integrated_error += error * dt;
117
118 let p = self.pd.p.control_with_error(error);
119 let i = self.integrated_error * self.ki;
120 let d = self.pd.control_with_p(p, target_dot, actual_dot);
121
122 p + i + d
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 #[test]
129 fn it_works() {
130 let result = 2 + 2;
131 assert_eq!(result, 4);
132 }
133}