blob: fb9df7467d5e58ac7669b48474c5a23f2834f80e [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.
Austin Schuhbe1401f2014-02-18 03:18:41 -080032 if (X_hat(2, 0) > last_voltage_ + 4.0) {
33 voltage_ -= X_hat(2, 0) - (last_voltage_ + 4.0);
34 LOG(INFO, "Capping due to runawway\n");
35 } else if (X_hat(2, 0) < last_voltage_ - 4.0) {
36 voltage_ += X_hat(2, 0) - (last_voltage_ - 4.0);
37 LOG(INFO, "Capping due to runawway\n");
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 Fredrickson1f633ef2014-02-16 05:35:45 +000043
Austin Schuhbe1401f2014-02-18 03:18:41 -080044 LOG(INFO, "X_hat is %f, applied is %f\n", X_hat(2, 0), voltage_);
45
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000046 last_voltage_ = voltage_;
47}
48
Austin Schuh30537882014-02-18 01:07:23 -080049void ZeroedStateFeedbackLoop::SetCalibration(double encoder_val,
50 double known_position) {
51 LOG(INFO, "Setting calibration such that %f -> %f\n", encoder_val,
52 known_position);
53 LOG(INFO, "Position was %f\n", absolute_position());
54 double previous_offset = offset_;
55 offset_ = known_position - encoder_val;
56 double doffset = offset_ - previous_offset;
57 LOG(INFO, "Changing offset from %f to %f\n", previous_offset, offset_);
58 X_hat(0, 0) += doffset;
59 // Offset our measurements because the offset is baked into them.
60 Y_(0, 0) += doffset;
61 // Offset the goal so we don't move.
62 R(0, 0) += doffset;
63 LOG(INFO, "Validation: position is %f\n", absolute_position());
64}
65
Ben Fredricksonedf0e092014-02-16 10:46:50 +000066ShooterMotor::ShooterMotor(control_loops::ShooterGroup *my_shooter)
67 : aos::control_loops::ControlLoop<control_loops::ShooterGroup>(my_shooter),
68 shooter_(MakeShooterLoop()),
Ben Fredrickson22c93322014-02-17 05:56:33 +000069 state_(STATE_INITIALIZE),
70 loading_problem_end_time_(0, 0),
Austin Schuh30537882014-02-18 01:07:23 -080071 load_timeout_(0, 0),
Ben Fredrickson22c93322014-02-17 05:56:33 +000072 shooter_brake_set_time_(0, 0),
Austin Schuh30537882014-02-18 01:07:23 -080073 unload_timeout_(0, 0),
Ben Fredrickson22c93322014-02-17 05:56:33 +000074 prepare_fire_end_time_(0, 0),
75 shot_end_time_(0, 0),
Austin Schuh30537882014-02-18 01:07:23 -080076 cycles_not_moved_(0) {}
77
78double ShooterMotor::PowerToPosition(double power) {
79 // LOG(WARNING, "power to position not correctly implemented\n");
80 const frc971::constants::Values &values = constants::GetValues();
81 double new_pos = ::std::min(::std::max(power, values.shooter.lower_limit),
82 values.shooter.upper_limit);
83 return new_pos;
84}
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000085
86// Positive is out, and positive power is out.
joe2d92e852014-01-25 14:31:24 -080087void ShooterMotor::RunIteration(
Ben Fredricksonedf0e092014-02-16 10:46:50 +000088 const control_loops::ShooterGroup::Goal *goal,
89 const control_loops::ShooterGroup::Position *position,
90 control_loops::ShooterGroup::Output *output,
Ben Fredrickson22c93322014-02-17 05:56:33 +000091 control_loops::ShooterGroup::Status *status) {
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000092 constexpr double dt = 0.01;
93
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000094 // we must always have these or we have issues.
95 if (goal == NULL || status == NULL) {
Ben Fredrickson22c93322014-02-17 05:56:33 +000096 if (output) output->voltage = 0;
97 LOG(ERROR, "Thought I would just check for null and die.\n");
98 return;
99 }
100
Austin Schuh30537882014-02-18 01:07:23 -0800101 if (reset()) {
102 state_ = STATE_INITIALIZE;
103 }
104 if (position) {
105 shooter_.CorrectPosition(position->position);
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000106 }
joe2d92e852014-01-25 14:31:24 -0800107
108 // Disable the motors now so that all early returns will return with the
109 // motors disabled.
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000110 if (output) output->voltage = 0;
joe2d92e852014-01-25 14:31:24 -0800111
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000112 const frc971::constants::Values &values = constants::GetValues();
113
Brian Silvermanaae236a2014-02-17 01:49:39 -0800114 // Don't even let the control loops run.
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000115 bool shooter_loop_disable = false;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000116
Brian Silvermanaae236a2014-02-17 01:49:39 -0800117 // Adds voltage to take up slack in gears before shot.
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000118 bool apply_some_voltage = false;
119
Austin Schuh30537882014-02-18 01:07:23 -0800120 // TODO(austin): Observe not seeing the sensors when we should by moving the
121 // calibration offset correclty.
122 const bool disabled = !::aos::robot_state->enabled;
123
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000124 switch (state_) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000125 case STATE_INITIALIZE:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000126 if (position) {
Austin Schuh30537882014-02-18 01:07:23 -0800127 // Reinitialize the internal filter state.
128 shooter_.InitializeState(position->position);
129 // TODO(austin): Test all of these initial states.
130
131 // Start off with the assumption that we are at the value
132 // futhest back given our sensors.
133 if (position->pusher_distal.current) {
134 shooter_.SetCalibration(position->position,
135 values.shooter.pusher_distal.lower_angle);
136 } else if (position->pusher_proximal.current) {
137 shooter_.SetCalibration(position->position,
138 values.shooter.pusher_proximal.lower_angle);
139 } else {
140 shooter_.SetCalibration(position->position,
141 values.shooter.upper_limit);
142 }
143
144 state_ = STATE_REQUEST_LOAD;
145
146 // Go to the current position.
147 shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
148 // If the plunger is all the way back, we want to be latched.
149 latch_piston_ = position->plunger;
150 brake_piston_ = false;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000151 } else {
Austin Schuh30537882014-02-18 01:07:23 -0800152 // If we can't start yet because we don't know where we are, set the
153 // latch and brake to their defaults.
154 latch_piston_ = true;
155 brake_piston_ = true;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000156 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000157 break;
158 case STATE_REQUEST_LOAD:
Austin Schuh30537882014-02-18 01:07:23 -0800159 if (position) {
Austin Schuh30537882014-02-18 01:07:23 -0800160 if (position->plunger && position->latch) {
161 // The plunger is back and we are latched, get ready to shoot.
162 state_ = STATE_PREPARE_SHOT;
163 latch_piston_ = true;
164 } else if (position->pusher_distal.current) {
165 // We started on the sensor, back up until we are found.
166 // If the plunger is all the way back and not latched, it won't be
167 // there for long.
168 state_ = STATE_LOAD_BACKTRACK;
169 latch_piston_ = false;
170 } else {
171 // Off the sensor, start loading.
172 Load();
173 latch_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000174 }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000175 }
176
Austin Schuh30537882014-02-18 01:07:23 -0800177 // Hold our current position.
178 shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
179 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000180 break;
181 case STATE_LOAD_BACKTRACK:
Austin Schuh30537882014-02-18 01:07:23 -0800182 // If we are here, then that means we started past the edge where we want
183 // to zero. Move backwards until we don't see the sensor anymore.
184 // The plunger is contacting the pusher (or will be shortly).
185
186 // TODO(austin): Windup here and below!
187 if (!disabled) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000188 shooter_.SetGoalPosition(
Austin Schuhfaeee632014-02-18 01:24:05 -0800189 shooter_.goal_position() + values.shooter.zeroing_speed * dt,
190 values.shooter.zeroing_speed);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000191 }
192
Austin Schuh30537882014-02-18 01:07:23 -0800193 if (position) {
194 if (!position->pusher_distal.current) {
195 Load();
196 }
197 }
198
199 latch_piston_ = false;
200 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000201 break;
202 case STATE_LOAD:
Austin Schuh30537882014-02-18 01:07:23 -0800203 // If we are disabled right now, reset the timer.
204 if (disabled) {
205 Load();
206 // Latch defaults to true when disabled. Leave it latched until we have
207 // useful sensor data.
208 latch_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000209 }
Austin Schuh30537882014-02-18 01:07:23 -0800210 // Go to 0, which should be the latch position, or trigger a hall effect
211 // on the way. If we don't see edges where we are supposed to, the
212 // offset will be updated by code above.
213 shooter_.SetGoalPosition(0.0, 0.0);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000214
Austin Schuh30537882014-02-18 01:07:23 -0800215 if (position) {
216 // If we see a posedge on any of the hall effects,
217 if (position->pusher_proximal.posedge_count !=
218 last_proximal_posedge_count_) {
219 LOG(DEBUG, "Setting calibration using proximal sensor\n");
220 shooter_.SetCalibration(position->pusher_proximal.posedge_value,
221 values.shooter.pusher_proximal.upper_angle);
222 }
223 if (position->pusher_distal.posedge_count !=
224 last_distal_posedge_count_) {
225 LOG(DEBUG, "Setting calibration using distal sensor\n");
226 shooter_.SetCalibration(position->pusher_distal.posedge_value,
227 values.shooter.pusher_distal.upper_angle);
228 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000229
Austin Schuh30537882014-02-18 01:07:23 -0800230 // Latch if the plunger is far enough back to trigger the hall effect.
231 // This happens when the distal sensor is triggered.
232 latch_piston_ = position->pusher_distal.current;
233
234 // Check if we are latched and back.
235 if (position->plunger && position->latch) {
236 state_ = STATE_PREPARE_SHOT;
237 } else if (position->plunger &&
238 ::std::abs(shooter_.absolute_position() -
239 shooter_.goal_position()) < 0.001) {
240 // We are at the goal, but not latched.
241 state_ = STATE_LOADING_PROBLEM;
242 loading_problem_end_time_ = Time::Now() + Time::InSeconds(0.5);
243 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000244 }
Austin Schuh30537882014-02-18 01:07:23 -0800245 if (load_timeout_ < Time::Now()) {
246 if (position) {
247 if (!position->pusher_distal.current ||
248 !position->pusher_proximal.current) {
249 state_ = STATE_ESTOP;
250 }
251 }
252 } else if (goal->unload_requested) {
253 Unload();
254 }
255 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000256 break;
257 case STATE_LOADING_PROBLEM:
Austin Schuh30537882014-02-18 01:07:23 -0800258 if (disabled) {
259 Load();
260 }
261 // We got to the goal, but the latch hasn't registered as down. It might
262 // be stuck, or on it's way but not there yet.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000263 if (Time::Now() > loading_problem_end_time_) {
Austin Schuh30537882014-02-18 01:07:23 -0800264 // Timeout by unloading.
265 Unload();
266 } else if (position && position->plunger && position->latch) {
267 // If both trigger, we are latched.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000268 state_ = STATE_PREPARE_SHOT;
269 }
Austin Schuh30537882014-02-18 01:07:23 -0800270 // Move a bit further back to help it trigger.
271 // If the latch is slow due to the air flowing through the tubes or
272 // inertia, but is otherwise free, this won't have much time to do
273 // anything and is safe. Otherwise this gives us a bit more room to free
274 // up the latch.
275 shooter_.SetGoalPosition(values.shooter.lower_limit, 0.0);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000276 LOG(DEBUG, "Waiting on latch: plunger %d, latch: %d\n",
Austin Schuh60c56662014-02-17 14:37:19 -0800277 position->plunger, position->latch);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000278
Austin Schuh30537882014-02-18 01:07:23 -0800279 latch_piston_ = true;
280 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000281 break;
282 case STATE_PREPARE_SHOT:
Austin Schuh30537882014-02-18 01:07:23 -0800283 // Move the shooter to the shot power set point and then lock the brake.
284 // TODO(austin): Timeout. Low priority.
285
Ben Fredrickson22c93322014-02-17 05:56:33 +0000286 shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
Austin Schuh30537882014-02-18 01:07:23 -0800287
288 LOG(DEBUG, "PDIFF: absolute_position: %.2f, pow: %.2f\n",
Austin Schuhbe1401f2014-02-18 03:18:41 -0800289 shooter_.absolute_position(), PowerToPosition(goal->shot_power));
Austin Schuh30537882014-02-18 01:07:23 -0800290 if (::std::abs(shooter_.absolute_position() -
Austin Schuhbe1401f2014-02-18 03:18:41 -0800291 PowerToPosition(goal->shot_power)) +
292 ::std::abs(shooter_.absolute_velocity()) <
293 0.001) {
Austin Schuh30537882014-02-18 01:07:23 -0800294 // We are there, set the brake and move on.
295 latch_piston_ = true;
296 brake_piston_ = true;
297 shooter_brake_set_time_ = Time::Now() + Time::InSeconds(0.05);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000298 state_ = STATE_READY;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000299 } else {
Austin Schuh30537882014-02-18 01:07:23 -0800300 latch_piston_ = true;
301 brake_piston_ = false;
302 }
303 if (goal->unload_requested) {
304 Unload();
Ben Fredrickson22c93322014-02-17 05:56:33 +0000305 }
306 break;
307 case STATE_READY:
Austin Schuh30537882014-02-18 01:07:23 -0800308 LOG(DEBUG, "In ready\n");
Austin Schuhbe1401f2014-02-18 03:18:41 -0800309 // Wait until the brake is set, and a shot is requested or the shot power
310 // is changed.
311 if (::std::abs(shooter_.absolute_position() -
312 PowerToPosition(goal->shot_power)) > 0.002) {
313 // TODO(austin): Add a state to release the brake.
314
315 // TODO(austin): Do we want to set the brake here or after shooting?
316 // Depends on air usage.
317 LOG(DEBUG, "Preparing shot again.\n");
318 state_ = STATE_PREPARE_SHOT;
319 } else if (Time::Now() > shooter_brake_set_time_) {
320 // We have waited long enough for the brake to set, turn the shooter
321 // control loop off.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000322 shooter_loop_disable = true;
Austin Schuh30537882014-02-18 01:07:23 -0800323 LOG(DEBUG, "Brake is now set\n");
324 if (goal->shot_requested && !disabled) {
325 LOG(DEBUG, "Shooting now\n");
326 shooter_loop_disable = true;
327 prepare_fire_end_time_ =
328 Time::Now(Time::kDefaultClock) + Time::InMS(40.0);
329 apply_some_voltage = true;
330 state_ = STATE_PREPARE_FIRE;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000331 }
Austin Schuh30537882014-02-18 01:07:23 -0800332 } else {
333 LOG(DEBUG, "Nothing %d %d\n", goal->shot_requested, !disabled);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000334 }
Ben Fredricksona6d77542014-02-17 07:54:43 +0000335 shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
336
Austin Schuh30537882014-02-18 01:07:23 -0800337 latch_piston_ = true;
338 brake_piston_ = true;
339
340 if (goal->unload_requested) {
341 Unload();
342 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000343 break;
Austin Schuh30537882014-02-18 01:07:23 -0800344
345 case STATE_PREPARE_FIRE:
346 // Apply a bit of voltage to bias the gears for a little bit of time, and
347 // then fire.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000348 shooter_loop_disable = true;
Austin Schuh30537882014-02-18 01:07:23 -0800349 if (disabled) {
350 // If we are disabled, reset the backlash bias timer.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000351 prepare_fire_end_time_ =
352 Time::Now(Time::kDefaultClock) + Time::InMS(40.0);
Austin Schuh30537882014-02-18 01:07:23 -0800353 break;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000354 }
Austin Schuh30537882014-02-18 01:07:23 -0800355 if (Time::Now() > prepare_fire_end_time_) {
356 cycles_not_moved_ = 0;
357 firing_starting_position_ = shooter_.absolute_position();
358 shot_end_time_ = Time::Now() + Time::InSeconds(1);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000359 state_ = STATE_FIRE;
Austin Schuhf5642a92014-02-18 01:42:32 -0800360 latch_piston_ = false;
Austin Schuh30537882014-02-18 01:07:23 -0800361 } else {
362 apply_some_voltage = true;
Austin Schuhf5642a92014-02-18 01:42:32 -0800363 latch_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000364 }
365
Austin Schuh30537882014-02-18 01:07:23 -0800366 brake_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000367 break;
Austin Schuh30537882014-02-18 01:07:23 -0800368
Ben Fredrickson22c93322014-02-17 05:56:33 +0000369 case STATE_FIRE:
Austin Schuh30537882014-02-18 01:07:23 -0800370 if (disabled) {
371 if (position) {
372 if (position->plunger) {
373 // If disabled and the plunger is still back there, reset the
374 // timeout.
375 shot_end_time_ = Time::Now() + Time::InSeconds(1);
376 }
377 }
378 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000379 shooter_loop_disable = true;
Austin Schuh30537882014-02-18 01:07:23 -0800380 // Count the number of contiguous cycles during which we haven't moved.
381 if (::std::abs(last_position_.position - shooter_.absolute_position()) <
382 0.0005) {
383 ++cycles_not_moved_;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000384 } else {
385 cycles_not_moved_ = 0;
386 }
Austin Schuh30537882014-02-18 01:07:23 -0800387
388 // If we have moved any amount since the start and the shooter has now
389 // been still for a couple cycles, the shot finished.
390 // Also move on if it times out.
391 if ((::std::abs(firing_starting_position_ -
392 shooter_.absolute_position()) > 0.0005 &&
393 cycles_not_moved_ > 3) ||
394 Time::Now() > shot_end_time_) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000395 state_ = STATE_REQUEST_LOAD;
396 }
Austin Schuh30537882014-02-18 01:07:23 -0800397 latch_piston_ = false;
398 brake_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000399 break;
400 case STATE_UNLOAD:
Austin Schuh30537882014-02-18 01:07:23 -0800401 // Reset the timeouts.
402 if (disabled) Unload();
403
404 // If it is latched and the plunger is back, move the pusher back to catch
405 // the plunger.
Austin Schuh60c56662014-02-17 14:37:19 -0800406 if (position->plunger && position->latch) {
Austin Schuh30537882014-02-18 01:07:23 -0800407 // Pull back to 0, 0.
408 shooter_.SetGoalPosition(0.0, 0.0);
409 if (shooter_.absolute_position() < 0.005) {
410 // When we are close enough, 'fire'.
411 latch_piston_ = false;
412 } else {
413 latch_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000414 }
415 } else {
Austin Schuh30537882014-02-18 01:07:23 -0800416 // The plunger isn't all the way back, or it is and it is unlatched, so
417 // we can now unload.
418 shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
419 latch_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000420 state_ = STATE_UNLOAD_MOVE;
Austin Schuh30537882014-02-18 01:07:23 -0800421 unload_timeout_ = Time::Now() + Time::InSeconds(2.0);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000422 }
423
Austin Schuh30537882014-02-18 01:07:23 -0800424 if (Time::Now() > unload_timeout_) {
425 // We have been stuck trying to unload for way too long, give up and
426 // turn everything off.
427 state_ = STATE_ESTOP;
428 }
429
430 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000431 break;
Austin Schuh30537882014-02-18 01:07:23 -0800432 case STATE_UNLOAD_MOVE: {
433 if (disabled) {
434 unload_timeout_ = Time::Now() + Time::InSeconds(2.0);
435 shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
436 }
437 // TODO(austin): Windup...
438
439 // Slowly move back until we hit the upper limit.
440 double goal_position =
441 shooter_.goal_position() + values.shooter.zeroing_speed * dt;
442 // If during this cycle, we would move past the limit, we are done
443 // unloading.
444 if (goal_position > values.shooter.upper_limit) {
445 shooter_.SetGoalPosition(values.shooter.upper_limit, 0.0);
446 // We don't want the loop fighting the spring when we are unloaded.
447 // Turn it off.
448 shooter_loop_disable = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000449 state_ = STATE_READY_UNLOAD;
450 } else {
Austin Schuh30537882014-02-18 01:07:23 -0800451 shooter_.SetGoalPosition(goal_position, values.shooter.zeroing_speed);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000452 }
453
Austin Schuh30537882014-02-18 01:07:23 -0800454 latch_piston_ = false;
455 brake_piston_ = false;
456 } break;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000457 case STATE_READY_UNLOAD:
Austin Schuh30537882014-02-18 01:07:23 -0800458 if (goal->load_requested) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000459 state_ = STATE_REQUEST_LOAD;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000460 }
Austin Schuh30537882014-02-18 01:07:23 -0800461 // If we are ready to load again,
462 shooter_loop_disable = true;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000463
Austin Schuh30537882014-02-18 01:07:23 -0800464 latch_piston_ = false;
465 brake_piston_ = false;
466 break;
467
468 case STATE_ESTOP:
469 // Totally lost, go to a safe state.
470 shooter_loop_disable = true;
471 latch_piston_ = true;
472 brake_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000473 break;
joe2d92e852014-01-25 14:31:24 -0800474 }
475
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000476 if (apply_some_voltage) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000477 shooter_.Update(true);
478 if (output) output->voltage = 2.0;
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000479 } else if (!shooter_loop_disable) {
Austin Schuh30537882014-02-18 01:07:23 -0800480 LOG(DEBUG, "Running the loop, goal is %f, position is %f\n",
481 shooter_.goal_position(), shooter_.absolute_position());
Ben Fredrickson22c93322014-02-17 05:56:33 +0000482 shooter_.Update(output == NULL);
483 if (output) output->voltage = shooter_.voltage();
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000484 } else {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000485 shooter_.Update(true);
486 if (output) output->voltage = 0.0;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000487 }
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000488
Austin Schuh30537882014-02-18 01:07:23 -0800489 if (output) {
490 output->latch_piston = latch_piston_;
491 output->brake_piston = brake_piston_;
492 }
493
Ben Fredrickson22c93322014-02-17 05:56:33 +0000494 status->done =
Austin Schuhbe1401f2014-02-18 03:18:41 -0800495 ::std::abs(shooter_.absolute_position() - PowerToPosition(goal->shot_power)) < 0.004;
Austin Schuh30537882014-02-18 01:07:23 -0800496
497 if (position) {
498 last_position_ = *position;
499 LOG(DEBUG,
Austin Schuhbe1401f2014-02-18 03:18:41 -0800500 "pos > absolute: %f velocity: %f state= %d\n",
501 shooter_.absolute_position(), shooter_.absolute_velocity(),
Austin Schuh30537882014-02-18 01:07:23 -0800502 state_);
503 }
504 if (position) {
505 last_distal_posedge_count_ = position->pusher_distal.posedge_count;
506 last_proximal_posedge_count_ = position->pusher_proximal.posedge_count;
507 }
joe2d92e852014-01-25 14:31:24 -0800508}
509
510} // namespace control_loops
511} // namespace frc971