blob: 17a7fbc48209f4ab7f81d7f1da63bb7ca4c9d56d [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() {
49 double max_value = ::std::max(::std::abs(U(0, 0)), ::std::abs(U(1, 0) + U(0, 0)));
50 if (max_value > 12.0) {
51 LOG(DEBUG, "Capping U because max is %f\n", max_value);
52 U = U * 12.0 / max_value;
53 LOG(DEBUG, "Capping U is now %f %f\n", U(0, 0), U(1, 0));
Austin Schuh4b7b5d02014-02-10 21:20:34 -080054 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -080055}
56
Austin Schuhcc0bf312014-02-09 00:39:29 -080057ClawMotor::ClawMotor(control_loops::ClawGroup *my_claw)
58 : aos::control_loops::ControlLoop<control_loops::ClawGroup>(my_claw),
Austin Schuh4b7b5d02014-02-10 21:20:34 -080059 has_top_claw_goal_(false),
60 top_claw_goal_(0.0),
Austin Schuhcda86af2014-02-16 16:16:39 -080061 top_claw_(this),
Austin Schuh4b7b5d02014-02-10 21:20:34 -080062 has_bottom_claw_goal_(false),
63 bottom_claw_goal_(0.0),
Austin Schuhcda86af2014-02-16 16:16:39 -080064 bottom_claw_(this),
65 claw_(MakeClawLoop()),
Ben Fredrickson9b388422014-02-13 06:15:31 +000066 was_enabled_(false),
67 doing_calibration_fine_tune_(false) {}
Austin Schuh3bb9a442014-02-02 16:01:45 -080068
Austin Schuh4b7b5d02014-02-10 21:20:34 -080069const int ZeroedStateFeedbackLoop::kZeroingMaxVoltage;
Austin Schuh3bb9a442014-02-02 16:01:45 -080070
Austin Schuhf9286cd2014-02-11 00:51:09 -080071bool ZeroedStateFeedbackLoop::GetPositionOfEdge(
72 const constants::Values::Claw &claw_values, double *edge_encoder,
73 double *edge_angle) {
74
75 // TODO(austin): Validate that the hall effect edge makes sense.
76 // We must now be on the side of the edge that we expect to be, and the
77 // encoder must have been on either side of the edge before and after.
78
Austin Schuhcda86af2014-02-16 16:16:39 -080079 // TODO(austin): Compute the last off range min and max and compare the edge
80 // value to the middle of the range. This will be quite a bit more reliable.
81
Austin Schuhf9286cd2014-02-11 00:51:09 -080082 if (front_hall_effect_posedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -080083 if (posedge_value_ - last_encoder() < 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -080084 *edge_angle = claw_values.front.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -080085 LOG(INFO, "%s Posedge front upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -080086 } else {
87 *edge_angle = claw_values.front.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -080088 LOG(INFO, "%s Posedge front lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -080089 }
90 *edge_encoder = posedge_value_;
91 return true;
92 }
93 if (front_hall_effect_negedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -080094 LOG(INFO, "%s Value is %f last is %f\n", name_, negedge_value_, last_encoder());
95 if (negedge_value_ - last_encoder() > 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -080096 *edge_angle = claw_values.front.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -080097 LOG(INFO, "%s Negedge front upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -080098 } else {
99 *edge_angle = claw_values.front.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800100 LOG(INFO, "%s Negedge front lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800101 }
102 *edge_encoder = negedge_value_;
103 return true;
104 }
105 if (calibration_hall_effect_posedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800106 if (posedge_value_ - last_encoder() < 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800107 *edge_angle = claw_values.calibration.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800108 LOG(INFO, "%s Posedge calibration upper edge -> %f\n", name_,
109 *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800110 } else {
111 *edge_angle = claw_values.calibration.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800112 LOG(INFO, "%s Posedge calibration lower edge -> %f\n", name_,
113 *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800114 }
115 *edge_encoder = posedge_value_;
116 return true;
117 }
118 if (calibration_hall_effect_negedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800119 if (negedge_value_ - last_encoder() > 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800120 *edge_angle = claw_values.calibration.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800121 LOG(INFO, "%s Negedge calibration upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800122 } else {
123 *edge_angle = claw_values.calibration.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800124 LOG(INFO, "%s Negedge calibration lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800125 }
126 *edge_encoder = negedge_value_;
127 return true;
128 }
129 if (back_hall_effect_posedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800130 if (posedge_value_ - last_encoder() < 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800131 *edge_angle = claw_values.back.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800132 LOG(INFO, "%s Posedge back upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800133 } else {
134 *edge_angle = claw_values.back.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800135 LOG(INFO, "%s Posedge back lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800136 }
137 *edge_encoder = posedge_value_;
138 return true;
139 }
140 if (back_hall_effect_negedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800141 if (negedge_value_ - last_encoder() > 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800142 *edge_angle = claw_values.back.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800143 LOG(INFO, "%s Negedge back upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800144 } else {
145 *edge_angle = claw_values.back.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800146 LOG(INFO, "%s Negedge back lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800147 }
148 *edge_encoder = negedge_value_;
149 return true;
150 }
151 return false;
152}
153
Austin Schuhcda86af2014-02-16 16:16:39 -0800154void TopZeroedStateFeedbackLoop::SetCalibration(double edge_encoder,
155 double edge_angle) {
156 double old_offset = offset_;
157 offset_ = edge_angle - edge_encoder;
158 const double doffset = offset_ - old_offset;
159 motor_->ChangeTopOffset(doffset);
160}
161
162void BottomZeroedStateFeedbackLoop::SetCalibration(double edge_encoder,
163 double edge_angle) {
164 double old_offset = offset_;
165 offset_ = edge_angle - edge_encoder;
166 const double doffset = offset_ - old_offset;
167 motor_->ChangeBottomOffset(doffset);
168}
169
170void ClawMotor::ChangeTopOffset(double doffset) {
171 claw_.ChangeTopOffset(doffset);
172 if (has_top_claw_goal_) {
173 top_claw_goal_ += doffset;
174 }
175}
176
177void ClawMotor::ChangeBottomOffset(double doffset) {
178 claw_.ChangeBottomOffset(doffset);
179 if (has_bottom_claw_goal_) {
180 bottom_claw_goal_ += doffset;
181 }
182}
183
184void ClawLimitedLoop::ChangeTopOffset(double doffset) {
185 Y_(1, 0) += doffset;
186 X_hat(1, 0) += doffset;
187 LOG(INFO, "Changing top offset by %f\n", doffset);
188}
189void ClawLimitedLoop::ChangeBottomOffset(double doffset) {
190 Y_(0, 0) += doffset;
191 X_hat(0, 0) += doffset;
192 X_hat(1, 0) -= doffset;
193 LOG(INFO, "Changing bottom offset by %f\n", doffset);
194}
joe7376ff52014-02-16 18:28:42 -0800195//void FixClawPos(double * bottom_goal, double * top_goal, frc971::constants::Values &values) {
196// //first update position based on angle limit
197//
198// double goal_angle = *top_goal - *bottom_goal;
199// if (goal_angle > values.lower_claw.front.upper_angle) {
200// *bottom_goal += goal_angle - values.lower_claw.front.upper_angle;
201// }
202// if (goal_angle < values.lower_claw.front.lower_angle) {
203// *bottom_goal += goal_angle - values.lower_claw.front.lower_angle;
204// }
205//
206// //now move both goals in unison
207// if (*bottom_goal < values.bottom.lower_limit) {
208// *bottom_goal += *bottom_goal - values.lower_claw.lower_limit;
209// *top_goal += *bottom_goal - values.bottom.lower_limit;
210// }
211// if (*bottom_goal > values.bottom.upper_limit) {
212// *bottom_goal -= *bottom_goal - values.bottom.upper_limit;
213// *top_goal -= *bottom_goal - values.bottom.upper_limit;
214// }
215//
216// if (*top_goal < values.bottom.lower_limit) {
217// *top_goal += *top_goal - values.bottom.lower_limit;
218// *bottom_goal += *top_goal - values.bottom.lower_limit;
219// }
220// if (*top_goal > values.top.upper_limit) {
221// *top_goal -= *top_goal - values.top.upper_limit;
222// *bottom_goal -= *top_goal - values.top.upper_limit;
223// }
224//}
225
Austin Schuhcda86af2014-02-16 16:16:39 -0800226
Austin Schuh3bb9a442014-02-02 16:01:45 -0800227// Positive angle is up, and positive power is up.
Austin Schuhcc0bf312014-02-09 00:39:29 -0800228void ClawMotor::RunIteration(const control_loops::ClawGroup::Goal *goal,
229 const control_loops::ClawGroup::Position *position,
230 control_loops::ClawGroup::Output *output,
Austin Schuh3bb9a442014-02-02 16:01:45 -0800231 ::aos::control_loops::Status *status) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800232 constexpr double dt = 0.01;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800233
234 // Disable the motors now so that all early returns will return with the
235 // motors disabled.
236 if (output) {
237 output->top_claw_voltage = 0;
238 output->bottom_claw_voltage = 0;
239 output->intake_voltage = 0;
240 }
241
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800242 // TODO(austin): Handle the disabled state and the disabled -> enabled
Austin Schuhcda86af2014-02-16 16:16:39 -0800243 // transition in all of these states.
244 // TODO(austin): Handle zeroing while disabled correctly (only use a single
245 // edge and direction when zeroing.)
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800246
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800247 if (::aos::robot_state.get() == nullptr) {
248 return;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800249 }
250
Austin Schuhf9286cd2014-02-11 00:51:09 -0800251 const frc971::constants::Values &values = constants::GetValues();
252
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800253 if (position) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800254 Eigen::Matrix<double, 2, 1> Y;
255 Y << position->bottom.position + bottom_claw_.offset(),
256 position->top.position + top_claw_.offset();
257 claw_.Correct(Y);
258
Austin Schuhf9286cd2014-02-11 00:51:09 -0800259 top_claw_.SetPositionValues(position->top);
260 bottom_claw_.SetPositionValues(position->bottom);
261
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800262 if (!has_top_claw_goal_) {
263 has_top_claw_goal_ = true;
Austin Schuhcda86af2014-02-16 16:16:39 -0800264 top_claw_goal_ = top_claw_.absolute_position();
265 initial_seperation_ =
266 top_claw_.absolute_position() - bottom_claw_.absolute_position();
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800267 }
268 if (!has_bottom_claw_goal_) {
269 has_bottom_claw_goal_ = true;
Austin Schuhcda86af2014-02-16 16:16:39 -0800270 bottom_claw_goal_ = bottom_claw_.absolute_position();
271 initial_seperation_ =
272 top_claw_.absolute_position() - bottom_claw_.absolute_position();
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800273 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800274 LOG(DEBUG, "Claw position is (top: %f bottom: %f\n",
275 top_claw_.absolute_position(), bottom_claw_.absolute_position());
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800276 }
277
278 bool autonomous = ::aos::robot_state->autonomous;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800279 bool enabled = ::aos::robot_state->enabled;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800280
Austin Schuhcda86af2014-02-16 16:16:39 -0800281 enum CalibrationMode {
282 READY,
283 FINE_TUNE,
284 UNKNOWN_LOCATION
285 };
286
287 CalibrationMode mode;
288
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800289 if ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED &&
290 bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED) ||
291 (autonomous &&
292 ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
293 top_claw_.zeroing_state() ==
294 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION) &&
295 (bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
296 bottom_claw_.zeroing_state() ==
297 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION)))) {
298 // Ready to use the claw.
299 // Limit the goals here.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800300 bottom_claw_goal_ = goal->bottom_angle;
301 top_claw_goal_ = goal->bottom_angle + goal->seperation_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800302 has_bottom_claw_goal_ = true;
303 has_top_claw_goal_ = true;
304 doing_calibration_fine_tune_ = false;
305
306 mode = READY;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800307 } else if (top_claw_.zeroing_state() !=
308 ZeroedStateFeedbackLoop::UNKNOWN_POSITION &&
309 bottom_claw_.zeroing_state() !=
310 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
311 // Time to fine tune the zero.
312 // Limit the goals here.
313 if (bottom_claw_.zeroing_state() != ZeroedStateFeedbackLoop::CALIBRATED) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800314 // always get the bottom claw to calibrated first
315 LOG(DEBUG, "Calibrating the bottom of the claw\n");
316 if (!doing_calibration_fine_tune_) {
317 if (::std::abs(bottom_absolute_position() -
318 values.start_fine_tune_pos) <
319 values.claw_unimportant_epsilon) {
320 doing_calibration_fine_tune_ = true;
321 bottom_claw_goal_ += values.claw_zeroing_speed * dt;
322 LOG(DEBUG, "Ready to fine tune the bottom\n");
323 } else {
324 // send bottom to zeroing start
325 bottom_claw_goal_ = values.start_fine_tune_pos;
326 LOG(DEBUG, "Going to the start position for the bottom\n");
327 }
328 } else {
329 bottom_claw_goal_ += values.claw_zeroing_speed * dt;
330 if (top_claw_.front_hall_effect() || top_claw_.back_hall_effect() ||
331 bottom_claw_.front_hall_effect() ||
332 bottom_claw_.back_hall_effect()) {
333 // We shouldn't hit a limit, but if we do, go back to the zeroing
334 // point and try again.
335 doing_calibration_fine_tune_ = false;
336 bottom_claw_goal_ = values.start_fine_tune_pos;
337 LOG(DEBUG, "Found a limit, starting over.\n");
338 }
Austin Schuh288c8c32014-02-16 17:20:17 -0800339
Austin Schuhcda86af2014-02-16 16:16:39 -0800340 if (bottom_claw_.calibration_hall_effect()) {
Austin Schuh288c8c32014-02-16 17:20:17 -0800341 if (bottom_claw_.calibration_hall_effect_posedge_count_changed() &&
342 position) {
343 // do calibration
344 bottom_claw_.SetCalibration(
345 position->bottom.posedge_value,
346 values.lower_claw.calibration.lower_angle);
347 bottom_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
348 // calibrated so we are done fine tuning bottom
349 doing_calibration_fine_tune_ = false;
350 LOG(DEBUG, "Calibrated the bottom correctly!\n");
351 } else {
352 doing_calibration_fine_tune_ = false;
353 bottom_claw_goal_ = values.start_fine_tune_pos;
354 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800355 } else {
356 LOG(DEBUG, "Fine tuning\n");
357 }
358 }
359 // now set the top claw to track
360
Austin Schuhcda86af2014-02-16 16:16:39 -0800361 top_claw_goal_ = bottom_claw_goal_ + values.claw_zeroing_separation;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800362 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800363 // bottom claw must be calibrated, start on the top
364 if (!doing_calibration_fine_tune_) {
365 if (::std::abs(top_absolute_position() - values.start_fine_tune_pos) <
366 values.claw_unimportant_epsilon) {
367 doing_calibration_fine_tune_ = true;
368 top_claw_goal_ += values.claw_zeroing_speed * dt;
369 LOG(DEBUG, "Ready to fine tune the top\n");
370 } else {
371 // send top to zeroing start
372 top_claw_goal_ = values.start_fine_tune_pos;
373 LOG(DEBUG, "Going to the start position for the top\n");
374 }
375 } else {
376 top_claw_goal_ += values.claw_zeroing_speed * dt;
377 if (top_claw_.front_hall_effect() || top_claw_.back_hall_effect() ||
378 bottom_claw_.front_hall_effect() ||
379 bottom_claw_.back_hall_effect()) {
380 // this should not happen, but now we know it won't
381 doing_calibration_fine_tune_ = false;
382 top_claw_goal_ = values.start_fine_tune_pos;
383 LOG(DEBUG, "Found a limit, starting over.\n");
384 }
385 if (top_claw_.calibration_hall_effect()) {
Austin Schuh288c8c32014-02-16 17:20:17 -0800386 if (top_claw_.calibration_hall_effect_posedge_count_changed() &&
387 position) {
388 // do calibration
389 top_claw_.SetCalibration(position->top.posedge_value,
390 values.upper_claw.calibration.lower_angle);
391 top_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
392 // calinrated so we are done fine tuning top
393 doing_calibration_fine_tune_ = false;
394 LOG(DEBUG, "Calibrated the top correctly!\n");
395 } else {
396 doing_calibration_fine_tune_ = false;
397 top_claw_goal_ = values.start_fine_tune_pos;
398 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800399 }
400 }
401 // now set the bottom claw to track
402 bottom_claw_goal_ = top_claw_goal_ - values.claw_zeroing_separation;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800403 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800404 mode = FINE_TUNE;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800405 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800406 doing_calibration_fine_tune_ = false;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800407 if (!was_enabled_ && enabled) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800408 if (position) {
409 top_claw_goal_ = position->top.position;
410 bottom_claw_goal_ = position->bottom.position;
Austin Schuhcda86af2014-02-16 16:16:39 -0800411 initial_seperation_ =
412 position->top.position - position->bottom.position;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800413 } else {
414 has_top_claw_goal_ = false;
415 has_bottom_claw_goal_ = false;
416 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800417 }
Austin Schuhf9286cd2014-02-11 00:51:09 -0800418
419 // TODO(austin): Limit the goals here.
420 // Need to prevent windup, limit voltage, deal with windup on only 1 claw,
421 // ...
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800422 if (top_claw_.zeroing_state() ==
423 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
424 }
425 if (bottom_claw_.zeroing_state() ==
426 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
427 }
428
429 if (bottom_claw_.zeroing_state() !=
430 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800431 if (enabled) {
432 // Time to slowly move back up to find any position to narrow down the
433 // zero.
434 top_claw_goal_ += values.claw_zeroing_off_speed * dt;
435 bottom_claw_goal_ += values.claw_zeroing_off_speed * dt;
436 // TODO(austin): Goal velocity too!
Austin Schuhcda86af2014-02-16 16:16:39 -0800437 LOG(DEBUG, "Bottom is known.\n");
Austin Schuhf9286cd2014-02-11 00:51:09 -0800438 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800439 } else {
440 // We don't know where either claw is. Slowly start moving down to find
441 // any hall effect.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800442 if (enabled) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800443 top_claw_goal_ -= values.claw_zeroing_off_speed * dt;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800444 bottom_claw_goal_ -= values.claw_zeroing_off_speed * dt;
445 // TODO(austin): Goal velocity too!
Austin Schuhcda86af2014-02-16 16:16:39 -0800446 LOG(DEBUG, "Both are unknown.\n");
Austin Schuhf9286cd2014-02-11 00:51:09 -0800447 }
448 }
449
450 if (enabled) {
451 top_claw_.SetCalibrationOnEdge(
452 values.upper_claw, ZeroedStateFeedbackLoop::APPROXIMATE_CALIBRATION);
453 bottom_claw_.SetCalibrationOnEdge(
454 values.lower_claw, ZeroedStateFeedbackLoop::APPROXIMATE_CALIBRATION);
455 } else {
456 top_claw_.SetCalibrationOnEdge(
457 values.upper_claw, ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
458 bottom_claw_.SetCalibrationOnEdge(
459 values.lower_claw, ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800460 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800461 mode = UNKNOWN_LOCATION;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800462 }
463
Austin Schuh288c8c32014-02-16 17:20:17 -0800464 // TODO(austin): Handle disabled properly everwhere... Restart and all that
465 // jazz.
466
467 // TODO(Joe): Write this.
joe7376ff52014-02-16 18:28:42 -0800468 // make sure this is possible phsically
469 // fix goals to make it possible
470 // break into function at some point?
471 //
472 //FixClawPos(&bottom_claw_goal_, &top_claw_goal_, values);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800473
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800474 // TODO(austin): ...
Austin Schuhf9286cd2014-02-11 00:51:09 -0800475 if (has_top_claw_goal_ && has_bottom_claw_goal_) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800476 claw_.R << bottom_claw_goal_, top_claw_goal_ - bottom_claw_goal_, 0, 0;
477 double separation = -971;
478 if (position != nullptr) {
479 separation = position->top.position - position->bottom.position;
480 }
481 LOG(DEBUG, "Goal is %f (bottom) %f, separation is %f\n", claw_.R(0, 0),
482 claw_.R(1, 0), separation);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800483
Austin Schuhcda86af2014-02-16 16:16:39 -0800484 claw_.Update(output == nullptr);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800485 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800486 claw_.Update(true);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800487 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800488
Austin Schuh288c8c32014-02-16 17:20:17 -0800489 (void) mode;
Austin Schuhcda86af2014-02-16 16:16:39 -0800490 /*
491 switch (mode) {
492 case READY:
493 break;
494 case FINE_TUNE:
495 break;
496 case UNKNOWN_LOCATION:
497 if (top_claw_->uncapped_voltage() > values.max_zeroing_voltage) {
498 double dx =
499 (top_claw_->uncapped_voltage() - values.max_zeroing_voltage) /
500 top_claw_->K(0, 0);
501 zeroing_position_ -= dx;
502 capped_goal_ = true;
503 } else if (top_claw_->uncapped_voltage() < -values.max_zeroing_voltage) {
504 double dx =
505 (top_claw_->uncapped_voltage() + values.max_zeroing_voltage) /
506 top_claw_->K(0, 0);
507 zeroing_position_ -= dx;
508 capped_goal_ = true;
509 }
510 break;
511 }
512 */
513
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800514 if (position) {
515 //LOG(DEBUG, "pos: %f hall: %s absolute: %f\n", position->top_position,
516 //position->top_calibration_hall_effect ? "true" : "false",
517 //zeroed_joint_.absolute_position());
Austin Schuh3bb9a442014-02-02 16:01:45 -0800518 }
519
520 if (output) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800521 output->top_claw_voltage = claw_.U(1, 0) + claw_.U(0, 0);
522 output->bottom_claw_voltage = claw_.U(0, 0);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800523 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800524 status->done = false;
525 //::std::abs(zeroed_joint_.absolute_position() - goal->bottom_angle -
526 //goal->seperation_angle) < 0.004;
527
528 was_enabled_ = ::aos::robot_state->enabled;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800529}
530
531} // namespace control_loops
532} // namespace frc971