blob: 96f44478088962cfeb743ddeada004768c131e7d [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
13// TODO(austin): Switch the control loop over to a seperation and a bottom
14// position. This will make things a lot more robust and allows for different
15// stiffnesses.
Austin Schuh3bb9a442014-02-02 16:01:45 -080016
17// Zeroing plan.
18// There are 2 types of zeros. Enabled and disabled ones.
19// Disabled ones are only valid during auto mode, and can be used to speed up
20// the enabled zero process. We need to re-zero during teleop in case the auto
21// zero was poor and causes us to miss all our shots.
22//
23// We need to be able to zero manually while disabled by moving the joint over
24// the zeros.
25// Zero on the down edge when disabled (gravity in the direction of motion)
26//
27// When enabled, zero on the up edge (gravity opposing the direction of motion)
28// The enabled sequence needs to work as follows. We can crash the claw if we
29// bring them too close to each other or too far from each other. The only safe
30// thing to do is to move them in unison.
31//
32// Start by moving them both towards the front of the bot to either find either
33// the middle hall effect on either jaw, or the front hall effect on the bottom
34// jaw. Any edge that isn't the desired edge will provide an approximate edge
35// location that can be used for the fine tuning step.
36// Once an edge is found on the front claw, move back the other way with both
37// claws until an edge is found for the other claw.
38// Now that we have an approximate zero, we can robustify the limits to keep
39// both claws safe. Then, we can move both claws to a position that is the
40// correct side of the zero and go zero.
41
42// Valid region plan.
43// Difference between the arms has a range, and the values of each arm has a range.
44// If a claw runs up against a static limit, don't let the goal change outside
45// the limit.
46// If a claw runs up against a movable limit, move both claws outwards to get
47// out of the condition.
48
49namespace frc971 {
50namespace control_loops {
51
Austin Schuhcda86af2014-02-16 16:16:39 -080052void ClawLimitedLoop::CapU() {
53 double max_value = ::std::max(::std::abs(U(0, 0)), ::std::abs(U(1, 0) + U(0, 0)));
54 if (max_value > 12.0) {
55 LOG(DEBUG, "Capping U because max is %f\n", max_value);
56 U = U * 12.0 / max_value;
57 LOG(DEBUG, "Capping U is now %f %f\n", U(0, 0), U(1, 0));
Austin Schuh4b7b5d02014-02-10 21:20:34 -080058 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -080059}
60
Austin Schuhcc0bf312014-02-09 00:39:29 -080061ClawMotor::ClawMotor(control_loops::ClawGroup *my_claw)
62 : aos::control_loops::ControlLoop<control_loops::ClawGroup>(my_claw),
Austin Schuh4b7b5d02014-02-10 21:20:34 -080063 has_top_claw_goal_(false),
64 top_claw_goal_(0.0),
Austin Schuhcda86af2014-02-16 16:16:39 -080065 top_claw_(this),
Austin Schuh4b7b5d02014-02-10 21:20:34 -080066 has_bottom_claw_goal_(false),
67 bottom_claw_goal_(0.0),
Austin Schuhcda86af2014-02-16 16:16:39 -080068 bottom_claw_(this),
69 claw_(MakeClawLoop()),
Ben Fredrickson9b388422014-02-13 06:15:31 +000070 was_enabled_(false),
71 doing_calibration_fine_tune_(false) {}
Austin Schuh3bb9a442014-02-02 16:01:45 -080072
Austin Schuh4b7b5d02014-02-10 21:20:34 -080073const int ZeroedStateFeedbackLoop::kZeroingMaxVoltage;
Austin Schuh3bb9a442014-02-02 16:01:45 -080074
Austin Schuhf9286cd2014-02-11 00:51:09 -080075bool ZeroedStateFeedbackLoop::GetPositionOfEdge(
76 const constants::Values::Claw &claw_values, double *edge_encoder,
77 double *edge_angle) {
78
79 // TODO(austin): Validate that the hall effect edge makes sense.
80 // We must now be on the side of the edge that we expect to be, and the
81 // encoder must have been on either side of the edge before and after.
82
Austin Schuhcda86af2014-02-16 16:16:39 -080083 // TODO(austin): Compute the last off range min and max and compare the edge
84 // value to the middle of the range. This will be quite a bit more reliable.
85
Austin Schuhf9286cd2014-02-11 00:51:09 -080086 if (front_hall_effect_posedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -080087 if (posedge_value_ - last_encoder() < 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -080088 *edge_angle = claw_values.front.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -080089 LOG(INFO, "%s Posedge front upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -080090 } else {
91 *edge_angle = claw_values.front.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -080092 LOG(INFO, "%s Posedge front lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -080093 }
94 *edge_encoder = posedge_value_;
95 return true;
96 }
97 if (front_hall_effect_negedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -080098 LOG(INFO, "%s Value is %f last is %f\n", name_, negedge_value_, last_encoder());
99 if (negedge_value_ - last_encoder() > 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800100 *edge_angle = claw_values.front.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800101 LOG(INFO, "%s Negedge front upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800102 } else {
103 *edge_angle = claw_values.front.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800104 LOG(INFO, "%s Negedge front lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800105 }
106 *edge_encoder = negedge_value_;
107 return true;
108 }
109 if (calibration_hall_effect_posedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800110 if (posedge_value_ - last_encoder() < 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800111 *edge_angle = claw_values.calibration.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800112 LOG(INFO, "%s Posedge calibration upper edge -> %f\n", name_,
113 *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800114 } else {
115 *edge_angle = claw_values.calibration.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800116 LOG(INFO, "%s Posedge calibration lower edge -> %f\n", name_,
117 *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800118 }
119 *edge_encoder = posedge_value_;
120 return true;
121 }
122 if (calibration_hall_effect_negedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800123 if (negedge_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 Negedge calibration upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800126 } else {
127 *edge_angle = claw_values.calibration.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800128 LOG(INFO, "%s Negedge calibration lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800129 }
130 *edge_encoder = negedge_value_;
131 return true;
132 }
133 if (back_hall_effect_posedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800134 if (posedge_value_ - last_encoder() < 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800135 *edge_angle = claw_values.back.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800136 LOG(INFO, "%s Posedge back upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800137 } else {
138 *edge_angle = claw_values.back.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800139 LOG(INFO, "%s Posedge back lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800140 }
141 *edge_encoder = posedge_value_;
142 return true;
143 }
144 if (back_hall_effect_negedge_count_changed()) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800145 if (negedge_value_ - last_encoder() > 0) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800146 *edge_angle = claw_values.back.upper_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800147 LOG(INFO, "%s Negedge back upper edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800148 } else {
149 *edge_angle = claw_values.back.lower_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800150 LOG(INFO, "%s Negedge back lower edge -> %f\n", name_, *edge_angle);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800151 }
152 *edge_encoder = negedge_value_;
153 return true;
154 }
155 return false;
156}
157
Austin Schuhcda86af2014-02-16 16:16:39 -0800158void TopZeroedStateFeedbackLoop::SetCalibration(double edge_encoder,
159 double edge_angle) {
160 double old_offset = offset_;
161 offset_ = edge_angle - edge_encoder;
162 const double doffset = offset_ - old_offset;
163 motor_->ChangeTopOffset(doffset);
164}
165
166void BottomZeroedStateFeedbackLoop::SetCalibration(double edge_encoder,
167 double edge_angle) {
168 double old_offset = offset_;
169 offset_ = edge_angle - edge_encoder;
170 const double doffset = offset_ - old_offset;
171 motor_->ChangeBottomOffset(doffset);
172}
173
174void ClawMotor::ChangeTopOffset(double doffset) {
175 claw_.ChangeTopOffset(doffset);
176 if (has_top_claw_goal_) {
177 top_claw_goal_ += doffset;
178 }
179}
180
181void ClawMotor::ChangeBottomOffset(double doffset) {
182 claw_.ChangeBottomOffset(doffset);
183 if (has_bottom_claw_goal_) {
184 bottom_claw_goal_ += doffset;
185 }
186}
187
188void ClawLimitedLoop::ChangeTopOffset(double doffset) {
189 Y_(1, 0) += doffset;
190 X_hat(1, 0) += doffset;
191 LOG(INFO, "Changing top offset by %f\n", doffset);
192}
193void ClawLimitedLoop::ChangeBottomOffset(double doffset) {
194 Y_(0, 0) += doffset;
195 X_hat(0, 0) += doffset;
196 X_hat(1, 0) -= doffset;
197 LOG(INFO, "Changing bottom offset by %f\n", doffset);
198}
199
Austin Schuh3bb9a442014-02-02 16:01:45 -0800200// Positive angle is up, and positive power is up.
Austin Schuhcc0bf312014-02-09 00:39:29 -0800201void ClawMotor::RunIteration(const control_loops::ClawGroup::Goal *goal,
202 const control_loops::ClawGroup::Position *position,
203 control_loops::ClawGroup::Output *output,
Austin Schuh3bb9a442014-02-02 16:01:45 -0800204 ::aos::control_loops::Status *status) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800205 constexpr double dt = 0.01;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800206
207 // Disable the motors now so that all early returns will return with the
208 // motors disabled.
209 if (output) {
210 output->top_claw_voltage = 0;
211 output->bottom_claw_voltage = 0;
212 output->intake_voltage = 0;
213 }
214
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800215 // TODO(austin): Handle the disabled state and the disabled -> enabled
Austin Schuhcda86af2014-02-16 16:16:39 -0800216 // transition in all of these states.
217 // TODO(austin): Handle zeroing while disabled correctly (only use a single
218 // edge and direction when zeroing.)
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800219
220 // TODO(austin): Save all the counters so we know when something actually
Austin Schuhcda86af2014-02-16 16:16:39 -0800221 // happens.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800222 // TODO(austin): Helpers to find the position of the claw on an edge.
223
224 // TODO(austin): This may not be necesary because of the ControlLoop class.
225 ::aos::robot_state.FetchLatest();
226 if (::aos::robot_state.get() == nullptr) {
227 return;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800228 }
229
Austin Schuhf9286cd2014-02-11 00:51:09 -0800230 const frc971::constants::Values &values = constants::GetValues();
231
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800232 if (position) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800233 Eigen::Matrix<double, 2, 1> Y;
234 Y << position->bottom.position + bottom_claw_.offset(),
235 position->top.position + top_claw_.offset();
236 claw_.Correct(Y);
237
Austin Schuhf9286cd2014-02-11 00:51:09 -0800238 top_claw_.SetPositionValues(position->top);
239 bottom_claw_.SetPositionValues(position->bottom);
240
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800241 if (!has_top_claw_goal_) {
242 has_top_claw_goal_ = true;
Austin Schuhcda86af2014-02-16 16:16:39 -0800243 top_claw_goal_ = top_claw_.absolute_position();
244 initial_seperation_ =
245 top_claw_.absolute_position() - bottom_claw_.absolute_position();
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800246 }
247 if (!has_bottom_claw_goal_) {
248 has_bottom_claw_goal_ = true;
Austin Schuhcda86af2014-02-16 16:16:39 -0800249 bottom_claw_goal_ = bottom_claw_.absolute_position();
250 initial_seperation_ =
251 top_claw_.absolute_position() - bottom_claw_.absolute_position();
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800252 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800253 LOG(DEBUG, "Claw position is (top: %f bottom: %f\n",
254 top_claw_.absolute_position(), bottom_claw_.absolute_position());
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800255 }
256
257 bool autonomous = ::aos::robot_state->autonomous;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800258 bool enabled = ::aos::robot_state->enabled;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800259
Austin Schuhcda86af2014-02-16 16:16:39 -0800260 enum CalibrationMode {
261 READY,
262 FINE_TUNE,
263 UNKNOWN_LOCATION
264 };
265
266 CalibrationMode mode;
267
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800268 if ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED &&
269 bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED) ||
270 (autonomous &&
271 ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
272 top_claw_.zeroing_state() ==
273 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION) &&
274 (bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
275 bottom_claw_.zeroing_state() ==
276 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION)))) {
277 // Ready to use the claw.
278 // Limit the goals here.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800279 bottom_claw_goal_ = goal->bottom_angle;
280 top_claw_goal_ = goal->bottom_angle + goal->seperation_angle;
Austin Schuhcda86af2014-02-16 16:16:39 -0800281 has_bottom_claw_goal_ = true;
282 has_top_claw_goal_ = true;
283 doing_calibration_fine_tune_ = false;
284
285 mode = READY;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800286 } else if (top_claw_.zeroing_state() !=
287 ZeroedStateFeedbackLoop::UNKNOWN_POSITION &&
288 bottom_claw_.zeroing_state() !=
289 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
290 // Time to fine tune the zero.
291 // Limit the goals here.
292 if (bottom_claw_.zeroing_state() != ZeroedStateFeedbackLoop::CALIBRATED) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800293 // always get the bottom claw to calibrated first
294 LOG(DEBUG, "Calibrating the bottom of the claw\n");
295 if (!doing_calibration_fine_tune_) {
296 if (::std::abs(bottom_absolute_position() -
297 values.start_fine_tune_pos) <
298 values.claw_unimportant_epsilon) {
299 doing_calibration_fine_tune_ = true;
300 bottom_claw_goal_ += values.claw_zeroing_speed * dt;
301 LOG(DEBUG, "Ready to fine tune the bottom\n");
302 } else {
303 // send bottom to zeroing start
304 bottom_claw_goal_ = values.start_fine_tune_pos;
305 LOG(DEBUG, "Going to the start position for the bottom\n");
306 }
307 } else {
308 bottom_claw_goal_ += values.claw_zeroing_speed * dt;
309 if (top_claw_.front_hall_effect() || top_claw_.back_hall_effect() ||
310 bottom_claw_.front_hall_effect() ||
311 bottom_claw_.back_hall_effect()) {
312 // We shouldn't hit a limit, but if we do, go back to the zeroing
313 // point and try again.
314 doing_calibration_fine_tune_ = false;
315 bottom_claw_goal_ = values.start_fine_tune_pos;
316 LOG(DEBUG, "Found a limit, starting over.\n");
317 }
318 // TODO(austin): We have a count for this... Need to double check that
319 // it ticked, just in case.
320 if (bottom_claw_.calibration_hall_effect()) {
321 // do calibration
322 bottom_claw_.SetCalibration(
323 position->bottom.posedge_value,
324 values.lower_claw.calibration.lower_angle);
325 bottom_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
326 // calibrated so we are done fine tuning bottom
327 doing_calibration_fine_tune_ = false;
328 LOG(DEBUG, "Calibrated the bottom correctly!\n");
329 } else {
330 LOG(DEBUG, "Fine tuning\n");
331 }
332 }
333 // now set the top claw to track
334
335 // TODO(austin): Some safe distance!
336 top_claw_goal_ = bottom_claw_goal_ + values.claw_zeroing_separation;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800337 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800338 // bottom claw must be calibrated, start on the top
339 if (!doing_calibration_fine_tune_) {
340 if (::std::abs(top_absolute_position() - values.start_fine_tune_pos) <
341 values.claw_unimportant_epsilon) {
342 doing_calibration_fine_tune_ = true;
343 top_claw_goal_ += values.claw_zeroing_speed * dt;
344 LOG(DEBUG, "Ready to fine tune the top\n");
345 } else {
346 // send top to zeroing start
347 top_claw_goal_ = values.start_fine_tune_pos;
348 LOG(DEBUG, "Going to the start position for the top\n");
349 }
350 } else {
351 top_claw_goal_ += values.claw_zeroing_speed * dt;
352 if (top_claw_.front_hall_effect() || top_claw_.back_hall_effect() ||
353 bottom_claw_.front_hall_effect() ||
354 bottom_claw_.back_hall_effect()) {
355 // this should not happen, but now we know it won't
356 doing_calibration_fine_tune_ = false;
357 top_claw_goal_ = values.start_fine_tune_pos;
358 LOG(DEBUG, "Found a limit, starting over.\n");
359 }
360 if (top_claw_.calibration_hall_effect()) {
361 // do calibration
362 top_claw_.SetCalibration(position->top.posedge_value,
363 values.upper_claw.calibration.lower_angle);
364 top_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
365 // calinrated so we are done fine tuning top
366 doing_calibration_fine_tune_ = false;
367 LOG(DEBUG, "Calibrated the top correctly!\n");
368 }
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
433 // TODO(austin): Handle disabled.
Austin Schuh3bb9a442014-02-02 16:01:45 -0800434
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800435 // TODO(austin): ...
Austin Schuhf9286cd2014-02-11 00:51:09 -0800436 if (has_top_claw_goal_ && has_bottom_claw_goal_) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800437 claw_.R << bottom_claw_goal_, top_claw_goal_ - bottom_claw_goal_, 0, 0;
438 double separation = -971;
439 if (position != nullptr) {
440 separation = position->top.position - position->bottom.position;
441 }
442 LOG(DEBUG, "Goal is %f (bottom) %f, separation is %f\n", claw_.R(0, 0),
443 claw_.R(1, 0), separation);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800444
Austin Schuhcda86af2014-02-16 16:16:39 -0800445 claw_.Update(output == nullptr);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800446 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800447 claw_.Update(true);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800448 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800449
Austin Schuhcda86af2014-02-16 16:16:39 -0800450 (void)mode;
451
452 /*
453 switch (mode) {
454 case READY:
455 break;
456 case FINE_TUNE:
457 break;
458 case UNKNOWN_LOCATION:
459 if (top_claw_->uncapped_voltage() > values.max_zeroing_voltage) {
460 double dx =
461 (top_claw_->uncapped_voltage() - values.max_zeroing_voltage) /
462 top_claw_->K(0, 0);
463 zeroing_position_ -= dx;
464 capped_goal_ = true;
465 } else if (top_claw_->uncapped_voltage() < -values.max_zeroing_voltage) {
466 double dx =
467 (top_claw_->uncapped_voltage() + values.max_zeroing_voltage) /
468 top_claw_->K(0, 0);
469 zeroing_position_ -= dx;
470 capped_goal_ = true;
471 }
472 break;
473 }
474 */
475
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800476 if (position) {
477 //LOG(DEBUG, "pos: %f hall: %s absolute: %f\n", position->top_position,
478 //position->top_calibration_hall_effect ? "true" : "false",
479 //zeroed_joint_.absolute_position());
Austin Schuh3bb9a442014-02-02 16:01:45 -0800480 }
481
482 if (output) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800483 output->top_claw_voltage = claw_.U(1, 0) + claw_.U(0, 0);
484 output->bottom_claw_voltage = claw_.U(0, 0);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800485 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800486 status->done = false;
487 //::std::abs(zeroed_joint_.absolute_position() - goal->bottom_angle -
488 //goal->seperation_angle) < 0.004;
489
490 was_enabled_ = ::aos::robot_state->enabled;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800491}
492
493} // namespace control_loops
494} // namespace frc971