blob: 5c6548ccc97176df51bbf7fb983548477bf887ca [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"
8#include "aos/common/logging/logging.h"
9
10#include "frc971/constants.h"
joe93778a62014-02-15 13:22:14 -080011#include "frc971/control_loops/shooter/shooter_motor_plant.h"
joe2d92e852014-01-25 14:31:24 -080012
13namespace frc971 {
14namespace control_loops {
15
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000016
17void ZeroedStateFeedbackLoop::CapU() {
18 const double old_voltage = voltage_;
19 voltage_ += U(0, 0);
20
21 uncapped_voltage_ = voltage_;
22
23 double limit = zeroing_state() != UNKNOWN_POSITION ? 12.0 : kZeroingMaxVoltage;
24
25 // Make sure that reality and the observer can't get too far off. There is a
26 // delay by one cycle between the applied voltage and X_hat(2, 0), so compare
27 // against last cycle's voltage.
28 if (X_hat(2, 0) > last_voltage_ + 2.0) {
29 voltage_ -= X_hat(2, 0) - (last_voltage_ + 2.0);
30 LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
31 } else if (X_hat(2, 0) < last_voltage_ -2.0) {
32 voltage_ += X_hat(2, 0) - (last_voltage_ - 2.0);
33 LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
34 }
35
36 voltage_ = std::min(limit, voltage_);
37 voltage_ = std::max(-limit, voltage_);
38 U(0, 0) = voltage_ - old_voltage;
39 LOG(DEBUG, "abc %f\n", X_hat(2, 0) - voltage_);
40 LOG(DEBUG, "error %f\n", X_hat(0, 0) - R(0, 0));
41
42 last_voltage_ = voltage_;
43}
44
joe2d92e852014-01-25 14:31:24 -080045ShooterMotor::ShooterMotor(control_loops::ShooterLoop *my_shooter)
46 : aos::control_loops::ControlLoop<control_loops::ShooterLoop>(my_shooter),
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000047 shooter_(MakeShooterLoop()) {
joe2d92e852014-01-25 14:31:24 -080048 {
49 using ::frc971::constants::GetValues;
50 ZeroedJoint<1>::ConfigurationData config_data;
51
joe3779d0c2014-02-15 19:41:22 -080052 config_data.lower_limit = GetValues().shooter_lower_physical_limit;
53 config_data.upper_limit = GetValues().shooter_upper_physical_limit;
joe93778a62014-02-15 13:22:14 -080054 //config_data.hall_effect_start_position[0] =
55 // GetValues().shooter_hall_effect_start_position;
joe2d92e852014-01-25 14:31:24 -080056 config_data.zeroing_off_speed = GetValues().shooter_zeroing_off_speed;
57 config_data.zeroing_speed = GetValues().shooter_zeroing_speed;
joe2d92e852014-01-25 14:31:24 -080058 config_data.max_zeroing_voltage = 5.0;
59 config_data.deadband_voltage = 0.0;
60
61 zeroed_joint_.set_config_data(config_data);
62 }
63}
64
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000065
66// Positive is out, and positive power is out.
joe2d92e852014-01-25 14:31:24 -080067void ShooterMotor::RunIteration(
joe93778a62014-02-15 13:22:14 -080068 const ShooterLoop::Goal *goal,
joe2d92e852014-01-25 14:31:24 -080069 const control_loops::ShooterLoop::Position *position,
70 ::aos::control_loops::Output *output,
71 ::aos::control_loops::Status * status) {
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000072 constexpr double dt = 0.01;
73
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000074 // we must always have these or we have issues.
75 if (goal == NULL || status == NULL) {
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000076 transform-position_ptr = NULL;
77 if (output) output->voltage = 0;
78 LOG(ERROR, "Thought I would just check for null and die.\n");
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000079 return;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000080 }
joe2d92e852014-01-25 14:31:24 -080081
82 // Disable the motors now so that all early returns will return with the
83 // motors disabled.
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000084 if (output) output->voltage = 0;
joe2d92e852014-01-25 14:31:24 -080085
86 ZeroedJoint<1>::PositionData transformed_position;
87 ZeroedJoint<1>::PositionData *transformed_position_ptr =
88 &transformed_position;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000089 if (position) {
90 transformed_position.position = position->pos;
91 transformed_position.hall_effects[0] = position->hall_effect;
92 transformed_position.hall_effect_positions[0] = position->calibration;
93 }
joe2d92e852014-01-25 14:31:24 -080094
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000095 const double voltage = shooter_.Update(transformed_position_ptr,
joe2d92e852014-01-25 14:31:24 -080096 output != NULL,
97 goal->goal, 0.0);
98
Ben Fredrickson1e512ff2014-02-15 21:36:52 +000099 const frc971::constants::Values &values = constants::GetValues();
100
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000101 double absolute_position = postiion->position - calibration_position_;
102
103
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000104 switch (state_) {
105 case STATE_INITIALIZE:
106 shooter_.zeroing_state() = ZeroedStateFeedbackLoop::UNKNOWN_POSITION;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000107
108 // start off with the assumption that we are at the value
109 // futhest back given our sensors
110 if (position && position->pusher_distal_hall_effect){
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000111 calibration_position_ = position->position -
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000112 values.pusher_distal_heffect.lower_edge;
113 } else if (position && position->pusher_proximal_hall_effect) {
114 calibration_position_ = position->position -
115 values.pusher_proximal_heffect.lower_edge;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000116 } else {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000117 calibration_position_ = values.shooter_total_length;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000118 }
119
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000120 state_ = STATE_REQUEST_LOAD;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000121
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000122 // zero out initial goal
123 shooter_.SetGoalPositionVelocity(0.0, 0.0);
124 if (position) {
125 output->latch_pistion = position->plunger_back_hall_effect;
126 } else {
127 // we don't know what is going on so just close the latch to be safe
128 output->latch_piston = true;
129 }
130 output->brake_piston = false;
131 break;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000132 case STATE_REQUEST_LOAD:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000133 if (position->plunger_back_hall_effect && position->latch_hall_effect) {
134 // already latched
135 state_ = STATE_PREPARE_SHOT;
136 } else if (postion->pusher_back_distal_hall_effect ||
137 (relative_position) < 0) {
138 state_ = STATE_LOADING_BACKTRACK;
139 if (relative_position) {
140 calibration_position_ = position->position;
141 }
142 } else {
143 state_ = STATE_LOAD;
144 }
145
146 shooter_.SetGoalPositionVelocity(0.0, 0.0);
147 if (position && output) output->latch_piston = position->plunger_back_hall_effect;
148 output->brake_piston = false;
149 break;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000150 case STATE_LOAD_BACKTRACK:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000151 if (absolute_position < values.pusher_back_distal_heffect.lower_edge + 0.01) {
152 shooter_.SetGoalPositionVelocity(position->position + values.shooter_zero_speed*dt,
153 values.shooter_zero_speed);
154 } else {
155 state = STATE_LOAD;
156 }
157
158 output->latch_piston = false;
159 output->brake_piston = true;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000160 break;
161 case STATE_LOAD:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000162 if (position->pusher_proximal_hall_effect &&
163 !last_position_.pusher_back_proximal_hall_effect) {
164 calibration_position_ = position->position -
165 values.pusher_promimal_heffect.lower_edge;
166 }
167 if (position->pusher_distal_hall_effect &&
168 !last_position_.pusher_back_distal_hall_effect) {
169 calibration_position_ = position->position -
170 values.pusher_distal_heffect.lower_edge;
171
172 }
173
174 shooter_.SetGoalPositionVelocity(calibration_position_, 0.0);
175 if (position && output) output->latch_piston = position->plunger_back_hall_effect;
176 if(output) output->brake_piston = false;
177
178 if (position->plunger_back_hall_effect && position->latch_hall_effect) {
179 state_ = STATE_PREPARE_SHOT;
180 } else if (position->plunger_back_hall_effect &&
181 position->position == PowerToPosition(goal->shot_power)) {
182 //TODO_ben: I'm worried it will bounce states if the position is drifting slightly
183 state_ = STATE_LOADING_PROBLEM;
184 loading_problem_end_time_ = clock() + 3 * CLOCKS_PER_SECOND;
185 }
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000186 break;
187 case STATE_LOADING_PROBLEM:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000188 if (position->plunger_back_hall_effect && position->latch_hall_effect) {
189 state_ = STATE_PREPARE_SHOT;
190 } else if (absolute_position < -0.02 || clock() > loading_problem_end_time_) {
191 state = STATE_UNLOAD;
192 }
193
194 shooter_.SetGoalPositionVelocity(position->position - values.shooter_zero_speed*dt,
195 values.shooter_zero_speed);
196 if (output) output->latch_piston = true;
197 if (output) output->brake_piston = false;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000198 break;
199 case STATE_PREPARE_SHOT:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000200 shooter_.SetGoalPosition(
201 PowerToPosition(shot_power), 0.0);
202 if (position->position == shooter.goal_position) {
203 state_ = STATE_READY;
204 output->latch_piston = true;
205 output->brake_piston = true;
206 shooter_brake_set_time_ = clock() + 5 * CLOCKS_PER_SECOND;
207 } else {
208 output->latch_piston =true;
209 output->brake_piston = false;
210 }
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000211 break;
212 case STATE_READY:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000213 if (clock() > shooter_brake_set_time_) {
214 shooter_loop_disable = true;
215 if (goal->unload_requested) {
216 state_ = STATE_UNLOAD;
217 } else if (PowerToPosition(goal->shot_power)
218 != position->position) {
219 //TODO_ben: I'm worried it will bounce states if the position is drifting slightly
220 state_ = STATE_PREPARE_SHOT;
221 }else if (goal->shot_requested) {
222 state_ = STATE_REQUEST_FIRE;
223 }
224
225 }
226 output->latch_piston = true;
227 output->brake_piston = true;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000228 break;
229 case STATE_REQUEST_FIRE:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000230 shooter_loop_disable = true;
231 if (position->plunger_back_hall_effect) {
232 prepare_fire_end_time_ = clock() + 10;
233 state_ = STATE_PREPARE_FIRE;
234 } else {
235 state_ = STATE_REQUEST_LOAD;
236 }
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000237 break;
238 case STATE_PREPARE_FIRE:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000239 shooter_loop_disable = true;
240 if (clock() < prepare_fire_end_time_) {
241 shooter_.ApplySomeVoltage();
242 } else {
243 State_ = STATE_FIRE;
244 cycles_not_moved_ = 0;
245 shot_end_time_ = clock() + 0.5 * CLOCKS_PER_SECOND;
246 }
247
248 output->latch_piston = true;
249 output->brake_piston = true;
250
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000251 break;
252 case STATE_FIRE:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000253 shooter_loop_disable = true;
254 //TODO_ben: need approamately equal
255 if (last_position->position - position->position < 7) {
256 cycles_not_moved++;
257 } else {
258 cycles_not_moved = 0;
259 }
260 output->latch_piston = true;
261 ouput->brake_piston = true;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000262 break;
263 case STATE_UNLOAD:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000264 if (position->plunger_back_hall_effect && position->latch_piston) {
265 shooter_SetGoalPosition(0.02, 0.0);
266 if (ablsolute_position == 0.02) {
267 output->latch_piston = false;
268 }
269 } else {
270 output->latch_piston = false;
271 state_ = STATE_UNLOAD_MOVE;
272 }
273
274 output->brake_piston = false;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000275 break;
276 case STATE_UNLOAD_MOVE:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000277 if (position->position > values.shooter_length - 0.03) {
278 shooter_.SetPosition(position->position, 0.0);
279 state_ = STATE_READY_UNLOADED;
280 } else {
281 shooter_.SetPosition(
282 position->position + values.shooter_zeroing_speed*dt
283 values.shooter_zeroing_speed);
284 }
285
286 output->latch_piston = false;
287 output->brake_piston = false;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000288 break;
289 case STATE_READY_UNLOAD:
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000290 if (!goal->unload_requested) {
291 state_ = STATE_REQUEST_LOAD;
292 }
293
294 output->latch_piston = false;
295 output->brake_piston = false;
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000296 break;
297 }
298
joe2d92e852014-01-25 14:31:24 -0800299 if (position) {
joe93778a62014-02-15 13:22:14 -0800300 LOG(DEBUG, "pos: hall: absolute: %f\n",
301 //position->pos,
302 //position->hall_effect ? "true" : "false",
joe2d92e852014-01-25 14:31:24 -0800303 zeroed_joint_.absolute_position());
304 }
305
Ben Fredrickson1e512ff2014-02-15 21:36:52 +0000306 output->voltage = voltage;
joe2d92e852014-01-25 14:31:24 -0800307 status->done = ::std::abs(zeroed_joint_.absolute_position() - goal->goal) < 0.004;
308}
309
310} // namespace control_loops
311} // namespace frc971