1use crate::control::Pid;
21use crate::motors::LiftMotor;
22
23#[derive(Copy, Clone, Debug)]
25pub enum LiftMode {
26 PositionControl,
28
29 Disabled,
31}
32
33pub struct LiftController<
35 const CS_P: char,
36 const CS_N: u8,
37 const IN1_P: char,
38 const IN1_N: u8,
39 const IN2_P: char,
40 const IN2_N: u8,
41 const SLP_P: char,
42 const SLP_N: u8,
43 const DIS_P: char,
44 const DIS_N: u8,
45> {
46 motor: LiftMotor<CS_P, CS_N, IN1_P, IN1_N, IN2_P, IN2_N, SLP_P, SLP_N, DIS_P, DIS_N>,
47 pid: Pid,
48 mode: LiftMode,
49
50 target_height_mm: f32,
52
53 min_height_mm: f32,
55 max_height_mm: f32,
56
57 on_target_tolerance_mm: f32,
59}
60
61impl<
62 const CS_P: char,
63 const CS_N: u8,
64 const IN1_P: char,
65 const IN1_N: u8,
66 const IN2_P: char,
67 const IN2_N: u8,
68 const SLP_P: char,
69 const SLP_N: u8,
70 const DIS_P: char,
71 const DIS_N: u8,
72 > LiftController<CS_P, CS_N, IN1_P, IN1_N, IN2_P, IN2_N, SLP_P, SLP_N, DIS_P, DIS_N>
73{
74 pub fn new(
76 motor: LiftMotor<CS_P, CS_N, IN1_P, IN1_N, IN2_P, IN2_N, SLP_P, SLP_N, DIS_P, DIS_N>,
77 pid: Pid,
78 min_height_mm: f32,
79 max_height_mm: f32,
80 on_target_tolerance_mm: f32,
81 ) -> Self {
82 Self {
83 motor,
84 pid,
85 mode: LiftMode::PositionControl,
86 target_height_mm: 0.0,
87 min_height_mm,
88 max_height_mm,
89 on_target_tolerance_mm,
90 }
91 }
92
93 pub fn set_target_height_mm(&mut self, mm: f32) {
95 let clamped = mm.clamp(self.min_height_mm, self.max_height_mm);
96 self.target_height_mm = clamped;
97 self.pid.reset();
98 }
99
100 pub fn disable(&mut self) {
102 self.mode = LiftMode::Disabled;
103 self.motor.inner_motor().coast();
104 }
105
106 pub fn enable(&mut self) {
108 self.mode = LiftMode::PositionControl;
109 }
110
111 #[inline]
113 pub fn height_mm(&self) -> f32 {
114 self.motor.height_mm()
115 }
116
117 pub fn on_target(&self) -> bool {
119 let err = (self.height_mm() - self.target_height_mm).abs();
120 err <= self.on_target_tolerance_mm
121 }
122
123 pub fn step(&mut self, dt: f32) {
127 match self.mode {
128 LiftMode::Disabled => {
129 self.motor.inner_motor().coast();
130 return;
131 }
132
133 LiftMode::PositionControl => {
134 let current = self.motor.height_mm();
135 let target = self
136 .target_height_mm
137 .clamp(self.min_height_mm, self.max_height_mm);
138 let error = target - current;
139
140 let mut u = self.pid.update(target, current, dt);
142
143 if u > 1.0 {
145 u = 1.0;
146 }
147 if u < -1.0 {
148 u = -1.0;
149 }
150
151 if error.abs() <= self.on_target_tolerance_mm {
153 self.motor.inner_motor().brake();
154 return;
155 }
156
157 self.motor.apply_pid_output(u);
159 }
160 }
161 }
162
163 pub fn motor(
165 &self,
166 ) -> &LiftMotor<CS_P, CS_N, IN1_P, IN1_N, IN2_P, IN2_N, SLP_P, SLP_N, DIS_P, DIS_N> {
167 &self.motor
168 }
169
170 pub fn motor_mut(
172 &mut self,
173 ) -> &mut LiftMotor<CS_P, CS_N, IN1_P, IN1_N, IN2_P, IN2_N, SLP_P, SLP_N, DIS_P, DIS_N> {
174 &mut self.motor
175 }
176}