blob: 667d2a4e61c2b61e720bb64a80c5a85d80c9aa55 [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(
Austin Schuhd27931c2014-02-16 19:18:20 -080072 const constants::Values::Claws::Claw &claw_values, double *edge_encoder,
Austin Schuhf9286cd2014-02-11 00:51:09 -080073 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() -
Austin Schuhd27931c2014-02-16 19:18:20 -0800287 values.claw.start_fine_tune_pos) <
288 values.claw.claw_unimportant_epsilon) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800289 doing_calibration_fine_tune_ = true;
Austin Schuhd27931c2014-02-16 19:18:20 -0800290 bottom_claw_goal_ += values.claw.claw_zeroing_speed * dt;
Austin Schuhcda86af2014-02-16 16:16:39 -0800291 LOG(DEBUG, "Ready to fine tune the bottom\n");
292 } else {
293 // send bottom to zeroing start
Austin Schuhd27931c2014-02-16 19:18:20 -0800294 bottom_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuhcda86af2014-02-16 16:16:39 -0800295 LOG(DEBUG, "Going to the start position for the bottom\n");
296 }
297 } else {
Austin Schuhd27931c2014-02-16 19:18:20 -0800298 bottom_claw_goal_ += values.claw.claw_zeroing_speed * dt;
Austin Schuhcda86af2014-02-16 16:16:39 -0800299 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;
Austin Schuhd27931c2014-02-16 19:18:20 -0800305 bottom_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuhcda86af2014-02-16 16:16:39 -0800306 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,
Austin Schuhd27931c2014-02-16 19:18:20 -0800315 values.claw.lower_claw.calibration.lower_angle);
Austin Schuh288c8c32014-02-16 17:20:17 -0800316 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;
Austin Schuhd27931c2014-02-16 19:18:20 -0800322 bottom_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuh288c8c32014-02-16 17:20:17 -0800323 }
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 Schuhd27931c2014-02-16 19:18:20 -0800330 top_claw_goal_ = bottom_claw_goal_ + values.claw.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_) {
Austin Schuhd27931c2014-02-16 19:18:20 -0800334 if (::std::abs(top_absolute_position() -
335 values.claw.start_fine_tune_pos) <
336 values.claw.claw_unimportant_epsilon) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800337 doing_calibration_fine_tune_ = true;
Austin Schuhd27931c2014-02-16 19:18:20 -0800338 top_claw_goal_ += values.claw.claw_zeroing_speed * dt;
Austin Schuhcda86af2014-02-16 16:16:39 -0800339 LOG(DEBUG, "Ready to fine tune the top\n");
340 } else {
341 // send top to zeroing start
Austin Schuhd27931c2014-02-16 19:18:20 -0800342 top_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuhcda86af2014-02-16 16:16:39 -0800343 LOG(DEBUG, "Going to the start position for the top\n");
344 }
345 } else {
Austin Schuhd27931c2014-02-16 19:18:20 -0800346 top_claw_goal_ += values.claw.claw_zeroing_speed * dt;
Austin Schuhcda86af2014-02-16 16:16:39 -0800347 if (top_claw_.front_hall_effect() || top_claw_.back_hall_effect() ||
348 bottom_claw_.front_hall_effect() ||
349 bottom_claw_.back_hall_effect()) {
350 // this should not happen, but now we know it won't
351 doing_calibration_fine_tune_ = false;
Austin Schuhd27931c2014-02-16 19:18:20 -0800352 top_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuhcda86af2014-02-16 16:16:39 -0800353 LOG(DEBUG, "Found a limit, starting over.\n");
354 }
355 if (top_claw_.calibration_hall_effect()) {
Austin Schuh288c8c32014-02-16 17:20:17 -0800356 if (top_claw_.calibration_hall_effect_posedge_count_changed() &&
357 position) {
358 // do calibration
Austin Schuhd27931c2014-02-16 19:18:20 -0800359 top_claw_.SetCalibration(
360 position->top.posedge_value,
361 values.claw.upper_claw.calibration.lower_angle);
Austin Schuh288c8c32014-02-16 17:20:17 -0800362 top_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
363 // calinrated so we are done fine tuning top
364 doing_calibration_fine_tune_ = false;
365 LOG(DEBUG, "Calibrated the top correctly!\n");
366 } else {
367 doing_calibration_fine_tune_ = false;
Austin Schuhd27931c2014-02-16 19:18:20 -0800368 top_claw_goal_ = values.claw.start_fine_tune_pos;
Austin Schuh288c8c32014-02-16 17:20:17 -0800369 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800370 }
371 }
372 // now set the bottom claw to track
Austin Schuhd27931c2014-02-16 19:18:20 -0800373 bottom_claw_goal_ = top_claw_goal_ - values.claw.claw_zeroing_separation;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800374 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800375 mode = FINE_TUNE;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800376 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800377 doing_calibration_fine_tune_ = false;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800378 if (!was_enabled_ && enabled) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800379 if (position) {
380 top_claw_goal_ = position->top.position;
381 bottom_claw_goal_ = position->bottom.position;
Austin Schuhcda86af2014-02-16 16:16:39 -0800382 initial_seperation_ =
383 position->top.position - position->bottom.position;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800384 } else {
385 has_top_claw_goal_ = false;
386 has_bottom_claw_goal_ = false;
387 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800388 }
Austin Schuhf9286cd2014-02-11 00:51:09 -0800389
390 // TODO(austin): Limit the goals here.
391 // Need to prevent windup, limit voltage, deal with windup on only 1 claw,
392 // ...
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800393 if (top_claw_.zeroing_state() ==
394 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
395 }
396 if (bottom_claw_.zeroing_state() ==
397 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
398 }
399
400 if (bottom_claw_.zeroing_state() !=
401 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800402 if (enabled) {
403 // Time to slowly move back up to find any position to narrow down the
404 // zero.
Austin Schuhd27931c2014-02-16 19:18:20 -0800405 top_claw_goal_ += values.claw.claw_zeroing_off_speed * dt;
406 bottom_claw_goal_ += values.claw.claw_zeroing_off_speed * dt;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800407 // TODO(austin): Goal velocity too!
Austin Schuhcda86af2014-02-16 16:16:39 -0800408 LOG(DEBUG, "Bottom is known.\n");
Austin Schuhf9286cd2014-02-11 00:51:09 -0800409 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800410 } else {
411 // We don't know where either claw is. Slowly start moving down to find
412 // any hall effect.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800413 if (enabled) {
Austin Schuhd27931c2014-02-16 19:18:20 -0800414 top_claw_goal_ -= values.claw.claw_zeroing_off_speed * dt;
415 bottom_claw_goal_ -= values.claw.claw_zeroing_off_speed * dt;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800416 // TODO(austin): Goal velocity too!
Austin Schuhcda86af2014-02-16 16:16:39 -0800417 LOG(DEBUG, "Both are unknown.\n");
Austin Schuhf9286cd2014-02-11 00:51:09 -0800418 }
419 }
420
421 if (enabled) {
422 top_claw_.SetCalibrationOnEdge(
Austin Schuhd27931c2014-02-16 19:18:20 -0800423 values.claw.upper_claw, ZeroedStateFeedbackLoop::APPROXIMATE_CALIBRATION);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800424 bottom_claw_.SetCalibrationOnEdge(
Austin Schuhd27931c2014-02-16 19:18:20 -0800425 values.claw.lower_claw, ZeroedStateFeedbackLoop::APPROXIMATE_CALIBRATION);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800426 } else {
427 top_claw_.SetCalibrationOnEdge(
Austin Schuhd27931c2014-02-16 19:18:20 -0800428 values.claw.upper_claw, ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800429 bottom_claw_.SetCalibrationOnEdge(
Austin Schuhd27931c2014-02-16 19:18:20 -0800430 values.claw.lower_claw, ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800431 }
Austin Schuhcda86af2014-02-16 16:16:39 -0800432 mode = UNKNOWN_LOCATION;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800433 }
434
Austin Schuh288c8c32014-02-16 17:20:17 -0800435 // TODO(austin): Handle disabled properly everwhere... Restart and all that
436 // jazz.
437
438 // TODO(Joe): Write this.
439 if (bottom_claw_goal_ < values.bottom.lower_limit) {
440 bottom_claw_goal_ = values.bottom.lower_limit;
441 }
442 if (bottom_claw_goal_ > values.bottom.upper_limit) {
443 bottom_claw_goal_ = values.bottom.upper_limit;
444 }
445
446 if (top_claw_goal_ < values.bottom.lower_limit) {
447 top_claw_goal_ = values.bottom.lower_limit;
448 }
449 if (top_claw_goal_ > values.top.upper_limit) {
450 top_claw_goal_ = values.top.upper_limit;
451 }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800452
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800453 // TODO(austin): ...
Austin Schuhf9286cd2014-02-11 00:51:09 -0800454 if (has_top_claw_goal_ && has_bottom_claw_goal_) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800455 claw_.R << bottom_claw_goal_, top_claw_goal_ - bottom_claw_goal_, 0, 0;
456 double separation = -971;
457 if (position != nullptr) {
458 separation = position->top.position - position->bottom.position;
459 }
460 LOG(DEBUG, "Goal is %f (bottom) %f, separation is %f\n", claw_.R(0, 0),
461 claw_.R(1, 0), separation);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800462
Austin Schuhcda86af2014-02-16 16:16:39 -0800463 claw_.Update(output == nullptr);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800464 } else {
Austin Schuhcda86af2014-02-16 16:16:39 -0800465 claw_.Update(true);
Austin Schuhf9286cd2014-02-11 00:51:09 -0800466 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800467
Austin Schuh288c8c32014-02-16 17:20:17 -0800468 (void) mode;
Austin Schuhcda86af2014-02-16 16:16:39 -0800469 /*
470 switch (mode) {
471 case READY:
472 break;
473 case FINE_TUNE:
474 break;
475 case UNKNOWN_LOCATION:
476 if (top_claw_->uncapped_voltage() > values.max_zeroing_voltage) {
477 double dx =
478 (top_claw_->uncapped_voltage() - values.max_zeroing_voltage) /
479 top_claw_->K(0, 0);
480 zeroing_position_ -= dx;
481 capped_goal_ = true;
482 } else if (top_claw_->uncapped_voltage() < -values.max_zeroing_voltage) {
483 double dx =
484 (top_claw_->uncapped_voltage() + values.max_zeroing_voltage) /
485 top_claw_->K(0, 0);
486 zeroing_position_ -= dx;
487 capped_goal_ = true;
488 }
489 break;
490 }
491 */
492
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800493 if (position) {
494 //LOG(DEBUG, "pos: %f hall: %s absolute: %f\n", position->top_position,
495 //position->top_calibration_hall_effect ? "true" : "false",
496 //zeroed_joint_.absolute_position());
Austin Schuh3bb9a442014-02-02 16:01:45 -0800497 }
498
499 if (output) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800500 output->top_claw_voltage = claw_.U(1, 0) + claw_.U(0, 0);
501 output->bottom_claw_voltage = claw_.U(0, 0);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800502 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800503 status->done = false;
504 //::std::abs(zeroed_joint_.absolute_position() - goal->bottom_angle -
505 //goal->seperation_angle) < 0.004;
506
507 was_enabled_ = ::aos::robot_state->enabled;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800508}
509
510} // namespace control_loops
511} // namespace frc971