blob: 86875bb12d0cd36beaede4ea5c2306f451a3df52 [file] [log] [blame]
Brian Silverman17f503e2015-08-02 18:17:18 -07001#ifndef Y2014_CONTROL_LOOPS_CLAW_CLAW_H_
2#define Y2014_CONTROL_LOOPS_CLAW_CLAW_H_
3
4#include <memory>
5
6#include "aos/common/controls/control_loop.h"
7#include "aos/common/controls/polytope.h"
8#include "y2014/constants.h"
9#include "frc971/control_loops/state_feedback_loop.h"
10#include "frc971/control_loops/coerce_goal.h"
11#include "y2014/control_loops/claw/claw.q.h"
12#include "y2014/control_loops/claw/claw_motor_plant.h"
13#include "frc971/control_loops/hall_effect_tracker.h"
14
Austin Schuh24957102015-11-28 16:04:40 -080015namespace y2014 {
Brian Silverman17f503e2015-08-02 18:17:18 -070016namespace control_loops {
17namespace testing {
18class WindupClawTest;
19};
20
21// Note: Everything in this file assumes that there is a 1 cycle delay between
22// power being requested and it showing up at the motor. It assumes that
23// X_hat(2, 1) is the voltage being applied as well. It will go unstable if
24// that isn't true.
25
26class ClawLimitedLoop : public StateFeedbackLoop<4, 2, 2> {
27 public:
28 ClawLimitedLoop(StateFeedbackLoop<4, 2, 2> &&loop);
29 virtual void CapU();
30
31 void set_is_zeroing(bool is_zeroing) { is_zeroing_ = is_zeroing; }
32 void set_positions_known(bool top_known, bool bottom_known) {
33 top_known_ = top_known;
34 bottom_known_ = bottom_known;
35 }
36
37 void ChangeTopOffset(double doffset);
38 void ChangeBottomOffset(double doffset);
39
40 double uncapped_average_voltage() const { return uncapped_average_voltage_; }
41
42 private:
43 double uncapped_average_voltage_;
44 bool is_zeroing_;
45
46 bool top_known_ = false, bottom_known_ = false;
47
48 const ::aos::controls::HPolytope<2> U_Poly_, U_Poly_zeroing_;
49};
50
51class ClawMotor;
52
53// This class implements the CapU function correctly given all the extra
54// information that we know about from the wrist motor.
55// It does not have any zeroing logic in it, only logic to deal with a delta U
56// controller.
57class ZeroedStateFeedbackLoop {
58 public:
59 ZeroedStateFeedbackLoop(const char *name, ClawMotor *motor);
60
61 const static int kZeroingMaxVoltage = 5;
62
63 enum JointZeroingState {
64 // We don't know where the joint is at all.
65 UNKNOWN_POSITION,
66 // We have an approximate position for where the claw is using.
67 APPROXIMATE_CALIBRATION,
68 // We observed the calibration edge while disabled. This is good enough for
69 // autonomous mode.
70 DISABLED_CALIBRATION,
71 // Ready for use during teleop.
72 CALIBRATED
73 };
74
75 void set_zeroing_state(JointZeroingState zeroing_state) {
76 zeroing_state_ = zeroing_state;
77 }
78 JointZeroingState zeroing_state() const { return zeroing_state_; }
79
Austin Schuh24957102015-11-28 16:04:40 -080080 void SetPositionValues(const ::frc971::control_loops::HalfClawPosition &claw);
Brian Silverman17f503e2015-08-02 18:17:18 -070081
Austin Schuh24957102015-11-28 16:04:40 -080082 void Reset(const ::frc971::control_loops::HalfClawPosition &claw);
Brian Silverman17f503e2015-08-02 18:17:18 -070083
84 double absolute_position() const { return encoder() + offset(); }
85
Austin Schuh24957102015-11-28 16:04:40 -080086 const ::frc971::HallEffectTracker &front() const { return front_; }
87 const ::frc971::HallEffectTracker &calibration() const { return calibration_; }
88 const ::frc971::HallEffectTracker &back() const { return back_; }
Brian Silverman17f503e2015-08-02 18:17:18 -070089
90 bool any_hall_effect_changed() const {
91 return front().either_count_changed() ||
92 calibration().either_count_changed() ||
93 back().either_count_changed();
94 }
95 bool front_or_back_triggered() const {
96 return front().value() || back().value();
97 }
98 bool any_triggered() const {
99 return calibration().value() || front().value() || back().value();
100 }
101
102 double encoder() const { return encoder_; }
103 double last_encoder() const { return last_encoder_; }
104
105 double offset() const { return offset_; }
106
107 // Returns true if an edge was detected in the last cycle and then sets the
108 // edge_position to the absolute position of the edge.
109 bool GetPositionOfEdge(const constants::Values::Claws::Claw &claw,
110 double *edge_encoder, double *edge_angle);
111
Austin Schuh24957102015-11-28 16:04:40 -0800112 bool SawFilteredPosedge(const ::frc971::HallEffectTracker &this_sensor,
113 const ::frc971::HallEffectTracker &sensorA,
114 const ::frc971::HallEffectTracker &sensorB);
Brian Silverman17f503e2015-08-02 18:17:18 -0700115
Austin Schuh24957102015-11-28 16:04:40 -0800116 bool SawFilteredNegedge(const ::frc971::HallEffectTracker &this_sensor,
117 const ::frc971::HallEffectTracker &sensorA,
118 const ::frc971::HallEffectTracker &sensorB);
Brian Silverman17f503e2015-08-02 18:17:18 -0700119
120#undef COUNT_SETTER_GETTER
121
122 protected:
123 // The accumulated voltage to apply to the motor.
124 double offset_;
125 const char *name_;
126
127 ClawMotor *motor_;
128
Austin Schuh24957102015-11-28 16:04:40 -0800129 ::frc971::HallEffectTracker front_, calibration_, back_;
Brian Silverman17f503e2015-08-02 18:17:18 -0700130
131 JointZeroingState zeroing_state_;
Brian Silverman17f503e2015-08-02 18:17:18 -0700132 double min_hall_effect_on_angle_;
133 double max_hall_effect_on_angle_;
134 double min_hall_effect_off_angle_;
135 double max_hall_effect_off_angle_;
136 double encoder_;
137 double last_encoder_;
138 double last_on_encoder_;
139 double last_off_encoder_;
140 bool any_triggered_last_;
141
Austin Schuh24957102015-11-28 16:04:40 -0800142 const ::frc971::HallEffectTracker* posedge_filter_ = nullptr;
143 const ::frc971::HallEffectTracker* negedge_filter_ = nullptr;
Brian Silverman17f503e2015-08-02 18:17:18 -0700144
145 private:
146 // Does the edges of 1 sensor for GetPositionOfEdge.
147 bool DoGetPositionOfEdge(const constants::Values::Claws::AnglePair &angles,
148 double *edge_encoder, double *edge_angle,
Austin Schuh24957102015-11-28 16:04:40 -0800149 const ::frc971::HallEffectTracker &sensor,
150 const ::frc971::HallEffectTracker &sensorA,
151 const ::frc971::HallEffectTracker &sensorB,
Brian Silverman17f503e2015-08-02 18:17:18 -0700152 const char *hall_effect_name);
153};
154
155class TopZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
156 public:
157 TopZeroedStateFeedbackLoop(ClawMotor *motor)
158 : ZeroedStateFeedbackLoop("top", motor) {}
159 // Sets the calibration offset given the absolute angle and the corresponding
160 // encoder value.
161 void SetCalibration(double edge_encoder, double edge_angle);
162
163 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
164 JointZeroingState zeroing_state);
165 double ComputeCalibrationChange(double edge_encoder, double edge_angle);
166 void HandleCalibrationError(
167 const constants::Values::Claws::Claw &claw_values);
168};
169
170class BottomZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
171 public:
172 BottomZeroedStateFeedbackLoop(ClawMotor *motor)
173 : ZeroedStateFeedbackLoop("bottom", motor) {}
174 // Sets the calibration offset given the absolute angle and the corrisponding
175 // encoder value.
176 void SetCalibration(double edge_encoder, double edge_angle);
177
178 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
179 JointZeroingState zeroing_state);
180 double ComputeCalibrationChange(double edge_encoder, double edge_angle);
181 void HandleCalibrationError(
182 const constants::Values::Claws::Claw &claw_values);
183};
184
Austin Schuh24957102015-11-28 16:04:40 -0800185class ClawMotor
186 : public aos::controls::ControlLoop<::frc971::control_loops::ClawQueue> {
Brian Silverman17f503e2015-08-02 18:17:18 -0700187 public:
Austin Schuh24957102015-11-28 16:04:40 -0800188 explicit ClawMotor(::frc971::control_loops::ClawQueue *my_claw =
189 &::frc971::control_loops::claw_queue);
Brian Silverman17f503e2015-08-02 18:17:18 -0700190
191 // True if the state machine is ready.
192 bool capped_goal() const { return capped_goal_; }
193
194 double uncapped_average_voltage() const {
195 return claw_.uncapped_average_voltage();
196 }
197
198 // True if the claw is zeroing.
199 bool is_zeroing() const;
200
201 // True if the state machine is ready.
202 bool is_ready() const;
203
204 void ChangeTopOffset(double doffset);
205 void ChangeBottomOffset(double doffset);
206
207 enum CalibrationMode {
208 READY,
209 PREP_FINE_TUNE_TOP,
210 FINE_TUNE_TOP,
211 PREP_FINE_TUNE_BOTTOM,
212 FINE_TUNE_BOTTOM,
213 UNKNOWN_LOCATION
214 };
215
216 CalibrationMode mode() const { return mode_; }
217
218 protected:
Austin Schuh24957102015-11-28 16:04:40 -0800219 virtual void RunIteration(
220 const ::frc971::control_loops::ClawQueue::Goal *goal,
221 const ::frc971::control_loops::ClawQueue::Position *position,
222 ::frc971::control_loops::ClawQueue::Output *output,
223 ::frc971::control_loops::ClawQueue::Status *status);
Brian Silverman17f503e2015-08-02 18:17:18 -0700224
225 double top_absolute_position() const {
226 return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
227 }
228 double bottom_absolute_position() const { return claw_.X_hat(0, 0); }
229
230 private:
231 // Friend the test classes for acces to the internal state.
232 friend class testing::WindupClawTest;
233
234 // The zeroed joint to use.
235 bool has_top_claw_goal_;
236 double top_claw_goal_;
237 TopZeroedStateFeedbackLoop top_claw_;
238
239 bool has_bottom_claw_goal_;
240 double bottom_claw_goal_;
241 BottomZeroedStateFeedbackLoop bottom_claw_;
242
243 // The claw loop.
244 ClawLimitedLoop claw_;
245
246 bool was_enabled_;
247 bool doing_calibration_fine_tune_;
248
249 // The initial separation when disabled. Used as the safe separation
250 // distance.
251 double initial_separation_;
252
253 bool capped_goal_;
254 CalibrationMode mode_;
255
256 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
257};
258
259// Modifies the bottom and top goal such that they are within the limits and
260// their separation isn't too much or little.
261void LimitClawGoal(double *bottom_goal, double *top_goal,
Austin Schuh24957102015-11-28 16:04:40 -0800262 const constants::Values &values);
Brian Silverman17f503e2015-08-02 18:17:18 -0700263
264} // namespace control_loops
Austin Schuh24957102015-11-28 16:04:40 -0800265} // namespace y2014
Brian Silverman17f503e2015-08-02 18:17:18 -0700266
267#endif // Y2014_CONTROL_LOOPS_CLAW_CLAW_H_