blob: b6d3b2f379dea370ae0d246ae1fe282236e64446 [file] [log] [blame]
Austin Schuh3bb9a442014-02-02 16:01:45 -08001#include "frc971/control_loops/claw/claw.h"
2
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"
Austin Schuhcda86af2014-02-16 16:16:39 -080011#include "frc971/control_loops/claw/claw_motor_plant.h"
12
Austin Schuh3bb9a442014-02-02 16:01:45 -080013// Zeroing plan.
14// There are 2 types of zeros. Enabled and disabled ones.
15// Disabled ones are only valid during auto mode, and can be used to speed up
16// the enabled zero process. We need to re-zero during teleop in case the auto
17// zero was poor and causes us to miss all our shots.
18//
19// We need to be able to zero manually while disabled by moving the joint over
20// the zeros.
21// Zero on the down edge when disabled (gravity in the direction of motion)
22//
23// When enabled, zero on the up edge (gravity opposing the direction of motion)
24// The enabled sequence needs to work as follows. We can crash the claw if we
25// bring them too close to each other or too far from each other. The only safe
26// thing to do is to move them in unison.
27//
28// Start by moving them both towards the front of the bot to either find either
29// the middle hall effect on either jaw, or the front hall effect on the bottom
30// jaw. Any edge that isn't the desired edge will provide an approximate edge
31// location that can be used for the fine tuning step.
32// Once an edge is found on the front claw, move back the other way with both
33// claws until an edge is found for the other claw.
34// Now that we have an approximate zero, we can robustify the limits to keep
35// both claws safe. Then, we can move both claws to a position that is the
36// correct side of the zero and go zero.
37
38// Valid region plan.
39// Difference between the arms has a range, and the values of each arm has a range.
40// If a claw runs up against a static limit, don't let the goal change outside
41// the limit.
42// If a claw runs up against a movable limit, move both claws outwards to get
43// out of the condition.
44
45namespace frc971 {
46namespace control_loops {
47
Austin Schuhcda86af2014-02-16 16:16:39 -080048void ClawLimitedLoop::CapU() {
Austin Schuh4cb047f2014-02-16 21:10:19 -080049 uncapped_average_voltage_ = U(0, 0) + U(1, 0) / 2.0;
50 if (is_zeroing_) {
51 const frc971::constants::Values &values = constants::GetValues();
52 if (uncapped_average_voltage_ > values.claw.max_zeroing_voltage) {
53 const double difference =
54 uncapped_average_voltage_ - values.claw.max_zeroing_voltage;
55 U(0, 0) -= difference;
Austin Schuh4cb047f2014-02-16 21:10:19 -080056 } else if (uncapped_average_voltage_ < -values.claw.max_zeroing_voltage) {
57 const double difference =
58 -uncapped_average_voltage_ - values.claw.max_zeroing_voltage;
59 U(0, 0) += difference;
Austin Schuh4cb047f2014-02-16 21:10:19 -080060 }
61 }
62
63 double max_value =
64 ::std::max(::std::abs(U(0, 0)), ::std::abs(U(1, 0) + U(0, 0)));
65
Austin Schuhcda86af2014-02-16 16:16:39 -080066 if (max_value > 12.0) {
67 LOG(DEBUG, "Capping U because max is %f\n", max_value);
68 U = U * 12.0 / max_value;
69 LOG(DEBUG, "Capping U is now %f %f\n", U(0, 0), U(1, 0));
Austin Schuh4b7b5d02014-02-10 21:20:34 -080070 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -080071}
72
Austin Schuhcc0bf312014-02-09 00:39:29 -080073ClawMotor::ClawMotor(control_loops::ClawGroup *my_claw)
74 : aos::control_loops::ControlLoop<control_loops::ClawGroup>(my_claw),
Austin Schuh4b7b5d02014-02-10 21:20:34 -080075 has_top_claw_goal_(false),
76 top_claw_goal_(0.0),
Austin Schuhcda86af2014-02-16 16:16:39 -080077 top_claw_(this),
Austin Schuh4b7b5d02014-02-10 21:20:34 -080078 has_bottom_claw_goal_(false),
79 bottom_claw_goal_(0.0),
Austin Schuhcda86af2014-02-16 16:16:39 -080080 bottom_claw_(this),
81 claw_(MakeClawLoop()),
Ben Fredrickson9b388422014-02-13 06:15:31 +000082 was_enabled_(false),
Austin Schuh4cb047f2014-02-16 21:10:19 -080083 doing_calibration_fine_tune_(false),
Austin Schuhe7f90d12014-02-17 00:48:25 -080084 capped_goal_(false),
85 mode_(UNKNOWN_LOCATION) {}
Austin Schuh3bb9a442014-02-02 16:01:45 -080086
Austin Schuh4b7b5d02014-02-10 21:20:34 -080087const int ZeroedStateFeedbackLoop::kZeroingMaxVoltage;
Austin Schuh3bb9a442014-02-02 16:01:45 -080088
Austin Schuhf9286cd2014-02-11 00:51:09 -080089bool ZeroedStateFeedbackLoop::GetPositionOfEdge(
Austin Schuhd27931c2014-02-16 19:18:20 -080090 const constants::Values::Claws::Claw &claw_values, double *edge_encoder,
Austin Schuhf9286cd2014-02-11 00:51:09 -080091 double *edge_angle) {
92
93 // TODO(austin): Validate that the hall effect edge makes sense.
94 // We must now be on the side of the edge that we expect to be, and the
95 // encoder must have been on either side of the edge before and after.
96
Austin Schuhcda86af2014-02-16 16:16:39 -080097 // TODO(austin): Compute the last off range min and max and compare the edge
98 // value to the middle of the range. This will be quite a bit more reliable.
99
Austin Schuhf9286cd2014-02-11 00:51:09 -0800100 if (front_hall_effect_posedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800101 if (posedge_value_ - last_encoder() < 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800102 *edge_angle = claw_values.front.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800103 LOG(INFO, "%s Posedge front upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800104 } else {
105 *edge_angle = claw_values.front.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800106 LOG(INFO, "%s Posedge front lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800107 }
108 *edge_encoder = posedge_value_;
109 return true;
110 }
111 if (front_hall_effect_negedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800112 if (negedge_value_ - last_encoder() > 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800113 *edge_angle = claw_values.front.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800114 LOG(INFO, "%s Negedge front upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800115 } else {
116 *edge_angle = claw_values.front.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800117 LOG(INFO, "%s Negedge front lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800118 }
119 *edge_encoder = negedge_value_;
120 return true;
121 }
122 if (calibration_hall_effect_posedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800123 if (posedge_value_ - last_encoder() < 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800124 *edge_angle = claw_values.calibration.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800125 LOG(INFO, "%s Posedge calibration upper edge -> %f\n", name_,
126 *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800127 } else {
128 *edge_angle = claw_values.calibration.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800129 LOG(INFO, "%s Posedge calibration lower edge -> %f\n", name_,
130 *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800131 }
132 *edge_encoder = posedge_value_;
133 return true;
134 }
135 if (calibration_hall_effect_negedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800136 if (negedge_value_ - last_encoder() > 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800137 *edge_angle = claw_values.calibration.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800138 LOG(INFO, "%s Negedge calibration upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800139 } else {
140 *edge_angle = claw_values.calibration.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800141 LOG(INFO, "%s Negedge calibration lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800142 }
143 *edge_encoder = negedge_value_;
144 return true;
145 }
146 if (back_hall_effect_posedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800147 if (posedge_value_ - last_encoder() < 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800148 *edge_angle = claw_values.back.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800149 LOG(INFO, "%s Posedge back upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800150 } else {
151 *edge_angle = claw_values.back.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800152 LOG(INFO, "%s Posedge back lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800153 }
154 *edge_encoder = posedge_value_;
155 return true;
156 }
157 if (back_hall_effect_negedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800158 if (negedge_value_ - last_encoder() > 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800159 *edge_angle = claw_values.back.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800160 LOG(INFO, "%s Negedge back upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800161 } else {
162 *edge_angle = claw_values.back.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800163 LOG(INFO, "%s Negedge back lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800164 }
165 *edge_encoder = negedge_value_;
166 return true;
167 }
168 return false;
169}
170
Austin Schuhcda86af2014-02-16 16:16:39 -0800171void TopZeroedStateFeedbackLoop::SetCalibration(double edge_encoder,
172 double edge_angle) {
173 double old_offset = offset_;
174 offset_ = edge_angle - edge_encoder;
175 const double doffset = offset_ - old_offset;
176 motor_->ChangeTopOffset(doffset);
177}
178
179void BottomZeroedStateFeedbackLoop::SetCalibration(double edge_encoder,
180 double edge_angle) {
181 double old_offset = offset_;
182 offset_ = edge_angle - edge_encoder;
183 const double doffset = offset_ - old_offset;
184 motor_->ChangeBottomOffset(doffset);
185}
186
187void ClawMotor::ChangeTopOffset(double doffset) {
188 claw_.ChangeTopOffset(doffset);
189 if (has_top_claw_goal_) {
190 top_claw_goal_ += doffset;
191 }
192}
193
194void ClawMotor::ChangeBottomOffset(double doffset) {
195 claw_.ChangeBottomOffset(doffset);
196 if (has_bottom_claw_goal_) {
197 bottom_claw_goal_ += doffset;
198 }
199}
200
201void ClawLimitedLoop::ChangeTopOffset(double doffset) {
202 Y_(1, 0) += doffset;
203 X_hat(1, 0) += doffset;
204 LOG(INFO, "Changing top offset by %f\n", doffset);
205}
206void ClawLimitedLoop::ChangeBottomOffset(double doffset) {
207 Y_(0, 0) += doffset;
208 X_hat(0, 0) += doffset;
209 X_hat(1, 0) -= doffset;
210 LOG(INFO, "Changing bottom offset by %f\n", doffset);
211}
212
Austin Schuhe7f90d12014-02-17 00:48:25 -0800213bool ClawMotor::is_ready() const {
214 return (
215 (top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED &&
216 bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED) ||
217 (::aos::robot_state->autonomous &&
218 ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
219 top_claw_.zeroing_state() ==
220 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION) &&
221 (bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
222 bottom_claw_.zeroing_state() ==
223 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION))));
224}
225
226bool ClawMotor::is_zeroing() const { return !is_ready(); }
227
Austin Schuh3bb9a442014-02-02 16:01:45 -0800228// Positive angle is up, and positive power is up.
Austin Schuhcc0bf312014-02-09 00:39:29 -0800229void ClawMotor::RunIteration(const control_loops::ClawGroup::Goal *goal,
230 const control_loops::ClawGroup::Position *position,
231 control_loops::ClawGroup::Output *output,
Austin Schuh3bb9a442014-02-02 16:01:45 -0800232 ::aos::control_loops::Status *status) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800233 constexpr double dt = 0.01;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800234
235 // Disable the motors now so that all early returns will return with the
236 // motors disabled.
237 if (output) {
238 output->top_claw_voltage = 0;
239 output->bottom_claw_voltage = 0;
240 output->intake_voltage = 0;
241 }
242
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800243 // TODO(austin): Handle the disabled state and the disabled -> enabled
Austin Schuhcda86af2014-02-16 16:16:39 -0800244 // transition in all of these states.
245 // TODO(austin): Handle zeroing while disabled correctly (only use a single
246 // edge and direction when zeroing.)
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800247
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800248 if (::aos::robot_state.get() == nullptr) {
249 return;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800250 }
251
Austin Schuhf9286cd2014-02-11 00:51:09 -0800252 const frc971::constants::Values &values = constants::GetValues();
253
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800254 if (position) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800255 Eigen::Matrix<double, 2, 1> Y;
256 Y << position->bottom.position + bottom_claw_.offset(),
257 position->top.position + top_claw_.offset();
258 claw_.Correct(Y);
259
Austin Schuhf9286cd2014-02-11 00:51:09 -0800260 top_claw_.SetPositionValues(position->top);
261 bottom_claw_.SetPositionValues(position->bottom);
262
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800263 if (!has_top_claw_goal_) {
264 has_top_claw_goal_ = true;
Austin Schuhcda86af2014-02-16 16:16:39 -0800265 top_claw_goal_ = top_claw_.absolute_position();
Austin Schuhe7f90d12014-02-17 00:48:25 -0800266 initial_separation_ =
Austin Schuhcda86af2014-02-16 16:16:39 -0800267 top_claw_.absolute_position() - bottom_claw_.absolute_position();
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800268 }
269 if (!has_bottom_claw_goal_) {
270 has_bottom_claw_goal_ = true;
Austin Schuhcda86af2014-02-16 16:16:39 -0800271 bottom_claw_goal_ = bottom_claw_.absolute_position();
Austin Schuhe7f90d12014-02-17 00:48:25 -0800272 initial_separation_ =
Austin Schuhcda86af2014-02-16 16:16:39 -0800273 top_claw_.absolute_position() - bottom_claw_.absolute_position();
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800274 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800275 LOG(DEBUG, "Claw position is (top: %f bottom: %f\n",
276 top_claw_.absolute_position(), bottom_claw_.absolute_position());
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800277 }
278
279 bool autonomous = ::aos::robot_state->autonomous;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800280 bool enabled = ::aos::robot_state->enabled;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800281
282 if ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED &&
283 bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED) ||
284 (autonomous &&
285 ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
286 top_claw_.zeroing_state() ==
287 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION) &&
288 (bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
289 bottom_claw_.zeroing_state() ==
290 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION)))) {
291 // Ready to use the claw.
292 // Limit the goals here.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800293 bottom_claw_goal_ = goal->bottom_angle;
294 top_claw_goal_ = goal->bottom_angle + goal->seperation_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800295 has_bottom_claw_goal_ = true;
296 has_top_claw_goal_ = true;
297 doing_calibration_fine_tune_ = false;
298
Austin Schuhe7f90d12014-02-17 00:48:25 -0800299 mode_ = READY;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800300 } else if (top_claw_.zeroing_state() !=
301 ZeroedStateFeedbackLoop::UNKNOWN_POSITION &&
302 bottom_claw_.zeroing_state() !=
303 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
304 // Time to fine tune the zero.
305 // Limit the goals here.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800306 // TODO(austin): Handle disabled state here.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800307 if (bottom_claw_.zeroing_state() != ZeroedStateFeedbackLoop::CALIBRATED) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800308 // always get the bottom claw to calibrated first
309 LOG(DEBUG, "Calibrating the bottom of the claw\n");
310 if (!doing_calibration_fine_tune_) {
311 if (::std::abs(bottom_absolute_position() -
Austin Schuhd27931c2014-02-16 19:18:20 -0800312 values.claw.start_fine_tune_pos) <
313 values.claw.claw_unimportant_epsilon) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800314 doing_calibration_fine_tune_ = true;
Austin Schuhd27931c2014-02-16 19:18:20 -0800315 bottom_claw_goal_ += values.claw.claw_zeroing_speed * dt;
Austin Schuhcda86af2014-02-16 16:16:39 -0800316 LOG(DEBUG, "Ready to fine tune the bottom\n");
Austin Schuhe7f90d12014-02-17 00:48:25 -0800317 mode_ = FINE_TUNE_BOTTOM;
Austin Schuhcda86af2014-02-16 16:16:39 -0800318 } else {
319 // send bottom to zeroing start
Austin Schuhd27931c2014-02-16 19:18:20 -0800320 bottom_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuhcda86af2014-02-16 16:16:39 -0800321 LOG(DEBUG, "Going to the start position for the bottom\n");
Austin Schuhe7f90d12014-02-17 00:48:25 -0800322 mode_ = PREP_FINE_TUNE_BOTTOM;
Austin Schuhcda86af2014-02-16 16:16:39 -0800323 }
324 } else {
Austin Schuhe7f90d12014-02-17 00:48:25 -0800325 mode_ = FINE_TUNE_BOTTOM;
Austin Schuhd27931c2014-02-16 19:18:20 -0800326 bottom_claw_goal_ += values.claw.claw_zeroing_speed * dt;
Austin Schuhcda86af2014-02-16 16:16:39 -0800327 if (top_claw_.front_hall_effect() || top_claw_.back_hall_effect() ||
328 bottom_claw_.front_hall_effect() ||
329 bottom_claw_.back_hall_effect()) {
330 // We shouldn't hit a limit, but if we do, go back to the zeroing
331 // point and try again.
332 doing_calibration_fine_tune_ = false;
Austin Schuhd27931c2014-02-16 19:18:20 -0800333 bottom_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuhcda86af2014-02-16 16:16:39 -0800334 LOG(DEBUG, "Found a limit, starting over.\n");
Austin Schuhe7f90d12014-02-17 00:48:25 -0800335 mode_ = PREP_FINE_TUNE_BOTTOM;
Austin Schuhcda86af2014-02-16 16:16:39 -0800336 }
Austin Schuh288c8c32014-02-16 17:20:17 -0800337
Austin Schuhcda86af2014-02-16 16:16:39 -0800338 if (bottom_claw_.calibration_hall_effect()) {
Austin Schuh288c8c32014-02-16 17:20:17 -0800339 if (bottom_claw_.calibration_hall_effect_posedge_count_changed() &&
340 position) {
341 // do calibration
342 bottom_claw_.SetCalibration(
343 position->bottom.posedge_value,
Austin Schuhd27931c2014-02-16 19:18:20 -0800344 values.claw.lower_claw.calibration.lower_angle);
Austin Schuh288c8c32014-02-16 17:20:17 -0800345 bottom_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
346 // calibrated so we are done fine tuning bottom
347 doing_calibration_fine_tune_ = false;
348 LOG(DEBUG, "Calibrated the bottom correctly!\n");
349 } else {
350 doing_calibration_fine_tune_ = false;
Austin Schuhd27931c2014-02-16 19:18:20 -0800351 bottom_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuhe7f90d12014-02-17 00:48:25 -0800352 mode_ = PREP_FINE_TUNE_BOTTOM;
Austin Schuh288c8c32014-02-16 17:20:17 -0800353 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800354 } else {
355 LOG(DEBUG, "Fine tuning\n");
356 }
357 }
358 // now set the top claw to track
359
Austin Schuhd27931c2014-02-16 19:18:20 -0800360 top_claw_goal_ = bottom_claw_goal_ + values.claw.claw_zeroing_separation;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800361 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800362 // bottom claw must be calibrated, start on the top
363 if (!doing_calibration_fine_tune_) {
Austin Schuhd27931c2014-02-16 19:18:20 -0800364 if (::std::abs(top_absolute_position() -
365 values.claw.start_fine_tune_pos) <
366 values.claw.claw_unimportant_epsilon) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800367 doing_calibration_fine_tune_ = true;
Austin Schuhd27931c2014-02-16 19:18:20 -0800368 top_claw_goal_ += values.claw.claw_zeroing_speed * dt;
Austin Schuhcda86af2014-02-16 16:16:39 -0800369 LOG(DEBUG, "Ready to fine tune the top\n");
Austin Schuhe7f90d12014-02-17 00:48:25 -0800370 mode_ = FINE_TUNE_TOP;
Austin Schuhcda86af2014-02-16 16:16:39 -0800371 } else {
372 // send top to zeroing start
Austin Schuhd27931c2014-02-16 19:18:20 -0800373 top_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuhcda86af2014-02-16 16:16:39 -0800374 LOG(DEBUG, "Going to the start position for the top\n");
Austin Schuhe7f90d12014-02-17 00:48:25 -0800375 mode_ = PREP_FINE_TUNE_TOP;
Austin Schuhcda86af2014-02-16 16:16:39 -0800376 }
377 } else {
Austin Schuhe7f90d12014-02-17 00:48:25 -0800378 mode_ = FINE_TUNE_TOP;
Austin Schuhd27931c2014-02-16 19:18:20 -0800379 top_claw_goal_ += values.claw.claw_zeroing_speed * dt;
Austin Schuhcda86af2014-02-16 16:16:39 -0800380 if (top_claw_.front_hall_effect() || top_claw_.back_hall_effect() ||
381 bottom_claw_.front_hall_effect() ||
382 bottom_claw_.back_hall_effect()) {
383 // this should not happen, but now we know it won't
384 doing_calibration_fine_tune_ = false;
Austin Schuhd27931c2014-02-16 19:18:20 -0800385 top_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuhcda86af2014-02-16 16:16:39 -0800386 LOG(DEBUG, "Found a limit, starting over.\n");
Austin Schuhe7f90d12014-02-17 00:48:25 -0800387 mode_ = PREP_FINE_TUNE_TOP;
Austin Schuhcda86af2014-02-16 16:16:39 -0800388 }
389 if (top_claw_.calibration_hall_effect()) {
Austin Schuh288c8c32014-02-16 17:20:17 -0800390 if (top_claw_.calibration_hall_effect_posedge_count_changed() &&
391 position) {
392 // do calibration
Austin Schuhd27931c2014-02-16 19:18:20 -0800393 top_claw_.SetCalibration(
394 position->top.posedge_value,
395 values.claw.upper_claw.calibration.lower_angle);
Austin Schuh288c8c32014-02-16 17:20:17 -0800396 top_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
Austin Schuhe7f90d12014-02-17 00:48:25 -0800397 // calibrated so we are done fine tuning top
Austin Schuh288c8c32014-02-16 17:20:17 -0800398 doing_calibration_fine_tune_ = false;
399 LOG(DEBUG, "Calibrated the top correctly!\n");
400 } else {
401 doing_calibration_fine_tune_ = false;
Austin Schuhd27931c2014-02-16 19:18:20 -0800402 top_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuhe7f90d12014-02-17 00:48:25 -0800403 mode_ = PREP_FINE_TUNE_TOP;
Austin Schuh288c8c32014-02-16 17:20:17 -0800404 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800405 }
406 }
407 // now set the bottom claw to track
Austin Schuhd27931c2014-02-16 19:18:20 -0800408 bottom_claw_goal_ = top_claw_goal_ - values.claw.claw_zeroing_separation;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800409 }
410 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800411 doing_calibration_fine_tune_ = false;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800412 if (!was_enabled_ && enabled) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800413 if (position) {
414 top_claw_goal_ = position->top.position;
415 bottom_claw_goal_ = position->bottom.position;
Austin Schuhe7f90d12014-02-17 00:48:25 -0800416 initial_separation_ =
Austin Schuhcda86af2014-02-16 16:16:39 -0800417 position->top.position - position->bottom.position;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800418 } else {
419 has_top_claw_goal_ = false;
420 has_bottom_claw_goal_ = false;
421 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800422 }
Austin Schuhf9286cd2014-02-11 00:51:09 -0800423
424 // TODO(austin): Limit the goals here.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800425
Austin Schuh4cb047f2014-02-16 21:10:19 -0800426 if ((bottom_claw_.zeroing_state() !=
427 ZeroedStateFeedbackLoop::UNKNOWN_POSITION ||
428 bottom_claw_.front_hall_effect() || top_claw_.front_hall_effect()) &&
429 !top_claw_.back_hall_effect() && !bottom_claw_.back_hall_effect()) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800430 if (enabled) {
431 // Time to slowly move back up to find any position to narrow down the
432 // zero.
Austin Schuhd27931c2014-02-16 19:18:20 -0800433 top_claw_goal_ += values.claw.claw_zeroing_off_speed * dt;
434 bottom_claw_goal_ += values.claw.claw_zeroing_off_speed * dt;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800435 // TODO(austin): Goal velocity too!
Austin Schuhcda86af2014-02-16 16:16:39 -0800436 LOG(DEBUG, "Bottom is known.\n");
Austin Schuhf9286cd2014-02-11 00:51:09 -0800437 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800438 } else {
439 // We don't know where either claw is. Slowly start moving down to find
440 // any hall effect.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800441 if (enabled) {
Austin Schuhd27931c2014-02-16 19:18:20 -0800442 top_claw_goal_ -= values.claw.claw_zeroing_off_speed * dt;
443 bottom_claw_goal_ -= values.claw.claw_zeroing_off_speed * dt;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800444 // TODO(austin): Goal velocity too!
Austin Schuhcda86af2014-02-16 16:16:39 -0800445 LOG(DEBUG, "Both are unknown.\n");
Austin Schuhf9286cd2014-02-11 00:51:09 -0800446 }
447 }
448
449 if (enabled) {
450 top_claw_.SetCalibrationOnEdge(
Austin Schuhd27931c2014-02-16 19:18:20 -0800451 values.claw.upper_claw, ZeroedStateFeedbackLoop::APPROXIMATE_CALIBRATION);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800452 bottom_claw_.SetCalibrationOnEdge(
Austin Schuhd27931c2014-02-16 19:18:20 -0800453 values.claw.lower_claw, ZeroedStateFeedbackLoop::APPROXIMATE_CALIBRATION);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800454 } else {
455 top_claw_.SetCalibrationOnEdge(
Austin Schuhd27931c2014-02-16 19:18:20 -0800456 values.claw.upper_claw, ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800457 bottom_claw_.SetCalibrationOnEdge(
Austin Schuhd27931c2014-02-16 19:18:20 -0800458 values.claw.lower_claw, ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800459 }
Austin Schuhe7f90d12014-02-17 00:48:25 -0800460 mode_ = UNKNOWN_LOCATION;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800461 }
462
Austin Schuhf9286cd2014-02-11 00:51:09 -0800463 if (has_top_claw_goal_ && has_bottom_claw_goal_) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800464 claw_.R << bottom_claw_goal_, top_claw_goal_ - bottom_claw_goal_, 0, 0;
465 double separation = -971;
466 if (position != nullptr) {
467 separation = position->top.position - position->bottom.position;
468 }
469 LOG(DEBUG, "Goal is %f (bottom) %f, separation is %f\n", claw_.R(0, 0),
470 claw_.R(1, 0), separation);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800471
Austin Schuh4cb047f2014-02-16 21:10:19 -0800472 // Only cap power when one of the halves of the claw is unknown.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800473 claw_.set_is_zeroing(mode_ == UNKNOWN_LOCATION || mode_ == FINE_TUNE_TOP ||
474 mode_ == FINE_TUNE_BOTTOM);
Austin Schuhcda86af2014-02-16 16:16:39 -0800475 claw_.Update(output == nullptr);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800476 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800477 claw_.Update(true);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800478 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800479
Austin Schuh4cb047f2014-02-16 21:10:19 -0800480 capped_goal_ = false;
Austin Schuhe7f90d12014-02-17 00:48:25 -0800481 switch (mode_) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800482 case READY:
Austin Schuhe7f90d12014-02-17 00:48:25 -0800483 case PREP_FINE_TUNE_TOP:
484 case PREP_FINE_TUNE_BOTTOM:
Austin Schuhcda86af2014-02-16 16:16:39 -0800485 break;
Austin Schuhe7f90d12014-02-17 00:48:25 -0800486 case FINE_TUNE_BOTTOM:
487 case FINE_TUNE_TOP:
Austin Schuh4cb047f2014-02-16 21:10:19 -0800488 case UNKNOWN_LOCATION: {
489 if (claw_.uncapped_average_voltage() > values.claw.max_zeroing_voltage) {
490 double dx = (claw_.uncapped_average_voltage() -
491 values.claw.max_zeroing_voltage) /
492 claw_.K(0, 0);
493 bottom_claw_goal_ -= dx;
494 top_claw_goal_ -= dx;
Austin Schuhcda86af2014-02-16 16:16:39 -0800495 capped_goal_ = true;
Austin Schuh4cb047f2014-02-16 21:10:19 -0800496 LOG(DEBUG, "Moving the goal by %f to prevent windup\n", dx);
Austin Schuhe7f90d12014-02-17 00:48:25 -0800497 LOG(DEBUG, "Uncapped is %f, max is %f, difference is %f\n",
498 claw_.uncapped_average_voltage(), values.claw.max_zeroing_voltage,
499 (claw_.uncapped_average_voltage() -
500 values.claw.max_zeroing_voltage));
Austin Schuh4cb047f2014-02-16 21:10:19 -0800501 } else if (claw_.uncapped_average_voltage() <
502 -values.claw.max_zeroing_voltage) {
503 double dx = (claw_.uncapped_average_voltage() +
504 values.claw.max_zeroing_voltage) /
505 claw_.K(0, 0);
506 bottom_claw_goal_ -= dx;
507 top_claw_goal_ -= dx;
Austin Schuhcda86af2014-02-16 16:16:39 -0800508 capped_goal_ = true;
Austin Schuh4cb047f2014-02-16 21:10:19 -0800509 LOG(DEBUG, "Moving the goal by %f to prevent windup\n", dx);
Austin Schuhcda86af2014-02-16 16:16:39 -0800510 }
Austin Schuh4cb047f2014-02-16 21:10:19 -0800511 } break;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800512 }
513
514 if (output) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800515 output->top_claw_voltage = claw_.U(1, 0) + claw_.U(0, 0);
516 output->bottom_claw_voltage = claw_.U(0, 0);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800517 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800518 status->done = false;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800519
520 was_enabled_ = ::aos::robot_state->enabled;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800521}
522
523} // namespace control_loops
524} // namespace frc971