blob: bef130b357392eca9e3bb680a5da7cd709e9e3fc [file] [log] [blame]
Austin Schuh3bb9a442014-02-02 16:01:45 -08001#ifndef FRC971_CONTROL_LOOPS_CLAW_CLAW_H_
2#define FRC971_CONTROL_LOOPS_CLAW_CLAW_H_
3
4#include <memory>
5
6#include "aos/common/control_loop/ControlLoop.h"
Austin Schuhf9286cd2014-02-11 00:51:09 -08007#include "frc971/constants.h"
Austin Schuh3bb9a442014-02-02 16:01:45 -08008#include "frc971/control_loops/state_feedback_loop.h"
9#include "frc971/control_loops/claw/claw.q.h"
Austin Schuhcda86af2014-02-16 16:16:39 -080010#include "frc971/control_loops/claw/claw_motor_plant.h"
Austin Schuh3bb9a442014-02-02 16:01:45 -080011
Austin Schuh3bb9a442014-02-02 16:01:45 -080012namespace frc971 {
13namespace control_loops {
14namespace testing {
15class ClawTest_NoWindupPositive_Test;
16class ClawTest_NoWindupNegative_Test;
17};
18
Austin Schuh4b7b5d02014-02-10 21:20:34 -080019// Note: Everything in this file assumes that there is a 1 cycle delay between
20// power being requested and it showing up at the motor. It assumes that
21// X_hat(2, 1) is the voltage being applied as well. It will go unstable if
22// that isn't true.
23
Austin Schuhcda86af2014-02-16 16:16:39 -080024class ClawLimitedLoop : public StateFeedbackLoop<4, 2, 2> {
25 public:
26 ClawLimitedLoop(StateFeedbackLoop<4, 2, 2> loop)
27 : StateFeedbackLoop<4, 2, 2>(loop) {}
28 virtual void CapU();
29
30 void ChangeTopOffset(double doffset);
31 void ChangeBottomOffset(double doffset);
32};
33
34class ClawMotor;
35
Austin Schuh4b7b5d02014-02-10 21:20:34 -080036// This class implements the CapU function correctly given all the extra
37// information that we know about from the wrist motor.
38// It does not have any zeroing logic in it, only logic to deal with a delta U
39// controller.
Austin Schuhcda86af2014-02-16 16:16:39 -080040class ZeroedStateFeedbackLoop {
Austin Schuh3bb9a442014-02-02 16:01:45 -080041 public:
Austin Schuhcda86af2014-02-16 16:16:39 -080042 ZeroedStateFeedbackLoop(const char *name, ClawMotor *motor)
43 : offset_(0.0),
44 name_(name),
45 motor_(motor),
Austin Schuh4b7b5d02014-02-10 21:20:34 -080046 front_hall_effect_posedge_count_(0.0),
47 previous_front_hall_effect_posedge_count_(0.0),
48 front_hall_effect_negedge_count_(0.0),
49 previous_front_hall_effect_negedge_count_(0.0),
50 calibration_hall_effect_posedge_count_(0.0),
51 previous_calibration_hall_effect_posedge_count_(0.0),
52 calibration_hall_effect_negedge_count_(0.0),
53 previous_calibration_hall_effect_negedge_count_(0.0),
54 back_hall_effect_posedge_count_(0.0),
55 previous_back_hall_effect_posedge_count_(0.0),
56 back_hall_effect_negedge_count_(0.0),
57 previous_back_hall_effect_negedge_count_(0.0),
Austin Schuhcda86af2014-02-16 16:16:39 -080058 front_hall_effect_(false),
59 calibration_hall_effect_(false),
60 back_hall_effect_(false),
Austin Schuhf9286cd2014-02-11 00:51:09 -080061 zeroing_state_(UNKNOWN_POSITION),
62 posedge_value_(0.0),
63 negedge_value_(0.0),
64 encoder_(0.0),
Austin Schuhcda86af2014-02-16 16:16:39 -080065 last_encoder_(0.0) {}
Austin Schuh3bb9a442014-02-02 16:01:45 -080066
Austin Schuh4b7b5d02014-02-10 21:20:34 -080067 const static int kZeroingMaxVoltage = 5;
Austin Schuh3bb9a442014-02-02 16:01:45 -080068
Austin Schuh4b7b5d02014-02-10 21:20:34 -080069 enum JointZeroingState {
70 // We don't know where the joint is at all.
71 UNKNOWN_POSITION,
72 // We have an approximate position for where the claw is using.
73 APPROXIMATE_CALIBRATION,
74 // We observed the calibration edge while disabled. This is good enough for
75 // autonomous mode.
76 DISABLED_CALIBRATION,
77 // Ready for use during teleop.
78 CALIBRATED
79 };
80
81 void set_zeroing_state(JointZeroingState zeroing_state) {
82 zeroing_state_ = zeroing_state;
83 }
84 JointZeroingState zeroing_state() const { return zeroing_state_; }
85
Austin Schuh4339ebb2014-02-11 00:56:44 -080086 void SetPositionValues(const HalfClawPosition &claw) {
Austin Schuhf9286cd2014-02-11 00:51:09 -080087 set_front_hall_effect_posedge_count(claw.front_hall_effect_posedge_count);
88 set_front_hall_effect_negedge_count(claw.front_hall_effect_negedge_count);
89 set_calibration_hall_effect_posedge_count(
90 claw.calibration_hall_effect_posedge_count);
91 set_calibration_hall_effect_negedge_count(
92 claw.calibration_hall_effect_negedge_count);
93 set_back_hall_effect_posedge_count(claw.back_hall_effect_posedge_count);
94 set_back_hall_effect_negedge_count(claw.back_hall_effect_negedge_count);
95
96 posedge_value_ = claw.posedge_value;
97 negedge_value_ = claw.negedge_value;
Austin Schuhcda86af2014-02-16 16:16:39 -080098 last_encoder_ = encoder_;
99 encoder_ = claw.position;
100
101 front_hall_effect_ = claw.front_hall_effect;
102 calibration_hall_effect_ = claw.calibration_hall_effect;
103 back_hall_effect_ = claw.back_hall_effect;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800104 }
105
Austin Schuhcda86af2014-02-16 16:16:39 -0800106 double absolute_position() const { return encoder() + offset(); }
107
108 bool front_hall_effect() const { return front_hall_effect_; }
109 bool calibration_hall_effect() const { return calibration_hall_effect_; }
110 bool back_hall_effect() const { return back_hall_effect_; }
111
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800112#define COUNT_SETTER_GETTER(variable) \
113 void set_##variable(int32_t value) { \
114 previous_##variable##_ = variable##_; \
115 variable##_ = value; \
116 } \
117 int32_t variable() const { return variable##_; } \
118 bool variable##_changed() const { \
119 return previous_##variable##_ != variable##_; \
120 }
121
Austin Schuhf9286cd2014-02-11 00:51:09 -0800122 // TODO(austin): Pull all this out of the new sub structure.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800123 COUNT_SETTER_GETTER(front_hall_effect_posedge_count);
124 COUNT_SETTER_GETTER(front_hall_effect_negedge_count);
125 COUNT_SETTER_GETTER(calibration_hall_effect_posedge_count);
126 COUNT_SETTER_GETTER(calibration_hall_effect_negedge_count);
127 COUNT_SETTER_GETTER(back_hall_effect_posedge_count);
128 COUNT_SETTER_GETTER(back_hall_effect_negedge_count);
129
130 bool any_hall_effect_changed() const {
131 return front_hall_effect_posedge_count_changed() ||
132 front_hall_effect_negedge_count_changed() ||
133 calibration_hall_effect_posedge_count_changed() ||
134 calibration_hall_effect_negedge_count_changed() ||
135 back_hall_effect_posedge_count_changed() ||
136 back_hall_effect_negedge_count_changed();
137 }
138
Austin Schuhf9286cd2014-02-11 00:51:09 -0800139 double encoder() const { return encoder_; }
140 double last_encoder() const { return last_encoder_; }
141
Austin Schuhcda86af2014-02-16 16:16:39 -0800142 double offset() const { return offset_; }
143
Austin Schuhf9286cd2014-02-11 00:51:09 -0800144 // Returns true if an edge was detected in the last cycle and then sets the
145 // edge_position to the absolute position of the edge.
Austin Schuhd27931c2014-02-16 19:18:20 -0800146 bool GetPositionOfEdge(const constants::Values::Claws::Claw &claw,
Austin Schuhf9286cd2014-02-11 00:51:09 -0800147 double *edge_encoder, double *edge_angle);
148
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800149#undef COUNT_SETTER_GETTER
150
Austin Schuhcda86af2014-02-16 16:16:39 -0800151 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800152 // The accumulated voltage to apply to the motor.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800153 double offset_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800154 const char *name_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800155
Austin Schuhcda86af2014-02-16 16:16:39 -0800156 ClawMotor *motor_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800157
158 int32_t front_hall_effect_posedge_count_;
159 int32_t previous_front_hall_effect_posedge_count_;
160 int32_t front_hall_effect_negedge_count_;
161 int32_t previous_front_hall_effect_negedge_count_;
162 int32_t calibration_hall_effect_posedge_count_;
163 int32_t previous_calibration_hall_effect_posedge_count_;
164 int32_t calibration_hall_effect_negedge_count_;
165 int32_t previous_calibration_hall_effect_negedge_count_;
166 int32_t back_hall_effect_posedge_count_;
167 int32_t previous_back_hall_effect_posedge_count_;
168 int32_t back_hall_effect_negedge_count_;
169 int32_t previous_back_hall_effect_negedge_count_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800170 bool front_hall_effect_;
171 bool calibration_hall_effect_;
172 bool back_hall_effect_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800173
174 JointZeroingState zeroing_state_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800175 double posedge_value_;
176 double negedge_value_;
177 double encoder_;
178 double last_encoder_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800179};
180
Austin Schuhcda86af2014-02-16 16:16:39 -0800181class TopZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
182 public:
183 TopZeroedStateFeedbackLoop(ClawMotor *motor)
184 : ZeroedStateFeedbackLoop("top", motor) {}
185 // Sets the calibration offset given the absolute angle and the corrisponding
186 // encoder value.
187 void SetCalibration(double edge_encoder, double edge_angle);
188
Austin Schuhd27931c2014-02-16 19:18:20 -0800189 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuhcda86af2014-02-16 16:16:39 -0800190 JointZeroingState zeroing_state) {
191 double edge_encoder;
192 double edge_angle;
193 if (GetPositionOfEdge(claw_values, &edge_encoder, &edge_angle)) {
194 LOG(INFO, "Calibration edge.\n");
195 SetCalibration(edge_encoder, edge_angle);
196 set_zeroing_state(zeroing_state);
197 return true;
198 }
199 return false;
200 }
201};
202
203class BottomZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
204 public:
205 BottomZeroedStateFeedbackLoop(ClawMotor *motor)
206 : ZeroedStateFeedbackLoop("bottom", motor) {}
207 // Sets the calibration offset given the absolute angle and the corrisponding
208 // encoder value.
209 void SetCalibration(double edge_encoder, double edge_angle);
210
Austin Schuhd27931c2014-02-16 19:18:20 -0800211 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuhcda86af2014-02-16 16:16:39 -0800212 JointZeroingState zeroing_state) {
213 double edge_encoder;
214 double edge_angle;
215 if (GetPositionOfEdge(claw_values, &edge_encoder, &edge_angle)) {
216 LOG(INFO, "Calibration edge.\n");
217 SetCalibration(edge_encoder, edge_angle);
218 set_zeroing_state(zeroing_state);
219 return true;
220 }
221 return false;
222 }
223};
Ben Fredrickson9b388422014-02-13 06:15:31 +0000224
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800225class ClawMotor
226 : public aos::control_loops::ControlLoop<control_loops::ClawGroup> {
227 public:
228 explicit ClawMotor(control_loops::ClawGroup *my_claw =
229 &control_loops::claw_queue_group);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800230
231 // True if the state machine is ready.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800232 bool is_ready() const { return false; }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800233
Austin Schuhcda86af2014-02-16 16:16:39 -0800234 void ChangeTopOffset(double doffset);
235 void ChangeBottomOffset(double doffset);
236
Austin Schuh3bb9a442014-02-02 16:01:45 -0800237 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800238 virtual void RunIteration(const control_loops::ClawGroup::Goal *goal,
239 const control_loops::ClawGroup::Position *position,
240 control_loops::ClawGroup::Output *output,
241 ::aos::control_loops::Status *status);
242
Austin Schuhcda86af2014-02-16 16:16:39 -0800243 double top_absolute_position() const {
244 return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
245 }
246 double bottom_absolute_position() const { return claw_.X_hat(0, 0); }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800247
248 private:
249 // Friend the test classes for acces to the internal state.
250 friend class testing::ClawTest_NoWindupPositive_Test;
251 friend class testing::ClawTest_NoWindupNegative_Test;
252
253 // The zeroed joint to use.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800254 bool has_top_claw_goal_;
255 double top_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800256 TopZeroedStateFeedbackLoop top_claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800257
258 bool has_bottom_claw_goal_;
259 double bottom_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800260 BottomZeroedStateFeedbackLoop bottom_claw_;
261
262 // The claw loop.
263 ClawLimitedLoop claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800264
265 bool was_enabled_;
Ben Fredrickson9b388422014-02-13 06:15:31 +0000266 bool doing_calibration_fine_tune_;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800267
Austin Schuhcda86af2014-02-16 16:16:39 -0800268 // The initial seperation when disabled. Used as the safe seperation
269 // distance.
270 double initial_seperation_;
271
Austin Schuh3bb9a442014-02-02 16:01:45 -0800272 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
273};
274
275} // namespace control_loops
276} // namespace frc971
277
278#endif // FRC971_CONTROL_LOOPS_CLAW_CLAW_H_