blob: dfc440c2e0678e98250f73f9d5647f41da35faba [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 Fredrickson1f633ef2014-02-16 05:35:45 +000018
19void ZeroedStateFeedbackLoop::CapU() {
20 const double old_voltage = voltage_;
21 voltage_ += U(0, 0);
22
23 uncapped_voltage_ = voltage_;
24
25 double limit = zeroing_state() != UNKNOWN_POSITION ? 12.0 : kZeroingMaxVoltage;
26
27 // Make sure that reality and the observer can't get too far off. There is a
28 // delay by one cycle between the applied voltage and X_hat(2, 0), so compare
29 // against last cycle's voltage.
30 if (X_hat(2, 0) > last_voltage_ + 2.0) {
31 voltage_ -= X_hat(2, 0) - (last_voltage_ + 2.0);
32 LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
33 } else if (X_hat(2, 0) < last_voltage_ -2.0) {
34 voltage_ += X_hat(2, 0) - (last_voltage_ - 2.0);
35 LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
36 }
37
38 voltage_ = std::min(limit, voltage_);
39 voltage_ = std::max(-limit, voltage_);
40 U(0, 0) = voltage_ - old_voltage;
41 LOG(DEBUG, "abc %f\n", X_hat(2, 0) - voltage_);
42 LOG(DEBUG, "error %f\n", X_hat(0, 0) - R(0, 0));
43
44 last_voltage_ = voltage_;
45}
46
Ben Fredricksonedf0e092014-02-16 10:46:50 +000047ShooterMotor::ShooterMotor(control_loops::ShooterGroup *my_shooter)
48 : aos::control_loops::ControlLoop<control_loops::ShooterGroup>(my_shooter),
49 shooter_(MakeShooterLoop()),
50 calibration_position_(0.0),
51 state_(STATE_INITIALIZE),
52 loading_problem_end_time_(0,0),
53 shooter_brake_set_time_(0,0),
54 prepare_fire_end_time_(0,0),
55 shot_end_time_(0,0),
56 cycles_not_moved_(0) { }
joe2d92e852014-01-25 14:31:24 -080057
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000058
59// Positive is out, and positive power is out.
joe2d92e852014-01-25 14:31:24 -080060void ShooterMotor::RunIteration(
Ben Fredricksonedf0e092014-02-16 10:46:50 +000061 const control_loops::ShooterGroup::Goal *goal,
62 const control_loops::ShooterGroup::Position *position,
63 control_loops::ShooterGroup::Output *output,
64 control_loops::ShooterGroup::Status * status) {
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000065 constexpr double dt = 0.01;
66
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000067 // we must always have these or we have issues.
68 if (goal == NULL || status == NULL) {
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000069 if (output) output->voltage = 0;
70 LOG(ERROR, "Thought I would just check for null and die.\n");
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000071 return;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000072 }
joe2d92e852014-01-25 14:31:24 -080073
74 // Disable the motors now so that all early returns will return with the
75 // motors disabled.
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000076 if (output) output->voltage = 0;
joe2d92e852014-01-25 14:31:24 -080077
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000078 const frc971::constants::Values &values = constants::GetValues();
79
Ben Fredricksonedf0e092014-02-16 10:46:50 +000080 double real_position = position->position - calibration_position_;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000081
Ben Fredricksonedf0e092014-02-16 10:46:50 +000082 bool shooter_loop_disable = false;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000083
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000084 switch (state_) {
85 case STATE_INITIALIZE:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000086 // start off with the assumption that we are at the value
87 // futhest back given our sensors
88 if (position && position->pusher_distal_hall_effect){
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000089 calibration_position_ = position->position -
Ben Fredricksonedf0e092014-02-16 10:46:50 +000090 values.shooter.pusher_distal.lower_limit;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000091 } else if (position && position->pusher_proximal_hall_effect) {
92 calibration_position_ = position->position -
Ben Fredricksonedf0e092014-02-16 10:46:50 +000093 values.shooter.pusher_proximal.lower_limit;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000094 } else {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000095 calibration_position_ = values.shooter_total_length;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000096 }
97
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000098 state_ = STATE_REQUEST_LOAD;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000099
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000100 // zero out initial goal
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000101 shooter_.SetGoalPosition(0.0, 0.0);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000102 if (position) {
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000103 output->latch_piston = position->plunger_back_hall_effect;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000104 } else {
105 // we don't know what is going on so just close the latch to be safe
106 output->latch_piston = true;
107 }
108 output->brake_piston = false;
109 break;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000110 case STATE_REQUEST_LOAD:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000111 if (position->plunger_back_hall_effect && position->latch_hall_effect) {
112 // already latched
113 state_ = STATE_PREPARE_SHOT;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000114 } else if (position->pusher_distal_hall_effect ||
115 (real_position) < 0) {
116 state_ = STATE_LOAD_BACKTRACK;
117 if (position) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000118 calibration_position_ = position->position;
119 }
120 } else {
121 state_ = STATE_LOAD;
122 }
123
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000124 shooter_.SetGoalPosition(0.0, 0.0);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000125 if (position && output) output->latch_piston = position->plunger_back_hall_effect;
126 output->brake_piston = false;
127 break;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000128 case STATE_LOAD_BACKTRACK:
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000129 if (real_position < values.shooter.pusher_distal.upper_limit + 0.01) {
130 shooter_.SetGoalPosition(position->position + values.shooter_zeroing_speed*dt,
131 values.shooter_zeroing_speed);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000132 } else {
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000133 state_ = STATE_LOAD;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000134 }
135
136 output->latch_piston = false;
137 output->brake_piston = true;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000138 break;
139 case STATE_LOAD:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000140 if (position->pusher_proximal_hall_effect &&
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000141 !last_position_.pusher_proximal_hall_effect) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000142 calibration_position_ = position->position -
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000143 values.shooter.pusher_proximal.upper_limit;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000144 }
145 if (position->pusher_distal_hall_effect &&
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000146 !last_position_.pusher_distal_hall_effect) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000147 calibration_position_ = position->position -
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000148 values.shooter.pusher_distal.lower_limit;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000149 }
150
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000151 shooter_.SetGoalPosition(calibration_position_, 0.0);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000152 if (position && output) output->latch_piston = position->plunger_back_hall_effect;
153 if(output) output->brake_piston = false;
154
155 if (position->plunger_back_hall_effect && position->latch_hall_effect) {
156 state_ = STATE_PREPARE_SHOT;
157 } else if (position->plunger_back_hall_effect &&
158 position->position == PowerToPosition(goal->shot_power)) {
159 //TODO_ben: I'm worried it will bounce states if the position is drifting slightly
160 state_ = STATE_LOADING_PROBLEM;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000161 loading_problem_end_time_ = Time::Now(Time::kDefaultClock) + Time::InSeconds(3.0);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000162 }
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000163 break;
164 case STATE_LOADING_PROBLEM:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000165 if (position->plunger_back_hall_effect && position->latch_hall_effect) {
166 state_ = STATE_PREPARE_SHOT;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000167 } else if (real_position < -0.02 || Time::Now() > loading_problem_end_time_) {
168 state_ = STATE_UNLOAD;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000169 }
170
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000171 shooter_.SetGoalPosition(position->position - values.shooter_zeroing_speed*dt,
172 values.shooter_zeroing_speed);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000173 if (output) output->latch_piston = true;
174 if (output) output->brake_piston = false;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000175 break;
176 case STATE_PREPARE_SHOT:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000177 shooter_.SetGoalPosition(
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000178 PowerToPosition(goal->shot_power), 0.0);
179 //TODO_ben: I'm worried it will bounce states if the position is drifting slightly
180 if (position->position == PowerToPosition(goal->shot_power)) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000181 state_ = STATE_READY;
182 output->latch_piston = true;
183 output->brake_piston = true;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000184 shooter_brake_set_time_ = Time::Now(Time::kDefaultClock) + Time::InSeconds(3.0);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000185 } else {
186 output->latch_piston =true;
187 output->brake_piston = false;
188 }
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000189 break;
190 case STATE_READY:
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000191 if (Time::Now() > shooter_brake_set_time_) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000192 shooter_loop_disable = true;
193 if (goal->unload_requested) {
194 state_ = STATE_UNLOAD;
195 } else if (PowerToPosition(goal->shot_power)
196 != position->position) {
197 //TODO_ben: I'm worried it will bounce states if the position is drifting slightly
198 state_ = STATE_PREPARE_SHOT;
199 }else if (goal->shot_requested) {
200 state_ = STATE_REQUEST_FIRE;
201 }
202
203 }
204 output->latch_piston = true;
205 output->brake_piston = true;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000206 break;
207 case STATE_REQUEST_FIRE:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000208 shooter_loop_disable = true;
209 if (position->plunger_back_hall_effect) {
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000210 prepare_fire_end_time_ = Time::Now(Time::kDefaultClock)
211 + Time::InMS(40.0);
212 shooter_.ApplySomeVoltage();
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000213 state_ = STATE_PREPARE_FIRE;
214 } else {
215 state_ = STATE_REQUEST_LOAD;
216 }
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000217 break;
218 case STATE_PREPARE_FIRE:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000219 shooter_loop_disable = true;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000220 if (Time::Now(Time::kDefaultClock) < prepare_fire_end_time_) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000221 shooter_.ApplySomeVoltage();
222 } else {
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000223 state_ = STATE_FIRE;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000224 cycles_not_moved_ = 0;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000225 shot_end_time_ = Time::Now(Time::kDefaultClock) +
226 Time::InMS(500);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000227 }
228
229 output->latch_piston = true;
230 output->brake_piston = true;
231
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000232 break;
233 case STATE_FIRE:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000234 shooter_loop_disable = true;
235 //TODO_ben: need approamately equal
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000236 if (last_position_.position - position->position < 7) {
237 cycles_not_moved_++;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000238 } else {
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000239 cycles_not_moved_ = 0;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000240 }
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000241 if ((real_position < 10.0 && cycles_not_moved_ > 5) ||
242 Time::Now(Time::kDefaultClock) > shot_end_time_) {
243 state_ = STATE_REQUEST_LOAD;
244 }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000245 output->latch_piston = true;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000246 output->brake_piston = true;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000247 break;
248 case STATE_UNLOAD:
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000249 if (position->plunger_back_hall_effect && position->latch_hall_effect) {
250 shooter_.SetGoalPosition(0.02, 0.0);
251 if (real_position == 0.02) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000252 output->latch_piston = false;
253 }
254 } else {
255 output->latch_piston = false;
256 state_ = STATE_UNLOAD_MOVE;
257 }
258
259 output->brake_piston = false;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000260 break;
261 case STATE_UNLOAD_MOVE:
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000262 if (position->position > values.shooter_total_length - 0.03) {
263 shooter_.SetGoalPosition(position->position, 0.0);
264 state_ = STATE_READY_UNLOAD;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000265 } else {
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000266 shooter_.SetGoalPosition(
267 position->position + values.shooter_zeroing_speed*dt,
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000268 values.shooter_zeroing_speed);
269 }
270
271 output->latch_piston = false;
272 output->brake_piston = false;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000273 break;
274 case STATE_READY_UNLOAD:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000275 if (!goal->unload_requested) {
276 state_ = STATE_REQUEST_LOAD;
277 }
278
279 output->latch_piston = false;
280 output->brake_piston = false;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000281 break;
282 }
283
joe2d92e852014-01-25 14:31:24 -0800284 if (position) {
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000285 last_position_ = *position;
286 LOG(DEBUG, "pos: hall: real: %.2f absolute: %.2f\n",
287 real_position, position->position);
joe2d92e852014-01-25 14:31:24 -0800288 }
289
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000290 if (!shooter_loop_disable) {
291 output->voltage = shooter_.voltage();
292 }
293 status->done = ::std::abs(position->position - PowerToPosition(goal->shot_power)) < 0.004;
joe2d92e852014-01-25 14:31:24 -0800294}
295
296} // namespace control_loops
297} // namespace frc971