blob: 943e0ad784a28b98323c4547598276afbb8c157a [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
Brian Silverman17f503e2015-08-02 18:17:18 -07006#include "frc971/control_loops/coerce_goal.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07007#include "frc971/control_loops/control_loop.h"
Brian Silverman17f503e2015-08-02 18:17:18 -07008#include "frc971/control_loops/hall_effect_tracker.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07009#include "frc971/control_loops/polytope.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070010#include "frc971/control_loops/state_feedback_loop.h"
11#include "y2014/constants.h"
12#include "y2014/control_loops/claw/claw_goal_generated.h"
13#include "y2014/control_loops/claw/claw_motor_plant.h"
14#include "y2014/control_loops/claw/claw_output_generated.h"
15#include "y2014/control_loops/claw/claw_position_generated.h"
16#include "y2014/control_loops/claw/claw_status_generated.h"
Brian Silverman17f503e2015-08-02 18:17:18 -070017
Austin Schuh24957102015-11-28 16:04:40 -080018namespace y2014 {
Brian Silverman17f503e2015-08-02 18:17:18 -070019namespace control_loops {
Alex Perrycb7da4b2019-08-28 19:35:56 -070020namespace claw {
Brian Silverman17f503e2015-08-02 18:17:18 -070021namespace testing {
22class WindupClawTest;
23};
24
25// Note: Everything in this file assumes that there is a 1 cycle delay between
26// power being requested and it showing up at the motor. It assumes that
27// X_hat(2, 1) is the voltage being applied as well. It will go unstable if
28// that isn't true.
29
30class ClawLimitedLoop : public StateFeedbackLoop<4, 2, 2> {
31 public:
32 ClawLimitedLoop(StateFeedbackLoop<4, 2, 2> &&loop);
33 virtual void CapU();
34
35 void set_is_zeroing(bool is_zeroing) { is_zeroing_ = is_zeroing; }
36 void set_positions_known(bool top_known, bool bottom_known) {
37 top_known_ = top_known;
38 bottom_known_ = bottom_known;
39 }
40
41 void ChangeTopOffset(double doffset);
42 void ChangeBottomOffset(double doffset);
43
44 double uncapped_average_voltage() const { return uncapped_average_voltage_; }
45
46 private:
47 double uncapped_average_voltage_;
48 bool is_zeroing_;
49
50 bool top_known_ = false, bottom_known_ = false;
51
James Kuszmaul61750662021-06-21 21:32:33 -070052 const ::frc971::controls::HPolytope<2> U_Poly_, U_Poly_zeroing_;
Brian Silverman17f503e2015-08-02 18:17:18 -070053};
54
55class ClawMotor;
56
57// This class implements the CapU function correctly given all the extra
58// information that we know about from the wrist motor.
59// It does not have any zeroing logic in it, only logic to deal with a delta U
60// controller.
61class ZeroedStateFeedbackLoop {
62 public:
63 ZeroedStateFeedbackLoop(const char *name, ClawMotor *motor);
64
65 const static int kZeroingMaxVoltage = 5;
66
67 enum JointZeroingState {
68 // We don't know where the joint is at all.
69 UNKNOWN_POSITION,
70 // We have an approximate position for where the claw is using.
71 APPROXIMATE_CALIBRATION,
72 // We observed the calibration edge while disabled. This is good enough for
73 // autonomous mode.
74 DISABLED_CALIBRATION,
75 // Ready for use during teleop.
76 CALIBRATED
77 };
78
79 void set_zeroing_state(JointZeroingState zeroing_state) {
80 zeroing_state_ = zeroing_state;
81 }
82 JointZeroingState zeroing_state() const { return zeroing_state_; }
83
Alex Perrycb7da4b2019-08-28 19:35:56 -070084 void SetPositionValues(const HalfClawPosition *claw);
Brian Silverman17f503e2015-08-02 18:17:18 -070085
Alex Perrycb7da4b2019-08-28 19:35:56 -070086 void Reset(const HalfClawPosition *claw);
Brian Silverman17f503e2015-08-02 18:17:18 -070087
88 double absolute_position() const { return encoder() + offset(); }
89
Austin Schuh24957102015-11-28 16:04:40 -080090 const ::frc971::HallEffectTracker &front() const { return front_; }
James Kuszmaul61750662021-06-21 21:32:33 -070091 const ::frc971::HallEffectTracker &calibration() const {
92 return calibration_;
93 }
Austin Schuh24957102015-11-28 16:04:40 -080094 const ::frc971::HallEffectTracker &back() const { return back_; }
Brian Silverman17f503e2015-08-02 18:17:18 -070095
96 bool any_hall_effect_changed() const {
97 return front().either_count_changed() ||
98 calibration().either_count_changed() ||
99 back().either_count_changed();
100 }
101 bool front_or_back_triggered() const {
102 return front().value() || back().value();
103 }
104 bool any_triggered() const {
105 return calibration().value() || front().value() || back().value();
106 }
107
108 double encoder() const { return encoder_; }
109 double last_encoder() const { return last_encoder_; }
110
111 double offset() const { return offset_; }
112
113 // Returns true if an edge was detected in the last cycle and then sets the
114 // edge_position to the absolute position of the edge.
115 bool GetPositionOfEdge(const constants::Values::Claws::Claw &claw,
116 double *edge_encoder, double *edge_angle);
117
Austin Schuh24957102015-11-28 16:04:40 -0800118 bool SawFilteredPosedge(const ::frc971::HallEffectTracker &this_sensor,
119 const ::frc971::HallEffectTracker &sensorA,
120 const ::frc971::HallEffectTracker &sensorB);
Brian Silverman17f503e2015-08-02 18:17:18 -0700121
Austin Schuh24957102015-11-28 16:04:40 -0800122 bool SawFilteredNegedge(const ::frc971::HallEffectTracker &this_sensor,
123 const ::frc971::HallEffectTracker &sensorA,
124 const ::frc971::HallEffectTracker &sensorB);
Brian Silverman17f503e2015-08-02 18:17:18 -0700125
126#undef COUNT_SETTER_GETTER
127
128 protected:
129 // The accumulated voltage to apply to the motor.
130 double offset_;
131 const char *name_;
132
133 ClawMotor *motor_;
134
Austin Schuh24957102015-11-28 16:04:40 -0800135 ::frc971::HallEffectTracker front_, calibration_, back_;
Brian Silverman17f503e2015-08-02 18:17:18 -0700136
137 JointZeroingState zeroing_state_;
Brian Silverman17f503e2015-08-02 18:17:18 -0700138 double min_hall_effect_on_angle_;
139 double max_hall_effect_on_angle_;
140 double min_hall_effect_off_angle_;
141 double max_hall_effect_off_angle_;
142 double encoder_;
143 double last_encoder_;
144 double last_on_encoder_;
145 double last_off_encoder_;
146 bool any_triggered_last_;
147
James Kuszmaul61750662021-06-21 21:32:33 -0700148 const ::frc971::HallEffectTracker *posedge_filter_ = nullptr;
149 const ::frc971::HallEffectTracker *negedge_filter_ = nullptr;
Brian Silverman17f503e2015-08-02 18:17:18 -0700150
151 private:
152 // Does the edges of 1 sensor for GetPositionOfEdge.
153 bool DoGetPositionOfEdge(const constants::Values::Claws::AnglePair &angles,
154 double *edge_encoder, double *edge_angle,
Austin Schuh24957102015-11-28 16:04:40 -0800155 const ::frc971::HallEffectTracker &sensor,
156 const ::frc971::HallEffectTracker &sensorA,
157 const ::frc971::HallEffectTracker &sensorB,
Brian Silverman17f503e2015-08-02 18:17:18 -0700158 const char *hall_effect_name);
159};
160
161class TopZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
162 public:
163 TopZeroedStateFeedbackLoop(ClawMotor *motor)
164 : ZeroedStateFeedbackLoop("top", motor) {}
165 // Sets the calibration offset given the absolute angle and the corresponding
166 // encoder value.
167 void SetCalibration(double edge_encoder, double edge_angle);
168
169 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
170 JointZeroingState zeroing_state);
171 double ComputeCalibrationChange(double edge_encoder, double edge_angle);
172 void HandleCalibrationError(
173 const constants::Values::Claws::Claw &claw_values);
174};
175
176class BottomZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
177 public:
178 BottomZeroedStateFeedbackLoop(ClawMotor *motor)
179 : ZeroedStateFeedbackLoop("bottom", motor) {}
180 // Sets the calibration offset given the absolute angle and the corrisponding
181 // encoder value.
182 void SetCalibration(double edge_encoder, double edge_angle);
183
184 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
185 JointZeroingState zeroing_state);
186 double ComputeCalibrationChange(double edge_encoder, double edge_angle);
187 void HandleCalibrationError(
188 const constants::Values::Claws::Claw &claw_values);
189};
190
Austin Schuh24957102015-11-28 16:04:40 -0800191class ClawMotor
James Kuszmaul61750662021-06-21 21:32:33 -0700192 : public frc971::controls::ControlLoop<Goal, Position, Status, Output> {
Brian Silverman17f503e2015-08-02 18:17:18 -0700193 public:
Alex Perrycb7da4b2019-08-28 19:35:56 -0700194 explicit ClawMotor(::aos::EventLoop *event_loop,
195 const ::std::string &name = "/claw");
Brian Silverman17f503e2015-08-02 18:17:18 -0700196
197 // True if the state machine is ready.
198 bool capped_goal() const { return capped_goal_; }
199
200 double uncapped_average_voltage() const {
201 return claw_.uncapped_average_voltage();
202 }
203
204 // True if the claw is zeroing.
205 bool is_zeroing() const;
206
207 // True if the state machine is ready.
208 bool is_ready() const;
209
210 void ChangeTopOffset(double doffset);
211 void ChangeBottomOffset(double doffset);
212
213 enum CalibrationMode {
214 READY,
215 PREP_FINE_TUNE_TOP,
216 FINE_TUNE_TOP,
217 PREP_FINE_TUNE_BOTTOM,
218 FINE_TUNE_BOTTOM,
219 UNKNOWN_LOCATION
220 };
221
222 CalibrationMode mode() const { return mode_; }
223
224 protected:
Alex Perrycb7da4b2019-08-28 19:35:56 -0700225 virtual void RunIteration(const Goal *goal, const Position *position,
226 aos::Sender<Output>::Builder *output,
227 aos::Sender<Status>::Builder *status);
Brian Silverman17f503e2015-08-02 18:17:18 -0700228
229 double top_absolute_position() const {
230 return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
231 }
232 double bottom_absolute_position() const { return claw_.X_hat(0, 0); }
233
234 private:
235 // Friend the test classes for acces to the internal state.
236 friend class testing::WindupClawTest;
237
238 // The zeroed joint to use.
239 bool has_top_claw_goal_;
240 double top_claw_goal_;
241 TopZeroedStateFeedbackLoop top_claw_;
242
243 bool has_bottom_claw_goal_;
244 double bottom_claw_goal_;
245 BottomZeroedStateFeedbackLoop bottom_claw_;
246
247 // The claw loop.
248 ClawLimitedLoop claw_;
249
250 bool was_enabled_;
251 bool doing_calibration_fine_tune_;
252
253 // The initial separation when disabled. Used as the safe separation
254 // distance.
255 double initial_separation_;
256
257 bool capped_goal_;
258 CalibrationMode mode_;
259
260 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
261};
262
263// Modifies the bottom and top goal such that they are within the limits and
264// their separation isn't too much or little.
265void LimitClawGoal(double *bottom_goal, double *top_goal,
Austin Schuh24957102015-11-28 16:04:40 -0800266 const constants::Values &values);
Brian Silverman17f503e2015-08-02 18:17:18 -0700267
Alex Perrycb7da4b2019-08-28 19:35:56 -0700268} // namespace claw
Brian Silverman17f503e2015-08-02 18:17:18 -0700269} // namespace control_loops
Austin Schuh24957102015-11-28 16:04:40 -0800270} // namespace y2014
Brian Silverman17f503e2015-08-02 18:17:18 -0700271
272#endif // Y2014_CONTROL_LOOPS_CLAW_CLAW_H_