blob: 08138fff048e0dc4e60b53d112a39ff8965d0bc2 [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_) {
Austin Schuh60c56662014-02-17 14:37:19 -080077 // TODO(austin): If 'reset()', we are lost, start over.
Ben Fredrickson22c93322014-02-17 05:56:33 +000078 initial_loop_ = false;
79 shooter_.SetPositionDirectly(position->position);
80 } else {
81 shooter_.SetPositionValues(position->position);
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000082 }
joe2d92e852014-01-25 14:31:24 -080083
84 // Disable the motors now so that all early returns will return with the
85 // motors disabled.
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000086 if (output) output->voltage = 0;
joe2d92e852014-01-25 14:31:24 -080087
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000088 const frc971::constants::Values &values = constants::GetValues();
89
Ben Fredrickson22c93322014-02-17 05:56:33 +000090 double real_position = shooter_.position();
91 double adjusted_position = shooter_.position() - calibration_position_;
92
93 if (position) {
94 last_position_ = *position;
95 LOG(DEBUG,
96 "pos > real: %.2f adjusted: %.2f raw: %.2f calib: %.2f state= %d\n",
97 real_position, adjusted_position, position->position,
98 calibration_position_, state_);
99 }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000100
Brian Silvermanaae236a2014-02-17 01:49:39 -0800101 // Don't even let the control loops run.
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000102 bool shooter_loop_disable = false;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000103
Brian Silvermanaae236a2014-02-17 01:49:39 -0800104 // Adds voltage to take up slack in gears before shot.
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000105 bool apply_some_voltage = false;
106
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000107 switch (state_) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000108 case STATE_INITIALIZE:
Brian Silvermanaae236a2014-02-17 01:49:39 -0800109 // Start off with the assumption that we are at the value
110 // futhest back given our sensors.
111 if (position && position->pusher_distal.current) {
Austin Schuh60c56662014-02-17 14:37:19 -0800112 //TODO(ben): use posedge
Ben Fredrickson22c93322014-02-17 05:56:33 +0000113 calibration_position_ =
Brian Silvermanaae236a2014-02-17 01:49:39 -0800114 position->position - values.shooter.pusher_distal.lower_angle;
115 } else if (position && position->pusher_proximal.current) {
Austin Schuh60c56662014-02-17 14:37:19 -0800116 //TODO(ben): use posedge
Ben Fredrickson22c93322014-02-17 05:56:33 +0000117 calibration_position_ =
Brian Silvermanaae236a2014-02-17 01:49:39 -0800118 position->position - values.shooter.pusher_proximal.lower_angle;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000119 }
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000120
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000121 state_ = STATE_REQUEST_LOAD;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000122
Brian Silvermanaae236a2014-02-17 01:49:39 -0800123 // Zero out initial goal.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000124 shooter_.SetGoalPosition(real_position, 0.0);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000125 if (position) {
Austin Schuh60c56662014-02-17 14:37:19 -0800126 output->latch_piston = position->plunger;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000127 } else {
Brian Silvermanaae236a2014-02-17 01:49:39 -0800128 // We don't know what is going on so just close the latch to be safe.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000129 output->latch_piston = true;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000130 }
131 output->brake_piston = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000132 break;
133 case STATE_REQUEST_LOAD:
Austin Schuh60c56662014-02-17 14:37:19 -0800134 if (position->plunger && position->latch) {
Brian Silvermanaae236a2014-02-17 01:49:39 -0800135 // Already latched.
Ben Fredrickson22c93322014-02-17 05:56:33 +0000136 state_ = STATE_PREPARE_SHOT;
Austin Schuh60c56662014-02-17 14:37:19 -0800137 } else if (position->pusher_distal.current || (adjusted_position) < 0) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000138 state_ = STATE_LOAD_BACKTRACK;
Austin Schuh60c56662014-02-17 14:37:19 -0800139 // TODO(ben): double check that rezero is the right thing to do here
Ben Fredrickson22c93322014-02-17 05:56:33 +0000140 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);
Austin Schuh60c56662014-02-17 14:37:19 -0800148 if (position && output) {
149 output->latch_piston = position->plunger;
150 }
151 if (output) {
152 output->brake_piston = false;
153 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000154 break;
155 case STATE_LOAD_BACKTRACK:
Brian Silvermanaae236a2014-02-17 01:49:39 -0800156 if (adjusted_position > values.shooter.pusher_distal.upper_angle + 0.01) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000157 shooter_.SetGoalPosition(
Austin Schuh60c56662014-02-17 14:37:19 -0800158 real_position - values.shooter.zeroing_speed * dt,
159 values.shooter.zeroing_speed);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000160 } else {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000161 state_ = STATE_LOAD;
162 }
163
164 if (output) output->latch_piston = false;
165 if (output) output->brake_piston = true;
166 break;
167 case STATE_LOAD:
Brian Silvermanaae236a2014-02-17 01:49:39 -0800168 if (position && position->pusher_proximal.current &&
169 !last_position_.pusher_proximal.current) {
Austin Schuh60c56662014-02-17 14:37:19 -0800170 //TODO(ben): use posedge
Ben Fredrickson22c93322014-02-17 05:56:33 +0000171 calibration_position_ =
Brian Silvermanaae236a2014-02-17 01:49:39 -0800172 position->position - values.shooter.pusher_proximal.upper_angle;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000173 }
Brian Silvermanaae236a2014-02-17 01:49:39 -0800174 if (position && position->pusher_distal.current &&
175 !last_position_.pusher_distal.current) {
Austin Schuh60c56662014-02-17 14:37:19 -0800176 //TODO(ben): use posedge
Ben Fredrickson22c93322014-02-17 05:56:33 +0000177 calibration_position_ =
Brian Silvermanaae236a2014-02-17 01:49:39 -0800178 position->position - values.shooter.pusher_distal.lower_angle;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000179 }
180
181 shooter_.SetGoalPosition(calibration_position_, 0.0);
182 if (position && output) {
Austin Schuh60c56662014-02-17 14:37:19 -0800183 output->latch_piston = position->plunger;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000184 }
185
Austin Schuh60c56662014-02-17 14:37:19 -0800186 if (position->plunger && position->latch) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000187 state_ = STATE_PREPARE_SHOT;
Austin Schuh60c56662014-02-17 14:37:19 -0800188 } else if (position->plunger &&
Ben Fredricksona6d77542014-02-17 07:54:43 +0000189 fabs(adjusted_position - PowerToPosition(goal->shot_power)) <
Austin Schuh60c56662014-02-17 14:37:19 -0800190 0.05) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000191 state_ = STATE_LOADING_PROBLEM;
192 loading_problem_end_time_ =
193 Time::Now(Time::kDefaultClock) + Time::InSeconds(3.0);
194 }
195 if (output) output->brake_piston = false;
196 break;
197 case STATE_LOADING_PROBLEM:
198 if (Time::Now() > loading_problem_end_time_) {
199 state_ = STATE_UNLOAD;
Austin Schuh60c56662014-02-17 14:37:19 -0800200 } else if (position->plunger && position->latch) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000201 state_ = STATE_PREPARE_SHOT;
202 }
203 shooter_.SetGoalPosition(calibration_position_, 0.0);
204 LOG(DEBUG, "Waiting on latch: plunger %d, latch: %d\n",
Austin Schuh60c56662014-02-17 14:37:19 -0800205 position->plunger, position->latch);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000206
207 if (output) output->latch_piston = true;
208 if (output) output->brake_piston = false;
209 break;
210 case STATE_PREPARE_SHOT:
211 shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
Ben Fredricksona6d77542014-02-17 07:54:43 +0000212 LOG(DEBUG, "PDIFF: adjusted_position: %.2f, pow: %.2f\n",
213 adjusted_position, PowerToPosition(goal->shot_power));
214 if (fabs(adjusted_position - PowerToPosition(goal->shot_power)) < 0.05) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000215 state_ = STATE_READY;
216 output->latch_piston = true;
217 output->brake_piston = true;
218 shooter_brake_set_time_ =
Ben Fredricksona6d77542014-02-17 07:54:43 +0000219 Time::Now(Time::kDefaultClock) + Time::InSeconds(0.03);
Ben Fredrickson22c93322014-02-17 05:56:33 +0000220 } else {
221 output->latch_piston = true;
222 output->brake_piston = false;
223 }
224 break;
225 case STATE_READY:
226 if (Time::Now() > shooter_brake_set_time_) {
227 shooter_loop_disable = true;
228 if (goal->unload_requested) {
Ben Fredricksona6d77542014-02-17 07:54:43 +0000229 printf("GHA\n");
Ben Fredrickson22c93322014-02-17 05:56:33 +0000230 state_ = STATE_UNLOAD;
Ben Fredricksona6d77542014-02-17 07:54:43 +0000231 } else if (fabs(adjusted_position - PowerToPosition(goal->shot_power)) >
Ben Fredrickson22c93322014-02-17 05:56:33 +0000232 0.05) {
Ben Fredricksona6d77542014-02-17 07:54:43 +0000233 printf("GHB\n");
Ben Fredrickson22c93322014-02-17 05:56:33 +0000234 state_ = STATE_PREPARE_SHOT;
235 } else if (goal->shot_requested) {
Ben Fredricksona6d77542014-02-17 07:54:43 +0000236 printf("GHC\n");
Ben Fredrickson22c93322014-02-17 05:56:33 +0000237 state_ = STATE_REQUEST_FIRE;
238 }
Ben Fredrickson22c93322014-02-17 05:56:33 +0000239 }
Ben Fredricksona6d77542014-02-17 07:54:43 +0000240 shooter_.SetGoalPosition(PowerToPosition(goal->shot_power), 0.0);
241
Ben Fredrickson22c93322014-02-17 05:56:33 +0000242 output->latch_piston = true;
243 output->brake_piston = true;
244 break;
245 case STATE_REQUEST_FIRE:
246 shooter_loop_disable = true;
Austin Schuh60c56662014-02-17 14:37:19 -0800247 if (position->plunger) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000248 prepare_fire_end_time_ =
249 Time::Now(Time::kDefaultClock) + Time::InMS(40.0);
250 apply_some_voltage = true;
251 state_ = STATE_PREPARE_FIRE;
252 } else {
253 state_ = STATE_REQUEST_LOAD;
254 }
255 break;
256 case STATE_PREPARE_FIRE:
257 shooter_loop_disable = true;
258 if (Time::Now(Time::kDefaultClock) < prepare_fire_end_time_) {
259 apply_some_voltage = true;
260 } else {
261 state_ = STATE_FIRE;
262 cycles_not_moved_ = 0;
263 shot_end_time_ = Time::Now(Time::kDefaultClock) + Time::InMS(500);
264 }
265
266 output->latch_piston = true;
267 output->brake_piston = true;
268
269 break;
270 case STATE_FIRE:
271 shooter_loop_disable = true;
Austin Schuh60c56662014-02-17 14:37:19 -0800272 //TODO(ben): need approamately equal
Ben Fredricksona6d77542014-02-17 07:54:43 +0000273 if (fabs(last_position_.position - adjusted_position) < 0.07) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000274 cycles_not_moved_++;
275 } else {
276 cycles_not_moved_ = 0;
277 }
278 if ((adjusted_position < 0.10 && cycles_not_moved_ > 5) ||
279 Time::Now(Time::kDefaultClock) > shot_end_time_) {
280 state_ = STATE_REQUEST_LOAD;
281 }
282 output->latch_piston = true;
283 output->brake_piston = true;
284 break;
285 case STATE_UNLOAD:
Austin Schuh60c56662014-02-17 14:37:19 -0800286 if (position->plunger && position->latch) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000287 shooter_.SetGoalPosition(0.02, 0.0);
288 if (adjusted_position < 0.04) {
289 output->latch_piston = false;
290 }
291 } else {
292 output->latch_piston = false;
293 state_ = STATE_UNLOAD_MOVE;
294 }
295
296 output->brake_piston = false;
297 break;
298 case STATE_UNLOAD_MOVE:
Austin Schuh60c56662014-02-17 14:37:19 -0800299 if (adjusted_position > values.shooter.upper_limit - 0.03) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000300 shooter_.SetGoalPosition(real_position, 0.0);
301 state_ = STATE_READY_UNLOAD;
302 } else {
303 shooter_.SetGoalPosition(
Austin Schuh60c56662014-02-17 14:37:19 -0800304 real_position + values.shooter.zeroing_speed * dt,
305 values.shooter.zeroing_speed);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000306 }
307
308 output->latch_piston = false;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000309 output->brake_piston = false;
310 break;
311 case STATE_READY_UNLOAD:
312 if (!goal->unload_requested) {
313 state_ = STATE_REQUEST_LOAD;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000314 }
315
Ben Fredrickson22c93322014-02-17 05:56:33 +0000316 output->latch_piston = false;
317 output->brake_piston = false;
318 break;
joe2d92e852014-01-25 14:31:24 -0800319 }
320
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000321 if (apply_some_voltage) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000322 shooter_.Update(true);
323 if (output) output->voltage = 2.0;
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000324 } else if (!shooter_loop_disable) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000325 LOG(DEBUG, "Running the loop, goal is %f\n", shooter_.R(0, 0));
326 shooter_.Update(output == NULL);
327 if (output) output->voltage = shooter_.voltage();
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000328 } else {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000329 shooter_.Update(true);
330 if (output) output->voltage = 0.0;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000331 }
Ben Fredrickson7d980c22014-02-16 21:39:02 +0000332
Ben Fredrickson22c93322014-02-17 05:56:33 +0000333 status->done =
Ben Fredricksona6d77542014-02-17 07:54:43 +0000334 ::std::fabs(adjusted_position - PowerToPosition(goal->shot_power)) < 0.004;
joe2d92e852014-01-25 14:31:24 -0800335}
336
337} // namespace control_loops
338} // namespace frc971