blob: 082ddce9c73fea867c425d7d3b9ac2ea23df14f2 [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
John Park33858a32018-09-28 23:05:48 -07006#include "aos/controls/control_loop.h"
7#include "aos/controls/polytope.h"
Brian Silverman17f503e2015-08-02 18:17:18 -07008#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
Brian Silvermanb601d892015-12-20 18:24:38 -050080 void SetPositionValues(const ::y2014::control_loops::HalfClawPosition &claw);
Brian Silverman17f503e2015-08-02 18:17:18 -070081
Brian Silvermanb601d892015-12-20 18:24:38 -050082 void Reset(const ::y2014::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
Brian Silvermanb601d892015-12-20 18:24:38 -0500186 : public aos::controls::ControlLoop<::y2014::control_loops::ClawQueue> {
Brian Silverman17f503e2015-08-02 18:17:18 -0700187 public:
Austin Schuh55a13dc2019-01-27 22:39:03 -0800188 explicit ClawMotor(
189 ::aos::EventLoop *event_loop,
190 const ::std::string &name = ".y2014.control_loops.claw_queue");
Brian Silverman17f503e2015-08-02 18:17:18 -0700191
192 // True if the state machine is ready.
193 bool capped_goal() const { return capped_goal_; }
194
195 double uncapped_average_voltage() const {
196 return claw_.uncapped_average_voltage();
197 }
198
199 // True if the claw is zeroing.
200 bool is_zeroing() const;
201
202 // True if the state machine is ready.
203 bool is_ready() const;
204
205 void ChangeTopOffset(double doffset);
206 void ChangeBottomOffset(double doffset);
207
208 enum CalibrationMode {
209 READY,
210 PREP_FINE_TUNE_TOP,
211 FINE_TUNE_TOP,
212 PREP_FINE_TUNE_BOTTOM,
213 FINE_TUNE_BOTTOM,
214 UNKNOWN_LOCATION
215 };
216
217 CalibrationMode mode() const { return mode_; }
218
219 protected:
Austin Schuh24957102015-11-28 16:04:40 -0800220 virtual void RunIteration(
Brian Silvermanb601d892015-12-20 18:24:38 -0500221 const ::y2014::control_loops::ClawQueue::Goal *goal,
222 const ::y2014::control_loops::ClawQueue::Position *position,
223 ::y2014::control_loops::ClawQueue::Output *output,
224 ::y2014::control_loops::ClawQueue::Status *status);
Brian Silverman17f503e2015-08-02 18:17:18 -0700225
226 double top_absolute_position() const {
227 return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
228 }
229 double bottom_absolute_position() const { return claw_.X_hat(0, 0); }
230
231 private:
232 // Friend the test classes for acces to the internal state.
233 friend class testing::WindupClawTest;
234
235 // The zeroed joint to use.
236 bool has_top_claw_goal_;
237 double top_claw_goal_;
238 TopZeroedStateFeedbackLoop top_claw_;
239
240 bool has_bottom_claw_goal_;
241 double bottom_claw_goal_;
242 BottomZeroedStateFeedbackLoop bottom_claw_;
243
244 // The claw loop.
245 ClawLimitedLoop claw_;
246
247 bool was_enabled_;
248 bool doing_calibration_fine_tune_;
249
250 // The initial separation when disabled. Used as the safe separation
251 // distance.
252 double initial_separation_;
253
254 bool capped_goal_;
255 CalibrationMode mode_;
256
257 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
258};
259
260// Modifies the bottom and top goal such that they are within the limits and
261// their separation isn't too much or little.
262void LimitClawGoal(double *bottom_goal, double *top_goal,
Austin Schuh24957102015-11-28 16:04:40 -0800263 const constants::Values &values);
Brian Silverman17f503e2015-08-02 18:17:18 -0700264
265} // namespace control_loops
Austin Schuh24957102015-11-28 16:04:40 -0800266} // namespace y2014
Brian Silverman17f503e2015-08-02 18:17:18 -0700267
268#endif // Y2014_CONTROL_LOOPS_CLAW_CLAW_H_