blob: c22b899763d8fb6f63c1e05c0514c9cbcfd1ecbe [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));
Austin Schuh30537882014-02-18 01:07:23 -080045 LOG(DEBUG, "Voltage sums up by %f\n", U(0, 0));
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000046
47 last_voltage_ = voltage_;
48}
49
Austin Schuh30537882014-02-18 01:07:23 -080050void ZeroedStateFeedbackLoop::SetCalibration(double encoder_val,
51 double known_position) {
52 LOG(INFO, "Setting calibration such that %f -> %f\n", encoder_val,
53 known_position);
54 LOG(INFO, "Position was %f\n", absolute_position());
55 double previous_offset = offset_;
56 offset_ = known_position - encoder_val;
57 double doffset = offset_ - previous_offset;
58 LOG(INFO, "Changing offset from %f to %f\n", previous_offset, offset_);
59 X_hat(0, 0) += doffset;
60 // Offset our measurements because the offset is baked into them.
61 Y_(0, 0) += doffset;
62 // Offset the goal so we don't move.
63 R(0, 0) += doffset;
64 LOG(INFO, "Validation: position is %f\n", absolute_position());
65}
66
Ben Fredricksonedf0e092014-02-16 10:46:50 +000067ShooterMotor::ShooterMotor(control_loops::ShooterGroup *my_shooter)
68 : aos::control_loops::ControlLoop<control_loops::ShooterGroup>(my_shooter),
69 shooter_(MakeShooterLoop()),
Ben Fredrickson22c93322014-02-17 05:56:33 +000070 state_(STATE_INITIALIZE),
71 loading_problem_end_time_(0, 0),
Austin Schuh30537882014-02-18 01:07:23 -080072 load_timeout_(0, 0),
Ben Fredrickson22c93322014-02-17 05:56:33 +000073 shooter_brake_set_time_(0, 0),
Austin Schuh30537882014-02-18 01:07:23 -080074 unload_timeout_(0, 0),
Ben Fredrickson22c93322014-02-17 05:56:33 +000075 prepare_fire_end_time_(0, 0),
76 shot_end_time_(0, 0),
Austin Schuh30537882014-02-18 01:07:23 -080077 cycles_not_moved_(0) {}
78
79double ShooterMotor::PowerToPosition(double power) {
80 // LOG(WARNING, "power to position not correctly implemented\n");
81 const frc971::constants::Values &values = constants::GetValues();
82 double new_pos = ::std::min(::std::max(power, values.shooter.lower_limit),
83 values.shooter.upper_limit);
84 return new_pos;
85}
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000086
87// Positive is out, and positive power is out.
joe2d92e852014-01-25 14:31:24 -080088void ShooterMotor::RunIteration(
Ben Fredricksonedf0e092014-02-16 10:46:50 +000089 const control_loops::ShooterGroup::Goal *goal,
90 const control_loops::ShooterGroup::Position *position,
91 control_loops::ShooterGroup::Output *output,
Ben Fredrickson22c93322014-02-17 05:56:33 +000092 control_loops::ShooterGroup::Status *status) {
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000093 constexpr double dt = 0.01;
94
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000095 // we must always have these or we have issues.
96 if (goal == NULL || status == NULL) {
Ben Fredrickson22c93322014-02-17 05:56:33 +000097 if (output) output->voltage = 0;
98 LOG(ERROR, "Thought I would just check for null and die.\n");
99 return;
100 }
101
Austin Schuh30537882014-02-18 01:07:23 -0800102 if (reset()) {
103 state_ = STATE_INITIALIZE;
104 }
105 if (position) {
106 shooter_.CorrectPosition(position->position);
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000107 }
joe2d92e852014-01-25 14:31:24 -0800108
109 // Disable the motors now so that all early returns will return with the
110 // motors disabled.
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000111 if (output) output->voltage = 0;
joe2d92e852014-01-25 14:31:24 -0800112
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000113 const frc971::constants::Values &values = constants::GetValues();
114
Austin Schuh30537882014-02-18 01:07:23 -0800115 double relative_position = shooter_.position();
116 double absolute_position = shooter_.absolute_position();
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000117
Brian Silvermanaae236a2014-02-17 01:49:39 -0800118 // Don't even let the control loops run.
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000119 bool shooter_loop_disable = false;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000120
Brian Silvermanaae236a2014-02-17 01:49:39 -0800121 // Adds voltage to take up slack in gears before shot.
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000122 bool apply_some_voltage = false;
123
Austin Schuh30537882014-02-18 01:07:23 -0800124 // TODO(austin): Observe not seeing the sensors when we should by moving the
125 // calibration offset correclty.
126 const bool disabled = !::aos::robot_state->enabled;
127
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000128 switch (state_) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000129 case STATE_INITIALIZE:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000130 if (position) {
Austin Schuh30537882014-02-18 01:07:23 -0800131 // Reinitialize the internal filter state.
132 shooter_.InitializeState(position->position);
133 // TODO(austin): Test all of these initial states.
134
135 // Start off with the assumption that we are at the value
136 // futhest back given our sensors.
137 if (position->pusher_distal.current) {
138 shooter_.SetCalibration(position->position,
139 values.shooter.pusher_distal.lower_angle);
140 } else if (position->pusher_proximal.current) {
141 shooter_.SetCalibration(position->position,
142 values.shooter.pusher_proximal.lower_angle);
143 } else {
144 shooter_.SetCalibration(position->position,
145 values.shooter.upper_limit);
146 }
147
148 state_ = STATE_REQUEST_LOAD;
149
150 // Go to the current position.
151 shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
152 // If the plunger is all the way back, we want to be latched.
153 latch_piston_ = position->plunger;
154 brake_piston_ = false;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000155 } else {
Austin Schuh30537882014-02-18 01:07:23 -0800156 // If we can't start yet because we don't know where we are, set the
157 // latch and brake to their defaults.
158 latch_piston_ = true;
159 brake_piston_ = true;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000160 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000161 break;
162 case STATE_REQUEST_LOAD:
Austin Schuh30537882014-02-18 01:07:23 -0800163 if (position) {
164 // Need to go forward a little if we are starting with the
165 // back_distal_sensor triggered
166 if (position->plunger && position->latch) {
167 // The plunger is back and we are latched, get ready to shoot.
168 state_ = STATE_PREPARE_SHOT;
169 latch_piston_ = true;
170 } else if (position->pusher_distal.current) {
171 // We started on the sensor, back up until we are found.
172 // If the plunger is all the way back and not latched, it won't be
173 // there for long.
174 state_ = STATE_LOAD_BACKTRACK;
175 latch_piston_ = false;
176 } else {
177 // Off the sensor, start loading.
178 Load();
179 latch_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000180 }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000181 }
182
Austin Schuh30537882014-02-18 01:07:23 -0800183 // Hold our current position.
184 shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
185 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000186 break;
187 case STATE_LOAD_BACKTRACK:
Austin Schuh30537882014-02-18 01:07:23 -0800188 // If we are here, then that means we started past the edge where we want
189 // to zero. Move backwards until we don't see the sensor anymore.
190 // The plunger is contacting the pusher (or will be shortly).
191
192 // TODO(austin): Windup here and below!
193 if (!disabled) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000194 shooter_.SetGoalPosition(
Austin Schuh30537882014-02-18 01:07:23 -0800195 shooter_.goal_position() - values.shooter.zeroing_speed * dt,
196 -values.shooter.zeroing_speed);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000197 }
198
Austin Schuh30537882014-02-18 01:07:23 -0800199 if (position) {
200 if (!position->pusher_distal.current) {
201 Load();
202 }
203 }
204
205 latch_piston_ = false;
206 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000207 break;
208 case STATE_LOAD:
Austin Schuh30537882014-02-18 01:07:23 -0800209 // If we are disabled right now, reset the timer.
210 if (disabled) {
211 Load();
212 // Latch defaults to true when disabled. Leave it latched until we have
213 // useful sensor data.
214 latch_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000215 }
Austin Schuh30537882014-02-18 01:07:23 -0800216 // Go to 0, which should be the latch position, or trigger a hall effect
217 // on the way. If we don't see edges where we are supposed to, the
218 // offset will be updated by code above.
219 shooter_.SetGoalPosition(0.0, 0.0);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000220
Austin Schuh30537882014-02-18 01:07:23 -0800221 if (position) {
222 // If we see a posedge on any of the hall effects,
223 if (position->pusher_proximal.posedge_count !=
224 last_proximal_posedge_count_) {
225 LOG(DEBUG, "Setting calibration using proximal sensor\n");
226 shooter_.SetCalibration(position->pusher_proximal.posedge_value,
227 values.shooter.pusher_proximal.upper_angle);
228 }
229 if (position->pusher_distal.posedge_count !=
230 last_distal_posedge_count_) {
231 LOG(DEBUG, "Setting calibration using distal sensor\n");
232 shooter_.SetCalibration(position->pusher_distal.posedge_value,
233 values.shooter.pusher_distal.upper_angle);
234 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000235
Austin Schuh30537882014-02-18 01:07:23 -0800236 // Latch if the plunger is far enough back to trigger the hall effect.
237 // This happens when the distal sensor is triggered.
238 latch_piston_ = position->pusher_distal.current;
239
240 // Check if we are latched and back.
241 if (position->plunger && position->latch) {
242 state_ = STATE_PREPARE_SHOT;
243 } else if (position->plunger &&
244 ::std::abs(shooter_.absolute_position() -
245 shooter_.goal_position()) < 0.001) {
246 // We are at the goal, but not latched.
247 state_ = STATE_LOADING_PROBLEM;
248 loading_problem_end_time_ = Time::Now() + Time::InSeconds(0.5);
249 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000250 }
Austin Schuh30537882014-02-18 01:07:23 -0800251 if (load_timeout_ < Time::Now()) {
252 if (position) {
253 if (!position->pusher_distal.current ||
254 !position->pusher_proximal.current) {
255 state_ = STATE_ESTOP;
256 }
257 }
258 } else if (goal->unload_requested) {
259 Unload();
260 }
261 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000262 break;
263 case STATE_LOADING_PROBLEM:
Austin Schuh30537882014-02-18 01:07:23 -0800264 if (disabled) {
265 Load();
266 }
267 // We got to the goal, but the latch hasn't registered as down. It might
268 // be stuck, or on it's way but not there yet.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000269 if (Time::Now() > loading_problem_end_time_) {
Austin Schuh30537882014-02-18 01:07:23 -0800270 // Timeout by unloading.
271 Unload();
272 } else if (position && position->plunger && position->latch) {
273 // If both trigger, we are latched.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000274 state_ = STATE_PREPARE_SHOT;
275 }
Austin Schuh30537882014-02-18 01:07:23 -0800276 // Move a bit further back to help it trigger.
277 // If the latch is slow due to the air flowing through the tubes or
278 // inertia, but is otherwise free, this won't have much time to do
279 // anything and is safe. Otherwise this gives us a bit more room to free
280 // up the latch.
281 shooter_.SetGoalPosition(values.shooter.lower_limit, 0.0);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000282 LOG(DEBUG, "Waiting on latch: plunger %d, latch: %d\n",
Austin Schuh60c56662014-02-17 14:37:19 -0800283 position->plunger, position->latch);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000284
Austin Schuh30537882014-02-18 01:07:23 -0800285 latch_piston_ = true;
286 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000287 break;
288 case STATE_PREPARE_SHOT:
Austin Schuh30537882014-02-18 01:07:23 -0800289 // Move the shooter to the shot power set point and then lock the brake.
290 // TODO(austin): Timeout. Low priority.
291
Ben Fredrickson22c93322014-02-17 05:56:33 +0000292 shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
Austin Schuh30537882014-02-18 01:07:23 -0800293
294 LOG(DEBUG, "PDIFF: absolute_position: %.2f, pow: %.2f\n",
295 absolute_position, PowerToPosition(goal->shot_power));
296 // TODO(austin): Goal velocity too...
297 if (::std::abs(shooter_.absolute_position() -
298 PowerToPosition(goal->shot_power)) < 0.001) {
299 // We are there, set the brake and move on.
300 latch_piston_ = true;
301 brake_piston_ = true;
302 shooter_brake_set_time_ = Time::Now() + Time::InSeconds(0.05);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000303 state_ = STATE_READY;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000304 } else {
Austin Schuh30537882014-02-18 01:07:23 -0800305 latch_piston_ = true;
306 brake_piston_ = false;
307 }
308 if (goal->unload_requested) {
309 Unload();
Ben Fredrickson22c93322014-02-17 05:56:33 +0000310 }
311 break;
312 case STATE_READY:
Austin Schuh30537882014-02-18 01:07:23 -0800313 LOG(DEBUG, "In ready\n");
314 // Wait until the brake is set, and a shot is requested or the shot power is changed.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000315 if (Time::Now() > shooter_brake_set_time_) {
Austin Schuh30537882014-02-18 01:07:23 -0800316 // We have waited long enough for the brake to set, turn the shooter control loop off.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000317 shooter_loop_disable = true;
Austin Schuh30537882014-02-18 01:07:23 -0800318 LOG(DEBUG, "Brake is now set\n");
319 if (goal->shot_requested && !disabled) {
320 LOG(DEBUG, "Shooting now\n");
321 shooter_loop_disable = true;
322 prepare_fire_end_time_ =
323 Time::Now(Time::kDefaultClock) + Time::InMS(40.0);
324 apply_some_voltage = true;
325 state_ = STATE_PREPARE_FIRE;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000326 }
Austin Schuh30537882014-02-18 01:07:23 -0800327 } else if (::std::abs(shooter_.absolute_position() -
328 PowerToPosition(goal->shot_power)) > 0.001) {
329 // TODO(austin): If the goal has changed, go back to prepare shot, not if we are off.
330 // TODO(austin): Add a state to release the brake.
331
332 // TODO(austin): Do we want to set the brake here or after shooting?
333 LOG(DEBUG, "Preparing shot again.\n");
334 state_ = STATE_PREPARE_SHOT;
335 } else {
336 LOG(DEBUG, "Nothing %d %d\n", goal->shot_requested, !disabled);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000337 }
Ben Fredricksona6d77542014-02-17 07:54:43 +0000338 shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
339
Austin Schuh30537882014-02-18 01:07:23 -0800340 latch_piston_ = true;
341 brake_piston_ = true;
342
343 if (goal->unload_requested) {
344 Unload();
345 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000346 break;
Austin Schuh30537882014-02-18 01:07:23 -0800347
348 case STATE_PREPARE_FIRE:
349 // Apply a bit of voltage to bias the gears for a little bit of time, and
350 // then fire.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000351 shooter_loop_disable = true;
Austin Schuh30537882014-02-18 01:07:23 -0800352 if (disabled) {
353 // If we are disabled, reset the backlash bias timer.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000354 prepare_fire_end_time_ =
355 Time::Now(Time::kDefaultClock) + Time::InMS(40.0);
Austin Schuh30537882014-02-18 01:07:23 -0800356 break;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000357 }
Austin Schuh30537882014-02-18 01:07:23 -0800358 if (Time::Now() > prepare_fire_end_time_) {
359 cycles_not_moved_ = 0;
360 firing_starting_position_ = shooter_.absolute_position();
361 shot_end_time_ = Time::Now() + Time::InSeconds(1);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000362 state_ = STATE_FIRE;
Austin Schuh30537882014-02-18 01:07:23 -0800363 } else {
364 apply_some_voltage = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000365 }
366
Austin Schuh30537882014-02-18 01:07:23 -0800367 latch_piston_ = true;
368 brake_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000369 break;
Austin Schuh30537882014-02-18 01:07:23 -0800370
Ben Fredrickson22c93322014-02-17 05:56:33 +0000371 case STATE_FIRE:
Austin Schuh30537882014-02-18 01:07:23 -0800372 if (disabled) {
373 if (position) {
374 if (position->plunger) {
375 // If disabled and the plunger is still back there, reset the
376 // timeout.
377 shot_end_time_ = Time::Now() + Time::InSeconds(1);
378 }
379 }
380 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000381 shooter_loop_disable = true;
Austin Schuh30537882014-02-18 01:07:23 -0800382 // Count the number of contiguous cycles during which we haven't moved.
383 if (::std::abs(last_position_.position - shooter_.absolute_position()) <
384 0.0005) {
385 ++cycles_not_moved_;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000386 } else {
387 cycles_not_moved_ = 0;
388 }
Austin Schuh30537882014-02-18 01:07:23 -0800389
390 // If we have moved any amount since the start and the shooter has now
391 // been still for a couple cycles, the shot finished.
392 // Also move on if it times out.
393 if ((::std::abs(firing_starting_position_ -
394 shooter_.absolute_position()) > 0.0005 &&
395 cycles_not_moved_ > 3) ||
396 Time::Now() > shot_end_time_) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000397 state_ = STATE_REQUEST_LOAD;
398 }
Austin Schuh30537882014-02-18 01:07:23 -0800399 latch_piston_ = false;
400 brake_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000401 break;
402 case STATE_UNLOAD:
Austin Schuh30537882014-02-18 01:07:23 -0800403 // Reset the timeouts.
404 if (disabled) Unload();
405
406 // If it is latched and the plunger is back, move the pusher back to catch
407 // the plunger.
Austin Schuh60c56662014-02-17 14:37:19 -0800408 if (position->plunger && position->latch) {
Austin Schuh30537882014-02-18 01:07:23 -0800409 // Pull back to 0, 0.
410 shooter_.SetGoalPosition(0.0, 0.0);
411 if (shooter_.absolute_position() < 0.005) {
412 // When we are close enough, 'fire'.
413 latch_piston_ = false;
414 } else {
415 latch_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000416 }
417 } else {
Austin Schuh30537882014-02-18 01:07:23 -0800418 // The plunger isn't all the way back, or it is and it is unlatched, so
419 // we can now unload.
420 shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
421 latch_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000422 state_ = STATE_UNLOAD_MOVE;
Austin Schuh30537882014-02-18 01:07:23 -0800423 unload_timeout_ = Time::Now() + Time::InSeconds(2.0);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000424 }
425
Austin Schuh30537882014-02-18 01:07:23 -0800426 if (Time::Now() > unload_timeout_) {
427 // We have been stuck trying to unload for way too long, give up and
428 // turn everything off.
429 state_ = STATE_ESTOP;
430 }
431
432 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000433 break;
Austin Schuh30537882014-02-18 01:07:23 -0800434 case STATE_UNLOAD_MOVE: {
435 if (disabled) {
436 unload_timeout_ = Time::Now() + Time::InSeconds(2.0);
437 shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
438 }
439 // TODO(austin): Windup...
440
441 // Slowly move back until we hit the upper limit.
442 double goal_position =
443 shooter_.goal_position() + values.shooter.zeroing_speed * dt;
444 // If during this cycle, we would move past the limit, we are done
445 // unloading.
446 if (goal_position > values.shooter.upper_limit) {
447 shooter_.SetGoalPosition(values.shooter.upper_limit, 0.0);
448 // We don't want the loop fighting the spring when we are unloaded.
449 // Turn it off.
450 shooter_loop_disable = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000451 state_ = STATE_READY_UNLOAD;
452 } else {
Austin Schuh30537882014-02-18 01:07:23 -0800453 shooter_.SetGoalPosition(goal_position, values.shooter.zeroing_speed);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000454 }
455
Austin Schuh30537882014-02-18 01:07:23 -0800456 latch_piston_ = false;
457 brake_piston_ = false;
458 } break;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000459 case STATE_READY_UNLOAD:
Austin Schuh30537882014-02-18 01:07:23 -0800460 if (goal->load_requested) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000461 state_ = STATE_REQUEST_LOAD;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000462 }
Austin Schuh30537882014-02-18 01:07:23 -0800463 // If we are ready to load again,
464 shooter_loop_disable = true;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000465
Austin Schuh30537882014-02-18 01:07:23 -0800466 latch_piston_ = false;
467 brake_piston_ = false;
468 break;
469
470 case STATE_ESTOP:
471 // Totally lost, go to a safe state.
472 shooter_loop_disable = true;
473 latch_piston_ = true;
474 brake_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000475 break;
joe2d92e852014-01-25 14:31:24 -0800476 }
477
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000478 if (apply_some_voltage) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000479 shooter_.Update(true);
480 if (output) output->voltage = 2.0;
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000481 } else if (!shooter_loop_disable) {
Austin Schuh30537882014-02-18 01:07:23 -0800482 LOG(DEBUG, "Running the loop, goal is %f, position is %f\n",
483 shooter_.goal_position(), shooter_.absolute_position());
Ben Fredrickson22c93322014-02-17 05:56:33 +0000484 shooter_.Update(output == NULL);
485 if (output) output->voltage = shooter_.voltage();
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000486 } else {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000487 shooter_.Update(true);
488 if (output) output->voltage = 0.0;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000489 }
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000490
Austin Schuh30537882014-02-18 01:07:23 -0800491 if (output) {
492 output->latch_piston = latch_piston_;
493 output->brake_piston = brake_piston_;
494 }
495
Ben Fredrickson22c93322014-02-17 05:56:33 +0000496 status->done =
Austin Schuh30537882014-02-18 01:07:23 -0800497 ::std::abs(absolute_position - PowerToPosition(goal->shot_power)) < 0.004;
498
499 if (position) {
500 last_position_ = *position;
501 LOG(DEBUG,
502 "pos > real: %.2f adjusted: %.2f raw: %.2f state= %d\n",
503 relative_position, absolute_position, position->position,
504 state_);
505 }
506 if (position) {
507 last_distal_posedge_count_ = position->pusher_distal.posedge_count;
508 last_proximal_posedge_count_ = position->pusher_proximal.posedge_count;
509 }
joe2d92e852014-01-25 14:31:24 -0800510}
511
512} // namespace control_loops
513} // namespace frc971