blob: faae2b02d423ae93e4c45029ae1b366b4486d400 [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 } else if (X_hat(2, 0) < last_voltage_ - 2.0) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000035 voltage_ += X_hat(2, 0) - (last_voltage_ - 2.0);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000036 }
37
38 voltage_ = std::min(limit, voltage_);
39 voltage_ = std::max(-limit, voltage_);
40 U(0, 0) = voltage_ - old_voltage;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000041
42 last_voltage_ = voltage_;
43}
44
Austin Schuh30537882014-02-18 01:07:23 -080045void ZeroedStateFeedbackLoop::SetCalibration(double encoder_val,
46 double known_position) {
47 LOG(INFO, "Setting calibration such that %f -> %f\n", encoder_val,
48 known_position);
49 LOG(INFO, "Position was %f\n", absolute_position());
50 double previous_offset = offset_;
51 offset_ = known_position - encoder_val;
52 double doffset = offset_ - previous_offset;
53 LOG(INFO, "Changing offset from %f to %f\n", previous_offset, offset_);
54 X_hat(0, 0) += doffset;
55 // Offset our measurements because the offset is baked into them.
56 Y_(0, 0) += doffset;
57 // Offset the goal so we don't move.
58 R(0, 0) += doffset;
59 LOG(INFO, "Validation: position is %f\n", absolute_position());
60}
61
Ben Fredricksonedf0e092014-02-16 10:46:50 +000062ShooterMotor::ShooterMotor(control_loops::ShooterGroup *my_shooter)
63 : aos::control_loops::ControlLoop<control_loops::ShooterGroup>(my_shooter),
64 shooter_(MakeShooterLoop()),
Ben Fredrickson22c93322014-02-17 05:56:33 +000065 state_(STATE_INITIALIZE),
66 loading_problem_end_time_(0, 0),
Austin Schuh30537882014-02-18 01:07:23 -080067 load_timeout_(0, 0),
Ben Fredrickson22c93322014-02-17 05:56:33 +000068 shooter_brake_set_time_(0, 0),
Austin Schuh30537882014-02-18 01:07:23 -080069 unload_timeout_(0, 0),
Ben Fredrickson22c93322014-02-17 05:56:33 +000070 prepare_fire_end_time_(0, 0),
71 shot_end_time_(0, 0),
Austin Schuh30537882014-02-18 01:07:23 -080072 cycles_not_moved_(0) {}
73
74double ShooterMotor::PowerToPosition(double power) {
75 // LOG(WARNING, "power to position not correctly implemented\n");
76 const frc971::constants::Values &values = constants::GetValues();
77 double new_pos = ::std::min(::std::max(power, values.shooter.lower_limit),
78 values.shooter.upper_limit);
79 return new_pos;
80}
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000081
82// Positive is out, and positive power is out.
joe2d92e852014-01-25 14:31:24 -080083void ShooterMotor::RunIteration(
Ben Fredricksonedf0e092014-02-16 10:46:50 +000084 const control_loops::ShooterGroup::Goal *goal,
85 const control_loops::ShooterGroup::Position *position,
86 control_loops::ShooterGroup::Output *output,
Ben Fredrickson22c93322014-02-17 05:56:33 +000087 control_loops::ShooterGroup::Status *status) {
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000088 constexpr double dt = 0.01;
89
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000090 // we must always have these or we have issues.
91 if (goal == NULL || status == NULL) {
Ben Fredrickson22c93322014-02-17 05:56:33 +000092 if (output) output->voltage = 0;
93 LOG(ERROR, "Thought I would just check for null and die.\n");
94 return;
95 }
96
Austin Schuh30537882014-02-18 01:07:23 -080097 if (reset()) {
98 state_ = STATE_INITIALIZE;
99 }
100 if (position) {
101 shooter_.CorrectPosition(position->position);
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000102 }
joe2d92e852014-01-25 14:31:24 -0800103
104 // Disable the motors now so that all early returns will return with the
105 // motors disabled.
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000106 if (output) output->voltage = 0;
joe2d92e852014-01-25 14:31:24 -0800107
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000108 const frc971::constants::Values &values = constants::GetValues();
109
Austin Schuh30537882014-02-18 01:07:23 -0800110 double relative_position = shooter_.position();
111 double absolute_position = shooter_.absolute_position();
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000112
Brian Silvermanaae236a2014-02-17 01:49:39 -0800113 // Don't even let the control loops run.
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000114 bool shooter_loop_disable = false;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000115
Brian Silvermanaae236a2014-02-17 01:49:39 -0800116 // Adds voltage to take up slack in gears before shot.
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000117 bool apply_some_voltage = false;
118
Austin Schuh30537882014-02-18 01:07:23 -0800119 // TODO(austin): Observe not seeing the sensors when we should by moving the
120 // calibration offset correclty.
121 const bool disabled = !::aos::robot_state->enabled;
122
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000123 switch (state_) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000124 case STATE_INITIALIZE:
Austin Schuhf5642a92014-02-18 01:42:32 -0800125 LOG(DEBUG, "Initializing\n");
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) {
160 // Need to go forward a little if we are starting with the
161 // back_distal_sensor triggered
162 if (position->plunger && position->latch) {
163 // The plunger is back and we are latched, get ready to shoot.
164 state_ = STATE_PREPARE_SHOT;
165 latch_piston_ = true;
166 } else if (position->pusher_distal.current) {
167 // We started on the sensor, back up until we are found.
168 // If the plunger is all the way back and not latched, it won't be
169 // there for long.
170 state_ = STATE_LOAD_BACKTRACK;
171 latch_piston_ = false;
172 } else {
173 // Off the sensor, start loading.
174 Load();
175 latch_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000176 }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000177 }
178
Austin Schuh30537882014-02-18 01:07:23 -0800179 // Hold our current position.
180 shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
181 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000182 break;
183 case STATE_LOAD_BACKTRACK:
Austin Schuh30537882014-02-18 01:07:23 -0800184 // If we are here, then that means we started past the edge where we want
185 // to zero. Move backwards until we don't see the sensor anymore.
186 // The plunger is contacting the pusher (or will be shortly).
187
188 // TODO(austin): Windup here and below!
189 if (!disabled) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000190 shooter_.SetGoalPosition(
Austin Schuhfaeee632014-02-18 01:24:05 -0800191 shooter_.goal_position() + values.shooter.zeroing_speed * dt,
192 values.shooter.zeroing_speed);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000193 }
194
Austin Schuh30537882014-02-18 01:07:23 -0800195 if (position) {
196 if (!position->pusher_distal.current) {
197 Load();
198 }
199 }
200
201 latch_piston_ = false;
202 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000203 break;
204 case STATE_LOAD:
Austin Schuh30537882014-02-18 01:07:23 -0800205 // If we are disabled right now, reset the timer.
206 if (disabled) {
207 Load();
208 // Latch defaults to true when disabled. Leave it latched until we have
209 // useful sensor data.
210 latch_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000211 }
Austin Schuh30537882014-02-18 01:07:23 -0800212 // Go to 0, which should be the latch position, or trigger a hall effect
213 // on the way. If we don't see edges where we are supposed to, the
214 // offset will be updated by code above.
215 shooter_.SetGoalPosition(0.0, 0.0);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000216
Austin Schuh30537882014-02-18 01:07:23 -0800217 if (position) {
218 // If we see a posedge on any of the hall effects,
219 if (position->pusher_proximal.posedge_count !=
220 last_proximal_posedge_count_) {
221 LOG(DEBUG, "Setting calibration using proximal sensor\n");
222 shooter_.SetCalibration(position->pusher_proximal.posedge_value,
223 values.shooter.pusher_proximal.upper_angle);
224 }
225 if (position->pusher_distal.posedge_count !=
226 last_distal_posedge_count_) {
227 LOG(DEBUG, "Setting calibration using distal sensor\n");
228 shooter_.SetCalibration(position->pusher_distal.posedge_value,
229 values.shooter.pusher_distal.upper_angle);
230 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000231
Austin Schuh30537882014-02-18 01:07:23 -0800232 // Latch if the plunger is far enough back to trigger the hall effect.
233 // This happens when the distal sensor is triggered.
234 latch_piston_ = position->pusher_distal.current;
235
236 // Check if we are latched and back.
237 if (position->plunger && position->latch) {
238 state_ = STATE_PREPARE_SHOT;
239 } else if (position->plunger &&
240 ::std::abs(shooter_.absolute_position() -
241 shooter_.goal_position()) < 0.001) {
242 // We are at the goal, but not latched.
243 state_ = STATE_LOADING_PROBLEM;
244 loading_problem_end_time_ = Time::Now() + Time::InSeconds(0.5);
245 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000246 }
Austin Schuh30537882014-02-18 01:07:23 -0800247 if (load_timeout_ < Time::Now()) {
248 if (position) {
249 if (!position->pusher_distal.current ||
250 !position->pusher_proximal.current) {
251 state_ = STATE_ESTOP;
252 }
253 }
254 } else if (goal->unload_requested) {
255 Unload();
256 }
257 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000258 break;
259 case STATE_LOADING_PROBLEM:
Austin Schuh30537882014-02-18 01:07:23 -0800260 if (disabled) {
261 Load();
262 }
263 // We got to the goal, but the latch hasn't registered as down. It might
264 // be stuck, or on it's way but not there yet.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000265 if (Time::Now() > loading_problem_end_time_) {
Austin Schuh30537882014-02-18 01:07:23 -0800266 // Timeout by unloading.
267 Unload();
268 } else if (position && position->plunger && position->latch) {
269 // If both trigger, we are latched.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000270 state_ = STATE_PREPARE_SHOT;
271 }
Austin Schuh30537882014-02-18 01:07:23 -0800272 // Move a bit further back to help it trigger.
273 // If the latch is slow due to the air flowing through the tubes or
274 // inertia, but is otherwise free, this won't have much time to do
275 // anything and is safe. Otherwise this gives us a bit more room to free
276 // up the latch.
277 shooter_.SetGoalPosition(values.shooter.lower_limit, 0.0);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000278 LOG(DEBUG, "Waiting on latch: plunger %d, latch: %d\n",
Austin Schuh60c56662014-02-17 14:37:19 -0800279 position->plunger, position->latch);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000280
Austin Schuh30537882014-02-18 01:07:23 -0800281 latch_piston_ = true;
282 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000283 break;
284 case STATE_PREPARE_SHOT:
Austin Schuh30537882014-02-18 01:07:23 -0800285 // Move the shooter to the shot power set point and then lock the brake.
286 // TODO(austin): Timeout. Low priority.
287
Ben Fredrickson22c93322014-02-17 05:56:33 +0000288 shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
Austin Schuh30537882014-02-18 01:07:23 -0800289
290 LOG(DEBUG, "PDIFF: absolute_position: %.2f, pow: %.2f\n",
291 absolute_position, PowerToPosition(goal->shot_power));
292 // TODO(austin): Goal velocity too...
293 if (::std::abs(shooter_.absolute_position() -
294 PowerToPosition(goal->shot_power)) < 0.001) {
295 // We are there, set the brake and move on.
296 latch_piston_ = true;
297 brake_piston_ = true;
298 shooter_brake_set_time_ = Time::Now() + Time::InSeconds(0.05);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000299 state_ = STATE_READY;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000300 } else {
Austin Schuh30537882014-02-18 01:07:23 -0800301 latch_piston_ = true;
302 brake_piston_ = false;
303 }
304 if (goal->unload_requested) {
305 Unload();
Ben Fredrickson22c93322014-02-17 05:56:33 +0000306 }
307 break;
308 case STATE_READY:
Austin Schuh30537882014-02-18 01:07:23 -0800309 LOG(DEBUG, "In ready\n");
310 // Wait until the brake is set, and a shot is requested or the shot power is changed.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000311 if (Time::Now() > shooter_brake_set_time_) {
Austin Schuh30537882014-02-18 01:07:23 -0800312 // We have waited long enough for the brake to set, turn the shooter control loop off.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000313 shooter_loop_disable = true;
Austin Schuh30537882014-02-18 01:07:23 -0800314 LOG(DEBUG, "Brake is now set\n");
315 if (goal->shot_requested && !disabled) {
316 LOG(DEBUG, "Shooting now\n");
317 shooter_loop_disable = true;
318 prepare_fire_end_time_ =
319 Time::Now(Time::kDefaultClock) + Time::InMS(40.0);
320 apply_some_voltage = true;
321 state_ = STATE_PREPARE_FIRE;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000322 }
Austin Schuh30537882014-02-18 01:07:23 -0800323 } else if (::std::abs(shooter_.absolute_position() -
324 PowerToPosition(goal->shot_power)) > 0.001) {
325 // TODO(austin): If the goal has changed, go back to prepare shot, not if we are off.
326 // TODO(austin): Add a state to release the brake.
327
328 // TODO(austin): Do we want to set the brake here or after shooting?
329 LOG(DEBUG, "Preparing shot again.\n");
330 state_ = STATE_PREPARE_SHOT;
331 } else {
332 LOG(DEBUG, "Nothing %d %d\n", goal->shot_requested, !disabled);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000333 }
Ben Fredricksona6d77542014-02-17 07:54:43 +0000334 shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
335
Austin Schuh30537882014-02-18 01:07:23 -0800336 latch_piston_ = true;
337 brake_piston_ = true;
338
339 if (goal->unload_requested) {
340 Unload();
341 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000342 break;
Austin Schuh30537882014-02-18 01:07:23 -0800343
344 case STATE_PREPARE_FIRE:
345 // Apply a bit of voltage to bias the gears for a little bit of time, and
346 // then fire.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000347 shooter_loop_disable = true;
Austin Schuh30537882014-02-18 01:07:23 -0800348 if (disabled) {
349 // If we are disabled, reset the backlash bias timer.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000350 prepare_fire_end_time_ =
351 Time::Now(Time::kDefaultClock) + Time::InMS(40.0);
Austin Schuh30537882014-02-18 01:07:23 -0800352 break;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000353 }
Austin Schuh30537882014-02-18 01:07:23 -0800354 if (Time::Now() > prepare_fire_end_time_) {
355 cycles_not_moved_ = 0;
356 firing_starting_position_ = shooter_.absolute_position();
357 shot_end_time_ = Time::Now() + Time::InSeconds(1);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000358 state_ = STATE_FIRE;
Austin Schuhf5642a92014-02-18 01:42:32 -0800359 latch_piston_ = false;
Austin Schuh30537882014-02-18 01:07:23 -0800360 } else {
361 apply_some_voltage = true;
Austin Schuhf5642a92014-02-18 01:42:32 -0800362 latch_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000363 }
364
Austin Schuh30537882014-02-18 01:07:23 -0800365 brake_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000366 break;
Austin Schuh30537882014-02-18 01:07:23 -0800367
Ben Fredrickson22c93322014-02-17 05:56:33 +0000368 case STATE_FIRE:
Austin Schuh30537882014-02-18 01:07:23 -0800369 if (disabled) {
370 if (position) {
371 if (position->plunger) {
372 // If disabled and the plunger is still back there, reset the
373 // timeout.
374 shot_end_time_ = Time::Now() + Time::InSeconds(1);
375 }
376 }
377 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000378 shooter_loop_disable = true;
Austin Schuh30537882014-02-18 01:07:23 -0800379 // Count the number of contiguous cycles during which we haven't moved.
380 if (::std::abs(last_position_.position - shooter_.absolute_position()) <
381 0.0005) {
382 ++cycles_not_moved_;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000383 } else {
384 cycles_not_moved_ = 0;
385 }
Austin Schuh30537882014-02-18 01:07:23 -0800386
387 // If we have moved any amount since the start and the shooter has now
388 // been still for a couple cycles, the shot finished.
389 // Also move on if it times out.
390 if ((::std::abs(firing_starting_position_ -
391 shooter_.absolute_position()) > 0.0005 &&
392 cycles_not_moved_ > 3) ||
393 Time::Now() > shot_end_time_) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000394 state_ = STATE_REQUEST_LOAD;
395 }
Austin Schuh30537882014-02-18 01:07:23 -0800396 latch_piston_ = false;
397 brake_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000398 break;
399 case STATE_UNLOAD:
Austin Schuh30537882014-02-18 01:07:23 -0800400 // Reset the timeouts.
401 if (disabled) Unload();
402
403 // If it is latched and the plunger is back, move the pusher back to catch
404 // the plunger.
Austin Schuh60c56662014-02-17 14:37:19 -0800405 if (position->plunger && position->latch) {
Austin Schuh30537882014-02-18 01:07:23 -0800406 // Pull back to 0, 0.
407 shooter_.SetGoalPosition(0.0, 0.0);
408 if (shooter_.absolute_position() < 0.005) {
409 // When we are close enough, 'fire'.
410 latch_piston_ = false;
411 } else {
412 latch_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000413 }
414 } else {
Austin Schuh30537882014-02-18 01:07:23 -0800415 // The plunger isn't all the way back, or it is and it is unlatched, so
416 // we can now unload.
417 shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
418 latch_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000419 state_ = STATE_UNLOAD_MOVE;
Austin Schuh30537882014-02-18 01:07:23 -0800420 unload_timeout_ = Time::Now() + Time::InSeconds(2.0);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000421 }
422
Austin Schuh30537882014-02-18 01:07:23 -0800423 if (Time::Now() > unload_timeout_) {
424 // We have been stuck trying to unload for way too long, give up and
425 // turn everything off.
426 state_ = STATE_ESTOP;
427 }
428
429 brake_piston_ = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000430 break;
Austin Schuh30537882014-02-18 01:07:23 -0800431 case STATE_UNLOAD_MOVE: {
432 if (disabled) {
433 unload_timeout_ = Time::Now() + Time::InSeconds(2.0);
434 shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
435 }
436 // TODO(austin): Windup...
437
438 // Slowly move back until we hit the upper limit.
439 double goal_position =
440 shooter_.goal_position() + values.shooter.zeroing_speed * dt;
441 // If during this cycle, we would move past the limit, we are done
442 // unloading.
443 if (goal_position > values.shooter.upper_limit) {
444 shooter_.SetGoalPosition(values.shooter.upper_limit, 0.0);
445 // We don't want the loop fighting the spring when we are unloaded.
446 // Turn it off.
447 shooter_loop_disable = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000448 state_ = STATE_READY_UNLOAD;
449 } else {
Austin Schuh30537882014-02-18 01:07:23 -0800450 shooter_.SetGoalPosition(goal_position, values.shooter.zeroing_speed);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000451 }
452
Austin Schuh30537882014-02-18 01:07:23 -0800453 latch_piston_ = false;
454 brake_piston_ = false;
455 } break;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000456 case STATE_READY_UNLOAD:
Austin Schuh30537882014-02-18 01:07:23 -0800457 if (goal->load_requested) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000458 state_ = STATE_REQUEST_LOAD;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000459 }
Austin Schuh30537882014-02-18 01:07:23 -0800460 // If we are ready to load again,
461 shooter_loop_disable = true;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000462
Austin Schuh30537882014-02-18 01:07:23 -0800463 latch_piston_ = false;
464 brake_piston_ = false;
465 break;
466
467 case STATE_ESTOP:
468 // Totally lost, go to a safe state.
469 shooter_loop_disable = true;
470 latch_piston_ = true;
471 brake_piston_ = true;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000472 break;
joe2d92e852014-01-25 14:31:24 -0800473 }
474
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000475 if (apply_some_voltage) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000476 shooter_.Update(true);
477 if (output) output->voltage = 2.0;
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000478 } else if (!shooter_loop_disable) {
Austin Schuh30537882014-02-18 01:07:23 -0800479 LOG(DEBUG, "Running the loop, goal is %f, position is %f\n",
480 shooter_.goal_position(), shooter_.absolute_position());
Ben Fredrickson22c93322014-02-17 05:56:33 +0000481 shooter_.Update(output == NULL);
482 if (output) output->voltage = shooter_.voltage();
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000483 } else {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000484 shooter_.Update(true);
485 if (output) output->voltage = 0.0;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000486 }
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000487
Austin Schuh30537882014-02-18 01:07:23 -0800488 if (output) {
489 output->latch_piston = latch_piston_;
490 output->brake_piston = brake_piston_;
491 }
492
Ben Fredrickson22c93322014-02-17 05:56:33 +0000493 status->done =
Austin Schuh30537882014-02-18 01:07:23 -0800494 ::std::abs(absolute_position - PowerToPosition(goal->shot_power)) < 0.004;
495
496 if (position) {
497 last_position_ = *position;
498 LOG(DEBUG,
499 "pos > real: %.2f adjusted: %.2f raw: %.2f state= %d\n",
500 relative_position, absolute_position, position->position,
501 state_);
502 }
503 if (position) {
504 last_distal_posedge_count_ = position->pusher_distal.posedge_count;
505 last_proximal_posedge_count_ = position->pusher_proximal.posedge_count;
506 }
joe2d92e852014-01-25 14:31:24 -0800507}
508
509} // namespace control_loops
510} // namespace frc971