blob: 831ef1953b948e856287fd7ee449a660b5805ea6 [file] [log] [blame]
joe93778a62014-02-15 13:22:14 -08001#include "frc971/control_loops/shooter/shooter.h"
joe2d92e852014-01-25 14:31:24 -08002
3#include <stdio.h>
4
5#include <algorithm>
6
7#include "aos/common/control_loop/control_loops.q.h"
Ben Fredricksonedf0e092014-02-16 10:46:50 +00008#include "aos/common/control_loop/control_loops.q.h"
joe2d92e852014-01-25 14:31:24 -08009#include "aos/common/logging/logging.h"
10
11#include "frc971/constants.h"
joe93778a62014-02-15 13:22:14 -080012#include "frc971/control_loops/shooter/shooter_motor_plant.h"
joe2d92e852014-01-25 14:31:24 -080013
14namespace frc971 {
15namespace control_loops {
16
Ben Fredricksonedf0e092014-02-16 10:46:50 +000017using ::aos::time::Time;
Ben Fredrickson22c93322014-02-17 05:56:33 +000018
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000019void ZeroedStateFeedbackLoop::CapU() {
20 const double old_voltage = voltage_;
21 voltage_ += U(0, 0);
22
23 uncapped_voltage_ = voltage_;
24
Ben Fredrickson22c93322014-02-17 05:56:33 +000025 // TODO(ben): Limit the voltage if we are ever not certain that things are
26 // working.
27 double limit = 12.0;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000028
29 // Make sure that reality and the observer can't get too far off. There is a
30 // delay by one cycle between the applied voltage and X_hat(2, 0), so compare
31 // against last cycle's voltage.
32 if (X_hat(2, 0) > last_voltage_ + 2.0) {
33 voltage_ -= X_hat(2, 0) - (last_voltage_ + 2.0);
Ben Fredrickson22c93322014-02-17 05:56:33 +000034 //LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
35 } else if (X_hat(2, 0) < last_voltage_ - 2.0) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000036 voltage_ += X_hat(2, 0) - (last_voltage_ - 2.0);
Ben Fredrickson22c93322014-02-17 05:56:33 +000037 //LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000038 }
39
40 voltage_ = std::min(limit, voltage_);
41 voltage_ = std::max(-limit, voltage_);
42 U(0, 0) = voltage_ - old_voltage;
Ben Fredrickson22c93322014-02-17 05:56:33 +000043 //LOG(DEBUG, "abc %f\n", X_hat(2, 0) - voltage_);
44 //LOG(DEBUG, "error %f\n", X_hat(0, 0) - R(0, 0));
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000045
46 last_voltage_ = voltage_;
47}
48
Ben Fredricksonedf0e092014-02-16 10:46:50 +000049ShooterMotor::ShooterMotor(control_loops::ShooterGroup *my_shooter)
50 : aos::control_loops::ControlLoop<control_loops::ShooterGroup>(my_shooter),
51 shooter_(MakeShooterLoop()),
Ben Fredrickson22c93322014-02-17 05:56:33 +000052 calibration_position_(0.0),
53 state_(STATE_INITIALIZE),
54 loading_problem_end_time_(0, 0),
55 shooter_brake_set_time_(0, 0),
56 prepare_fire_end_time_(0, 0),
57 shot_end_time_(0, 0),
58 cycles_not_moved_(0),
59 initial_loop_(true) {}
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000060
61// Positive is out, and positive power is out.
joe2d92e852014-01-25 14:31:24 -080062void ShooterMotor::RunIteration(
Ben Fredricksonedf0e092014-02-16 10:46:50 +000063 const control_loops::ShooterGroup::Goal *goal,
64 const control_loops::ShooterGroup::Position *position,
65 control_loops::ShooterGroup::Output *output,
Ben Fredrickson22c93322014-02-17 05:56:33 +000066 control_loops::ShooterGroup::Status *status) {
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000067 constexpr double dt = 0.01;
68
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000069 // we must always have these or we have issues.
70 if (goal == NULL || status == NULL) {
Ben Fredrickson22c93322014-02-17 05:56:33 +000071 if (output) output->voltage = 0;
72 LOG(ERROR, "Thought I would just check for null and die.\n");
73 return;
74 }
75
76 if (initial_loop_) {
77 initial_loop_ = false;
78 shooter_.SetPositionDirectly(position->position);
79 } else {
80 shooter_.SetPositionValues(position->position);
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000081 }
joe2d92e852014-01-25 14:31:24 -080082
83 // Disable the motors now so that all early returns will return with the
84 // motors disabled.
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000085 if (output) output->voltage = 0;
joe2d92e852014-01-25 14:31:24 -080086
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000087 const frc971::constants::Values &values = constants::GetValues();
88
Ben Fredrickson22c93322014-02-17 05:56:33 +000089 double real_position = shooter_.position();
90 double adjusted_position = shooter_.position() - calibration_position_;
91
92 if (position) {
93 last_position_ = *position;
94 LOG(DEBUG,
95 "pos > real: %.2f adjusted: %.2f raw: %.2f calib: %.2f state= %d\n",
96 real_position, adjusted_position, position->position,
97 calibration_position_, state_);
98 }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000099
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000100 // don't even let the control loops run
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000101 bool shooter_loop_disable = false;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000102
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000103 // adds voltage to take up slack in gears before shot
104 bool apply_some_voltage = false;
105
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000106 switch (state_) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000107 case STATE_INITIALIZE:
108 // start off with the assumption that we are at the value
109 // futhest back given our sensors
110 if (position && position->pusher_distal_hall_effect) {
111 //TODO_ben: use posedge
112 calibration_position_ =
113 position->position - values.shooter.pusher_distal.lower_limit;
114 } else if (position && position->pusher_proximal_hall_effect) {
115 //TODO_ben: use posedge
116 calibration_position_ =
117 position->position - values.shooter.pusher_proximal.lower_limit;
118 }
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000119
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000120 state_ = STATE_REQUEST_LOAD;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000121
Ben Fredrickson22c93322014-02-17 05:56:33 +0000122 // zero out initial goal
123 shooter_.SetGoalPosition(real_position, 0.0);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000124 if (position) {
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000125 output->latch_piston = position->plunger_back_hall_effect;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000126 } else {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000127 // we don't know what is going on so just close the latch to be safe
128 output->latch_piston = true;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000129 }
130 output->brake_piston = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000131 break;
132 case STATE_REQUEST_LOAD:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000133 if (position->plunger_back_hall_effect && position->latch_hall_effect) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000134 // already latched
135 state_ = STATE_PREPARE_SHOT;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000136 } else if (position->pusher_distal_hall_effect ||
Ben Fredrickson22c93322014-02-17 05:56:33 +0000137 (adjusted_position) < 0) {
138 state_ = STATE_LOAD_BACKTRACK;
139 //TODO_ben: double check that rezero is the right thing to do here
140 if (position) {
141 calibration_position_ = position->position;
142 }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000143 } else {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000144 state_ = STATE_LOAD;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000145 }
146
Ben Fredrickson22c93322014-02-17 05:56:33 +0000147 shooter_.SetGoalPosition(0.0, 0.0);
148 if (position && output)
149 output->latch_piston = position->plunger_back_hall_effect;
150 if (output) output->brake_piston = false;
151 break;
152 case STATE_LOAD_BACKTRACK:
153 if (adjusted_position > values.shooter.pusher_distal.upper_limit + 0.01) {
154 shooter_.SetGoalPosition(
155 real_position - values.shooter_zeroing_speed * dt,
156 values.shooter_zeroing_speed);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000157 } else {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000158 state_ = STATE_LOAD;
159 }
160
161 if (output) output->latch_piston = false;
162 if (output) output->brake_piston = true;
163 break;
164 case STATE_LOAD:
165 if (position && position->pusher_proximal_hall_effect &&
166 !last_position_.pusher_proximal_hall_effect) {
167 //TODO_ben: use posedge
168 calibration_position_ =
169 position->position - values.shooter.pusher_proximal.upper_limit;
170 }
171 if (position && position->pusher_distal_hall_effect &&
172 !last_position_.pusher_distal_hall_effect) {
173 //TODO_ben: use posedge
174 calibration_position_ =
175 position->position - values.shooter.pusher_distal.lower_limit;
176 }
177
178 shooter_.SetGoalPosition(calibration_position_, 0.0);
179 if (position && output) {
180 output->latch_piston = position->plunger_back_hall_effect;
181 }
182
183 if (position->plunger_back_hall_effect && position->latch_hall_effect) {
184 state_ = STATE_PREPARE_SHOT;
185 } else if (position->plunger_back_hall_effect &&
Ben Fredricksona6d77542014-02-17 07:54:43 +0000186 fabs(adjusted_position - PowerToPosition(goal->shot_power)) <
Ben Fredrickson22c93322014-02-17 05:56:33 +0000187 0.05) {
188 state_ = STATE_LOADING_PROBLEM;
189 loading_problem_end_time_ =
190 Time::Now(Time::kDefaultClock) + Time::InSeconds(3.0);
191 }
192 if (output) output->brake_piston = false;
193 break;
194 case STATE_LOADING_PROBLEM:
195 if (Time::Now() > loading_problem_end_time_) {
196 state_ = STATE_UNLOAD;
197 } else if (position->plunger_back_hall_effect &&
198 position->latch_hall_effect) {
199 state_ = STATE_PREPARE_SHOT;
200 }
201 shooter_.SetGoalPosition(calibration_position_, 0.0);
202 LOG(DEBUG, "Waiting on latch: plunger %d, latch: %d\n",
203 position->plunger_back_hall_effect, position->latch_hall_effect);
204
205 if (output) output->latch_piston = true;
206 if (output) output->brake_piston = false;
207 break;
208 case STATE_PREPARE_SHOT:
209 shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
Ben Fredricksona6d77542014-02-17 07:54:43 +0000210 LOG(DEBUG, "PDIFF: adjusted_position: %.2f, pow: %.2f\n",
211 adjusted_position, PowerToPosition(goal->shot_power));
212 if (fabs(adjusted_position - PowerToPosition(goal->shot_power)) < 0.05) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000213 state_ = STATE_READY;
214 output->latch_piston = true;
215 output->brake_piston = true;
216 shooter_brake_set_time_ =
Ben Fredricksona6d77542014-02-17 07:54:43 +0000217 Time::Now(Time::kDefaultClock) + Time::InSeconds(0.03);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000218 } else {
219 output->latch_piston = true;
220 output->brake_piston = false;
221 }
222 break;
223 case STATE_READY:
224 if (Time::Now() > shooter_brake_set_time_) {
225 shooter_loop_disable = true;
226 if (goal->unload_requested) {
Ben Fredricksona6d77542014-02-17 07:54:43 +0000227 printf("GHA\n");
Ben Fredrickson22c93322014-02-17 05:56:33 +0000228 state_ = STATE_UNLOAD;
Ben Fredricksona6d77542014-02-17 07:54:43 +0000229 } else if (fabs(adjusted_position - PowerToPosition(goal->shot_power)) >
Ben Fredrickson22c93322014-02-17 05:56:33 +0000230 0.05) {
Ben Fredricksona6d77542014-02-17 07:54:43 +0000231 printf("GHB\n");
Ben Fredrickson22c93322014-02-17 05:56:33 +0000232 state_ = STATE_PREPARE_SHOT;
233 } else if (goal->shot_requested) {
Ben Fredricksona6d77542014-02-17 07:54:43 +0000234 printf("GHC\n");
Ben Fredrickson22c93322014-02-17 05:56:33 +0000235 state_ = STATE_REQUEST_FIRE;
236 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000237 }
Ben Fredricksona6d77542014-02-17 07:54:43 +0000238 shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
239
Ben Fredrickson22c93322014-02-17 05:56:33 +0000240 output->latch_piston = true;
241 output->brake_piston = true;
242 break;
243 case STATE_REQUEST_FIRE:
244 shooter_loop_disable = true;
245 if (position->plunger_back_hall_effect) {
246 prepare_fire_end_time_ =
247 Time::Now(Time::kDefaultClock) + Time::InMS(40.0);
248 apply_some_voltage = true;
249 state_ = STATE_PREPARE_FIRE;
250 } else {
251 state_ = STATE_REQUEST_LOAD;
252 }
253 break;
254 case STATE_PREPARE_FIRE:
255 shooter_loop_disable = true;
256 if (Time::Now(Time::kDefaultClock) < prepare_fire_end_time_) {
257 apply_some_voltage = true;
258 } else {
259 state_ = STATE_FIRE;
260 cycles_not_moved_ = 0;
261 shot_end_time_ = Time::Now(Time::kDefaultClock) + Time::InMS(500);
262 }
263
264 output->latch_piston = true;
265 output->brake_piston = true;
266
267 break;
268 case STATE_FIRE:
269 shooter_loop_disable = true;
270 //TODO_ben: need approamately equal
Ben Fredricksona6d77542014-02-17 07:54:43 +0000271 if (fabs(last_position_.position - adjusted_position) < 0.07) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000272 cycles_not_moved_++;
273 } else {
274 cycles_not_moved_ = 0;
275 }
276 if ((adjusted_position < 0.10 && cycles_not_moved_ > 5) ||
277 Time::Now(Time::kDefaultClock) > shot_end_time_) {
278 state_ = STATE_REQUEST_LOAD;
279 }
280 output->latch_piston = true;
281 output->brake_piston = true;
282 break;
283 case STATE_UNLOAD:
284 if (position->plunger_back_hall_effect && position->latch_hall_effect) {
285 shooter_.SetGoalPosition(0.02, 0.0);
286 if (adjusted_position < 0.04) {
287 output->latch_piston = false;
288 }
289 } else {
290 output->latch_piston = false;
291 state_ = STATE_UNLOAD_MOVE;
292 }
293
294 output->brake_piston = false;
295 break;
296 case STATE_UNLOAD_MOVE:
297 if (adjusted_position > values.shooter_total_length - 0.03) {
298 shooter_.SetGoalPosition(real_position, 0.0);
299 state_ = STATE_READY_UNLOAD;
300 } else {
301 shooter_.SetGoalPosition(
302 real_position + values.shooter_zeroing_speed * dt,
303 values.shooter_zeroing_speed);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000304 }
305
306 output->latch_piston = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000307 output->brake_piston = false;
308 break;
309 case STATE_READY_UNLOAD:
310 if (!goal->unload_requested) {
311 state_ = STATE_REQUEST_LOAD;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000312 }
313
Ben Fredrickson22c93322014-02-17 05:56:33 +0000314 output->latch_piston = false;
315 output->brake_piston = false;
316 break;
joe2d92e852014-01-25 14:31:24 -0800317 }
318
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000319 if (apply_some_voltage) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000320 shooter_.Update(true);
321 if (output) output->voltage = 2.0;
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000322 } else if (!shooter_loop_disable) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000323 LOG(DEBUG, "Running the loop, goal is %f\n", shooter_.R(0, 0));
324 shooter_.Update(output == NULL);
325 if (output) output->voltage = shooter_.voltage();
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000326 } else {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000327 shooter_.Update(true);
328 if (output) output->voltage = 0.0;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000329 }
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000330
Ben Fredrickson22c93322014-02-17 05:56:33 +0000331 status->done =
Ben Fredricksona6d77542014-02-17 07:54:43 +0000332 ::std::fabs(adjusted_position - PowerToPosition(goal->shot_power)) < 0.004;
joe2d92e852014-01-25 14:31:24 -0800333}
334
335} // namespace control_loops
336} // namespace frc971