blob: 49b188632cddbb9ac8b2689a4c46b6311822a95f [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}
195
Austin Schuh3bb9a442014-02-02 16:01:45 -0800196// Positive angle is up, and positive power is up.
Austin Schuhcc0bf312014-02-09 00:39:29 -0800197void ClawMotor::RunIteration(const control_loops::ClawGroup::Goal *goal,
198 const control_loops::ClawGroup::Position *position,
199 control_loops::ClawGroup::Output *output,
Austin Schuh3bb9a442014-02-02 16:01:45 -0800200 ::aos::control_loops::Status *status) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800201 constexpr double dt = 0.01;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800202
203 // Disable the motors now so that all early returns will return with the
204 // motors disabled.
205 if (output) {
206 output->top_claw_voltage = 0;
207 output->bottom_claw_voltage = 0;
208 output->intake_voltage = 0;
209 }
210
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800211 // TODO(austin): Handle the disabled state and the disabled -> enabled
Austin Schuhcda86af2014-02-16 16:16:39 -0800212 // transition in all of these states.
213 // TODO(austin): Handle zeroing while disabled correctly (only use a single
214 // edge and direction when zeroing.)
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800215
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800216 if (::aos::robot_state.get() == nullptr) {
217 return;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800218 }
219
Austin Schuhf9286cd2014-02-11 00:51:09 -0800220 const frc971::constants::Values &values = constants::GetValues();
221
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800222 if (position) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800223 Eigen::Matrix<double, 2, 1> Y;
224 Y << position->bottom.position + bottom_claw_.offset(),
225 position->top.position + top_claw_.offset();
226 claw_.Correct(Y);
227
Austin Schuhf9286cd2014-02-11 00:51:09 -0800228 top_claw_.SetPositionValues(position->top);
229 bottom_claw_.SetPositionValues(position->bottom);
230
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800231 if (!has_top_claw_goal_) {
232 has_top_claw_goal_ = true;
Austin Schuhcda86af2014-02-16 16:16:39 -0800233 top_claw_goal_ = top_claw_.absolute_position();
234 initial_seperation_ =
235 top_claw_.absolute_position() - bottom_claw_.absolute_position();
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800236 }
237 if (!has_bottom_claw_goal_) {
238 has_bottom_claw_goal_ = true;
Austin Schuhcda86af2014-02-16 16:16:39 -0800239 bottom_claw_goal_ = bottom_claw_.absolute_position();
240 initial_seperation_ =
241 top_claw_.absolute_position() - bottom_claw_.absolute_position();
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800242 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800243 LOG(DEBUG, "Claw position is (top: %f bottom: %f\n",
244 top_claw_.absolute_position(), bottom_claw_.absolute_position());
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800245 }
246
247 bool autonomous = ::aos::robot_state->autonomous;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800248 bool enabled = ::aos::robot_state->enabled;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800249
Austin Schuhcda86af2014-02-16 16:16:39 -0800250 enum CalibrationMode {
251 READY,
252 FINE_TUNE,
253 UNKNOWN_LOCATION
254 };
255
256 CalibrationMode mode;
257
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800258 if ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED &&
259 bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED) ||
260 (autonomous &&
261 ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
262 top_claw_.zeroing_state() ==
263 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION) &&
264 (bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
265 bottom_claw_.zeroing_state() ==
266 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION)))) {
267 // Ready to use the claw.
268 // Limit the goals here.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800269 bottom_claw_goal_ = goal->bottom_angle;
270 top_claw_goal_ = goal->bottom_angle + goal->seperation_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800271 has_bottom_claw_goal_ = true;
272 has_top_claw_goal_ = true;
273 doing_calibration_fine_tune_ = false;
274
275 mode = READY;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800276 } else if (top_claw_.zeroing_state() !=
277 ZeroedStateFeedbackLoop::UNKNOWN_POSITION &&
278 bottom_claw_.zeroing_state() !=
279 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
280 // Time to fine tune the zero.
281 // Limit the goals here.
282 if (bottom_claw_.zeroing_state() != ZeroedStateFeedbackLoop::CALIBRATED) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800283 // always get the bottom claw to calibrated first
284 LOG(DEBUG, "Calibrating the bottom of the claw\n");
285 if (!doing_calibration_fine_tune_) {
286 if (::std::abs(bottom_absolute_position() -
287 values.start_fine_tune_pos) <
288 values.claw_unimportant_epsilon) {
289 doing_calibration_fine_tune_ = true;
290 bottom_claw_goal_ += values.claw_zeroing_speed * dt;
291 LOG(DEBUG, "Ready to fine tune the bottom\n");
292 } else {
293 // send bottom to zeroing start
294 bottom_claw_goal_ = values.start_fine_tune_pos;
295 LOG(DEBUG, "Going to the start position for the bottom\n");
296 }
297 } else {
298 bottom_claw_goal_ += values.claw_zeroing_speed * dt;
299 if (top_claw_.front_hall_effect() || top_claw_.back_hall_effect() ||
300 bottom_claw_.front_hall_effect() ||
301 bottom_claw_.back_hall_effect()) {
302 // We shouldn't hit a limit, but if we do, go back to the zeroing
303 // point and try again.
304 doing_calibration_fine_tune_ = false;
305 bottom_claw_goal_ = values.start_fine_tune_pos;
306 LOG(DEBUG, "Found a limit, starting over.\n");
307 }
Austin Schuh288c8c32014-02-16 17:20:17 -0800308
Austin Schuhcda86af2014-02-16 16:16:39 -0800309 if (bottom_claw_.calibration_hall_effect()) {
Austin Schuh288c8c32014-02-16 17:20:17 -0800310 if (bottom_claw_.calibration_hall_effect_posedge_count_changed() &&
311 position) {
312 // do calibration
313 bottom_claw_.SetCalibration(
314 position->bottom.posedge_value,
315 values.lower_claw.calibration.lower_angle);
316 bottom_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
317 // calibrated so we are done fine tuning bottom
318 doing_calibration_fine_tune_ = false;
319 LOG(DEBUG, "Calibrated the bottom correctly!\n");
320 } else {
321 doing_calibration_fine_tune_ = false;
322 bottom_claw_goal_ = values.start_fine_tune_pos;
323 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800324 } else {
325 LOG(DEBUG, "Fine tuning\n");
326 }
327 }
328 // now set the top claw to track
329
Austin Schuhcda86af2014-02-16 16:16:39 -0800330 top_claw_goal_ = bottom_claw_goal_ + values.claw_zeroing_separation;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800331 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800332 // bottom claw must be calibrated, start on the top
333 if (!doing_calibration_fine_tune_) {
334 if (::std::abs(top_absolute_position() - values.start_fine_tune_pos) <
335 values.claw_unimportant_epsilon) {
336 doing_calibration_fine_tune_ = true;
337 top_claw_goal_ += values.claw_zeroing_speed * dt;
338 LOG(DEBUG, "Ready to fine tune the top\n");
339 } else {
340 // send top to zeroing start
341 top_claw_goal_ = values.start_fine_tune_pos;
342 LOG(DEBUG, "Going to the start position for the top\n");
343 }
344 } else {
345 top_claw_goal_ += values.claw_zeroing_speed * dt;
346 if (top_claw_.front_hall_effect() || top_claw_.back_hall_effect() ||
347 bottom_claw_.front_hall_effect() ||
348 bottom_claw_.back_hall_effect()) {
349 // this should not happen, but now we know it won't
350 doing_calibration_fine_tune_ = false;
351 top_claw_goal_ = values.start_fine_tune_pos;
352 LOG(DEBUG, "Found a limit, starting over.\n");
353 }
354 if (top_claw_.calibration_hall_effect()) {
Austin Schuh288c8c32014-02-16 17:20:17 -0800355 if (top_claw_.calibration_hall_effect_posedge_count_changed() &&
356 position) {
357 // do calibration
358 top_claw_.SetCalibration(position->top.posedge_value,
359 values.upper_claw.calibration.lower_angle);
360 top_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
361 // calinrated so we are done fine tuning top
362 doing_calibration_fine_tune_ = false;
363 LOG(DEBUG, "Calibrated the top correctly!\n");
364 } else {
365 doing_calibration_fine_tune_ = false;
366 top_claw_goal_ = values.start_fine_tune_pos;
367 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800368 }
369 }
370 // now set the bottom claw to track
371 bottom_claw_goal_ = top_claw_goal_ - values.claw_zeroing_separation;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800372 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800373 mode = FINE_TUNE;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800374 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800375 doing_calibration_fine_tune_ = false;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800376 if (!was_enabled_ && enabled) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800377 if (position) {
378 top_claw_goal_ = position->top.position;
379 bottom_claw_goal_ = position->bottom.position;
Austin Schuhcda86af2014-02-16 16:16:39 -0800380 initial_seperation_ =
381 position->top.position - position->bottom.position;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800382 } else {
383 has_top_claw_goal_ = false;
384 has_bottom_claw_goal_ = false;
385 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800386 }
Austin Schuhf9286cd2014-02-11 00:51:09 -0800387
388 // TODO(austin): Limit the goals here.
389 // Need to prevent windup, limit voltage, deal with windup on only 1 claw,
390 // ...
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800391 if (top_claw_.zeroing_state() ==
392 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
393 }
394 if (bottom_claw_.zeroing_state() ==
395 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
396 }
397
398 if (bottom_claw_.zeroing_state() !=
399 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800400 if (enabled) {
401 // Time to slowly move back up to find any position to narrow down the
402 // zero.
403 top_claw_goal_ += values.claw_zeroing_off_speed * dt;
404 bottom_claw_goal_ += values.claw_zeroing_off_speed * dt;
405 // TODO(austin): Goal velocity too!
Austin Schuhcda86af2014-02-16 16:16:39 -0800406 LOG(DEBUG, "Bottom is known.\n");
Austin Schuhf9286cd2014-02-11 00:51:09 -0800407 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800408 } else {
409 // We don't know where either claw is. Slowly start moving down to find
410 // any hall effect.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800411 if (enabled) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800412 top_claw_goal_ -= values.claw_zeroing_off_speed * dt;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800413 bottom_claw_goal_ -= values.claw_zeroing_off_speed * dt;
414 // TODO(austin): Goal velocity too!
Austin Schuhcda86af2014-02-16 16:16:39 -0800415 LOG(DEBUG, "Both are unknown.\n");
Austin Schuhf9286cd2014-02-11 00:51:09 -0800416 }
417 }
418
419 if (enabled) {
420 top_claw_.SetCalibrationOnEdge(
421 values.upper_claw, ZeroedStateFeedbackLoop::APPROXIMATE_CALIBRATION);
422 bottom_claw_.SetCalibrationOnEdge(
423 values.lower_claw, ZeroedStateFeedbackLoop::APPROXIMATE_CALIBRATION);
424 } else {
425 top_claw_.SetCalibrationOnEdge(
426 values.upper_claw, ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
427 bottom_claw_.SetCalibrationOnEdge(
428 values.lower_claw, ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800429 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800430 mode = UNKNOWN_LOCATION;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800431 }
432
Austin Schuh288c8c32014-02-16 17:20:17 -0800433 // TODO(austin): Handle disabled properly everwhere... Restart and all that
434 // jazz.
435
436 // TODO(Joe): Write this.
437 if (bottom_claw_goal_ < values.bottom.lower_limit) {
438 bottom_claw_goal_ = values.bottom.lower_limit;
439 }
440 if (bottom_claw_goal_ > values.bottom.upper_limit) {
441 bottom_claw_goal_ = values.bottom.upper_limit;
442 }
443
444 if (top_claw_goal_ < values.bottom.lower_limit) {
445 top_claw_goal_ = values.bottom.lower_limit;
446 }
447 if (top_claw_goal_ > values.top.upper_limit) {
448 top_claw_goal_ = values.top.upper_limit;
449 }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800450
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800451 // TODO(austin): ...
Austin Schuhf9286cd2014-02-11 00:51:09 -0800452 if (has_top_claw_goal_ && has_bottom_claw_goal_) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800453 claw_.R << bottom_claw_goal_, top_claw_goal_ - bottom_claw_goal_, 0, 0;
454 double separation = -971;
455 if (position != nullptr) {
456 separation = position->top.position - position->bottom.position;
457 }
458 LOG(DEBUG, "Goal is %f (bottom) %f, separation is %f\n", claw_.R(0, 0),
459 claw_.R(1, 0), separation);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800460
Austin Schuhcda86af2014-02-16 16:16:39 -0800461 claw_.Update(output == nullptr);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800462 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800463 claw_.Update(true);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800464 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800465
Austin Schuh288c8c32014-02-16 17:20:17 -0800466 (void) mode;
Austin Schuhcda86af2014-02-16 16:16:39 -0800467 /*
468 switch (mode) {
469 case READY:
470 break;
471 case FINE_TUNE:
472 break;
473 case UNKNOWN_LOCATION:
474 if (top_claw_->uncapped_voltage() > values.max_zeroing_voltage) {
475 double dx =
476 (top_claw_->uncapped_voltage() - values.max_zeroing_voltage) /
477 top_claw_->K(0, 0);
478 zeroing_position_ -= dx;
479 capped_goal_ = true;
480 } else if (top_claw_->uncapped_voltage() < -values.max_zeroing_voltage) {
481 double dx =
482 (top_claw_->uncapped_voltage() + values.max_zeroing_voltage) /
483 top_claw_->K(0, 0);
484 zeroing_position_ -= dx;
485 capped_goal_ = true;
486 }
487 break;
488 }
489 */
490
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800491 if (position) {
492 //LOG(DEBUG, "pos: %f hall: %s absolute: %f\n", position->top_position,
493 //position->top_calibration_hall_effect ? "true" : "false",
494 //zeroed_joint_.absolute_position());
Austin Schuh3bb9a442014-02-02 16:01:45 -0800495 }
496
497 if (output) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800498 output->top_claw_voltage = claw_.U(1, 0) + claw_.U(0, 0);
499 output->bottom_claw_voltage = claw_.U(0, 0);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800500 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800501 status->done = false;
502 //::std::abs(zeroed_joint_.absolute_position() - goal->bottom_angle -
503 //goal->seperation_angle) < 0.004;
504
505 was_enabled_ = ::aos::robot_state->enabled;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800506}
507
508} // namespace control_loops
509} // namespace frc971