blob: fb16c514109dd1bb7f8f9cf4b32c3d0f0d393495 [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"
11#include "frc971/control_loops/claw/top_claw_motor_plant.h"
12#include "frc971/control_loops/claw/bottom_claw_motor_plant.h"
13
14// Zeroing plan.
15// There are 2 types of zeros. Enabled and disabled ones.
16// Disabled ones are only valid during auto mode, and can be used to speed up
17// the enabled zero process. We need to re-zero during teleop in case the auto
18// zero was poor and causes us to miss all our shots.
19//
20// We need to be able to zero manually while disabled by moving the joint over
21// the zeros.
22// Zero on the down edge when disabled (gravity in the direction of motion)
23//
24// When enabled, zero on the up edge (gravity opposing the direction of motion)
25// The enabled sequence needs to work as follows. We can crash the claw if we
26// bring them too close to each other or too far from each other. The only safe
27// thing to do is to move them in unison.
28//
29// Start by moving them both towards the front of the bot to either find either
30// the middle hall effect on either jaw, or the front hall effect on the bottom
31// jaw. Any edge that isn't the desired edge will provide an approximate edge
32// location that can be used for the fine tuning step.
33// Once an edge is found on the front claw, move back the other way with both
34// claws until an edge is found for the other claw.
35// Now that we have an approximate zero, we can robustify the limits to keep
36// both claws safe. Then, we can move both claws to a position that is the
37// correct side of the zero and go zero.
38
39// Valid region plan.
40// Difference between the arms has a range, and the values of each arm has a range.
41// If a claw runs up against a static limit, don't let the goal change outside
42// the limit.
43// If a claw runs up against a movable limit, move both claws outwards to get
44// out of the condition.
45
46namespace frc971 {
47namespace control_loops {
48
Austin Schuh4b7b5d02014-02-10 21:20:34 -080049void ZeroedStateFeedbackLoop::CapU() {
50 const double old_voltage = voltage_;
51 voltage_ += U(0, 0);
52
53 uncapped_voltage_ = voltage_;
54
55 double limit = zeroing_state_ != UNKNOWN_POSITION ? 12.0 : kZeroingMaxVoltage;
56
57 // Make sure that reality and the observer can't get too far off. There is a
58 // delay by one cycle between the applied voltage and X_hat(2, 0), so compare
59 // against last cycle's voltage.
60 if (X_hat(2, 0) > last_voltage_ + 2.0) {
61 voltage_ -= X_hat(2, 0) - (last_voltage_ + 2.0);
62 LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
63 } else if (X_hat(2, 0) < last_voltage_ -2.0) {
64 voltage_ += X_hat(2, 0) - (last_voltage_ - 2.0);
65 LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
66 }
67
68 voltage_ = std::min(limit, voltage_);
69 voltage_ = std::max(-limit, voltage_);
70 U(0, 0) = voltage_ - old_voltage;
71 //LOG(DEBUG, "abc %f\n", X_hat(2, 0) - voltage_);
72 //LOG(DEBUG, "error %f\n", X_hat(0, 0) - R(0, 0));
73
74 last_voltage_ = voltage_;
75}
76
Austin Schuhcc0bf312014-02-09 00:39:29 -080077ClawMotor::ClawMotor(control_loops::ClawGroup *my_claw)
78 : aos::control_loops::ControlLoop<control_loops::ClawGroup>(my_claw),
Austin Schuh4b7b5d02014-02-10 21:20:34 -080079 has_top_claw_goal_(false),
80 top_claw_goal_(0.0),
81 top_claw_(MakeTopClawLoop()),
82 has_bottom_claw_goal_(false),
83 bottom_claw_goal_(0.0),
84 bottom_claw_(MakeBottomClawLoop()),
85 was_enabled_(false) {}
Austin Schuh3bb9a442014-02-02 16:01:45 -080086
Austin Schuh4b7b5d02014-02-10 21:20:34 -080087const int ZeroedStateFeedbackLoop::kZeroingMaxVoltage;
Austin Schuh3bb9a442014-02-02 16:01:45 -080088
89// Positive angle is up, and positive power is up.
Austin Schuhcc0bf312014-02-09 00:39:29 -080090void ClawMotor::RunIteration(const control_loops::ClawGroup::Goal *goal,
91 const control_loops::ClawGroup::Position *position,
92 control_loops::ClawGroup::Output *output,
Austin Schuh3bb9a442014-02-02 16:01:45 -080093 ::aos::control_loops::Status *status) {
94
95 // Disable the motors now so that all early returns will return with the
96 // motors disabled.
97 if (output) {
98 output->top_claw_voltage = 0;
99 output->bottom_claw_voltage = 0;
100 output->intake_voltage = 0;
101 }
102
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800103 // TODO(austin): Handle the disabled state and the disabled -> enabled
104 // transition in all of these states.
105 // TODO(austin): Handle zeroing while disabled.
106
107 // TODO(austin): Save all the counters so we know when something actually
108 // happens.
109 // TODO(austin): Helpers to find the position of the claw on an edge.
110
111 // TODO(austin): This may not be necesary because of the ControlLoop class.
112 ::aos::robot_state.FetchLatest();
113 if (::aos::robot_state.get() == nullptr) {
114 return;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800115 }
116
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800117 if (position) {
118 if (!has_top_claw_goal_) {
119 has_top_claw_goal_ = true;
120 top_claw_goal_ = position->top.position;
121 }
122 if (!has_bottom_claw_goal_) {
123 has_bottom_claw_goal_ = true;
124 bottom_claw_goal_ = position->bottom.position;
125 }
126
127 top_claw_.set_front_hall_effect_posedge_count(
128 position->top.front_hall_effect_posedge_count);
129 top_claw_.set_front_hall_effect_negedge_count(
130 position->top.front_hall_effect_negedge_count);
131 top_claw_.set_calibration_hall_effect_posedge_count(
132 position->top.calibration_hall_effect_posedge_count);
133 top_claw_.set_calibration_hall_effect_negedge_count(
134 position->top.calibration_hall_effect_negedge_count);
135 top_claw_.set_back_hall_effect_posedge_count(
136 position->top.back_hall_effect_posedge_count);
137 top_claw_.set_back_hall_effect_negedge_count(
138 position->top.back_hall_effect_negedge_count);
139
140 bottom_claw_.set_front_hall_effect_posedge_count(
141 position->bottom.front_hall_effect_posedge_count);
142 bottom_claw_.set_front_hall_effect_negedge_count(
143 position->bottom.front_hall_effect_negedge_count);
144 bottom_claw_.set_calibration_hall_effect_posedge_count(
145 position->bottom.calibration_hall_effect_posedge_count);
146 bottom_claw_.set_calibration_hall_effect_negedge_count(
147 position->bottom.calibration_hall_effect_negedge_count);
148 bottom_claw_.set_back_hall_effect_posedge_count(
149 position->bottom.back_hall_effect_posedge_count);
150 bottom_claw_.set_back_hall_effect_negedge_count(
151 position->bottom.back_hall_effect_negedge_count);
152 }
153
154 bool autonomous = ::aos::robot_state->autonomous;
155
156 if ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED &&
157 bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED) ||
158 (autonomous &&
159 ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
160 top_claw_.zeroing_state() ==
161 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION) &&
162 (bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
163 bottom_claw_.zeroing_state() ==
164 ZeroedStateFeedbackLoop::DISABLED_CALIBRATION)))) {
165 // Ready to use the claw.
166 // Limit the goals here.
167 } else if (top_claw_.zeroing_state() !=
168 ZeroedStateFeedbackLoop::UNKNOWN_POSITION &&
169 bottom_claw_.zeroing_state() !=
170 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
171 // Time to fine tune the zero.
172 // Limit the goals here.
173 if (bottom_claw_.zeroing_state() != ZeroedStateFeedbackLoop::CALIBRATED) {
174 } else {
175 }
176 } else {
177 if (!was_enabled_ && enabled) {
178
179 }
180 // Limit the goals here.
181 if (top_claw_.zeroing_state() ==
182 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
183 }
184 if (bottom_claw_.zeroing_state() ==
185 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
186 }
187
188 if (bottom_claw_.zeroing_state() !=
189 ZeroedStateFeedbackLoop::UNKNOWN_POSITION) {
190 // Time to slowly move back up to find any position to narrow down the
191 // zero.
192 } else {
193 // We don't know where either claw is. Slowly start moving down to find
194 // any hall effect.
195 LOG(INFO, "Unknown position\n");
196 }
197 }
198
199 // TODO(austin): Handle disabled.
Austin Schuh3bb9a442014-02-02 16:01:45 -0800200
201 if (position) {
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800202 top_claw_.Y << position->top.position;
203 bottom_claw_.Y << position->bottom.position;
204 }
205
206 // TODO(austin): ...
207 top_claw_.R << goal->bottom_angle + goal->seperation_angle, 0.0, 0.0;
208 bottom_claw_.R << goal->bottom_angle, 0.0, 0.0;
209
210 top_claw_.Update(position != nullptr, output == nullptr);
211 bottom_claw_.Update(position != nullptr, output == nullptr);
212
213 if (position) {
214 //LOG(DEBUG, "pos: %f hall: %s absolute: %f\n", position->top_position,
215 //position->top_calibration_hall_effect ? "true" : "false",
216 //zeroed_joint_.absolute_position());
Austin Schuh3bb9a442014-02-02 16:01:45 -0800217 }
218
219 if (output) {
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800220 output->top_claw_voltage = top_claw_.voltage();
221 output->bottom_claw_voltage = bottom_claw_.voltage();
Austin Schuh3bb9a442014-02-02 16:01:45 -0800222 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800223 status->done = false;
224 //::std::abs(zeroed_joint_.absolute_position() - goal->bottom_angle -
225 //goal->seperation_angle) < 0.004;
226
227 was_enabled_ = ::aos::robot_state->enabled;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800228}
229
230} // namespace control_loops
231} // namespace frc971