blob: 175657c379dade36c6ba25fffb8a5137c9a568f4 [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
Briana6553ed2014-04-02 21:26:46 -07006#include "aos/common/controls/control_loop.h"
7#include "aos/common/controls/polytope.h"
Austin Schuhf9286cd2014-02-11 00:51:09 -08008#include "frc971/constants.h"
Austin Schuh3bb9a442014-02-02 16:01:45 -08009#include "frc971/control_loops/state_feedback_loop.h"
James Kuszmaulf63b0ae2014-03-25 16:52:11 -070010#include "frc971/control_loops/coerce_goal.h"
Austin Schuh3bb9a442014-02-02 16:01:45 -080011#include "frc971/control_loops/claw/claw.q.h"
Austin Schuhcda86af2014-02-16 16:16:39 -080012#include "frc971/control_loops/claw/claw_motor_plant.h"
Brian Silvermane0a95462014-02-17 00:41:09 -080013#include "frc971/control_loops/hall_effect_tracker.h"
Austin Schuh3bb9a442014-02-02 16:01:45 -080014
Austin Schuh3bb9a442014-02-02 16:01:45 -080015namespace frc971 {
16namespace control_loops {
17namespace testing {
Austin Schuhe7f90d12014-02-17 00:48:25 -080018class WindupClawTest;
Austin Schuh3bb9a442014-02-02 16:01:45 -080019};
20
Austin Schuh4b7b5d02014-02-10 21:20:34 -080021// 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
Austin Schuhcda86af2014-02-16 16:16:39 -080026class ClawLimitedLoop : public StateFeedbackLoop<4, 2, 2> {
27 public:
Brian Silverman0a151c92014-05-02 15:28:44 -070028 ClawLimitedLoop(StateFeedbackLoop<4, 2, 2> &&loop);
Austin Schuhcda86af2014-02-16 16:16:39 -080029 virtual void CapU();
30
Austin Schuh4cb047f2014-02-16 21:10:19 -080031 void set_is_zeroing(bool is_zeroing) { is_zeroing_ = is_zeroing; }
Brian Silvermaned9df2f2014-04-05 07:07:15 -070032 void set_positions_known(bool top_known, bool bottom_known) {
33 top_known_ = top_known;
34 bottom_known_ = bottom_known;
35 }
Austin Schuh4cb047f2014-02-16 21:10:19 -080036
Austin Schuhcda86af2014-02-16 16:16:39 -080037 void ChangeTopOffset(double doffset);
38 void ChangeBottomOffset(double doffset);
Austin Schuh4cb047f2014-02-16 21:10:19 -080039
40 double uncapped_average_voltage() const { return uncapped_average_voltage_; }
41
42 private:
43 double uncapped_average_voltage_;
44 bool is_zeroing_;
James Kuszmaulf63b0ae2014-03-25 16:52:11 -070045
Brian Silvermaned9df2f2014-04-05 07:07:15 -070046 bool top_known_ = false, bottom_known_ = false;
47
Brian Silverman6dd2c532014-03-29 23:34:39 -070048 const ::aos::controls::HPolytope<2> U_Poly_, U_Poly_zeroing_;
Austin Schuhcda86af2014-02-16 16:16:39 -080049};
50
51class ClawMotor;
52
Austin Schuh4b7b5d02014-02-10 21:20:34 -080053// 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.
Austin Schuhcda86af2014-02-16 16:16:39 -080057class ZeroedStateFeedbackLoop {
Austin Schuh3bb9a442014-02-02 16:01:45 -080058 public:
Austin Schuh27b8fb12014-02-22 15:10:05 -080059 ZeroedStateFeedbackLoop(const char *name, ClawMotor *motor);
Austin Schuh3bb9a442014-02-02 16:01:45 -080060
Austin Schuh4b7b5d02014-02-10 21:20:34 -080061 const static int kZeroingMaxVoltage = 5;
Austin Schuh3bb9a442014-02-02 16:01:45 -080062
Austin Schuh4b7b5d02014-02-10 21:20:34 -080063 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 Schuh27b8fb12014-02-22 15:10:05 -080080 void SetPositionValues(const HalfClawPosition &claw);
Austin Schuhf9286cd2014-02-11 00:51:09 -080081
Austin Schuh27b8fb12014-02-22 15:10:05 -080082 void Reset(const HalfClawPosition &claw);
Ben Fredricksonade3eab2014-02-22 07:30:53 +000083
Austin Schuhcda86af2014-02-16 16:16:39 -080084 double absolute_position() const { return encoder() + offset(); }
85
Brian Silvermane0a95462014-02-17 00:41:09 -080086 const HallEffectTracker &front() const { return front_; }
87 const HallEffectTracker &calibration() const { return calibration_; }
88 const HallEffectTracker &back() const { return back_; }
Austin Schuh4b7b5d02014-02-10 21:20:34 -080089
90 bool any_hall_effect_changed() const {
Brian Silvermane0a95462014-02-17 00:41:09 -080091 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();
Austin Schuh4b7b5d02014-02-10 21:20:34 -080097 }
Austin Schuh27b8fb12014-02-22 15:10:05 -080098 bool any_triggered() const {
99 return calibration().value() || front().value() || back().value();
100 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800101
Austin Schuhf9286cd2014-02-11 00:51:09 -0800102 double encoder() const { return encoder_; }
103 double last_encoder() const { return last_encoder_; }
104
Austin Schuhcda86af2014-02-16 16:16:39 -0800105 double offset() const { return offset_; }
106
Austin Schuhf9286cd2014-02-11 00:51:09 -0800107 // 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.
Austin Schuhd27931c2014-02-16 19:18:20 -0800109 bool GetPositionOfEdge(const constants::Values::Claws::Claw &claw,
Austin Schuhf9286cd2014-02-11 00:51:09 -0800110 double *edge_encoder, double *edge_angle);
111
Ben Fredricksoneaecbbb2014-02-23 12:12:03 +0000112 bool SawFilteredPosedge(const HallEffectTracker &this_sensor,
113 const HallEffectTracker &sensorA,
114 const HallEffectTracker &sensorB);
115
116 bool SawFilteredNegedge(const HallEffectTracker &this_sensor,
117 const HallEffectTracker &sensorA,
118 const HallEffectTracker &sensorB);
119
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800120#undef COUNT_SETTER_GETTER
121
Austin Schuhcda86af2014-02-16 16:16:39 -0800122 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800123 // The accumulated voltage to apply to the motor.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800124 double offset_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800125 const char *name_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800126
Austin Schuhcda86af2014-02-16 16:16:39 -0800127 ClawMotor *motor_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800128
Brian Silvermane0a95462014-02-17 00:41:09 -0800129 HallEffectTracker front_, calibration_, back_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800130
131 JointZeroingState zeroing_state_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800132 double posedge_value_;
133 double negedge_value_;
Austin Schuh27b8fb12014-02-22 15:10:05 -0800134 double min_hall_effect_on_angle_;
135 double max_hall_effect_on_angle_;
136 double min_hall_effect_off_angle_;
137 double max_hall_effect_off_angle_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800138 double encoder_;
139 double last_encoder_;
Austin Schuhf84a1302014-02-19 00:23:30 -0800140 double last_on_encoder_;
141 double last_off_encoder_;
Austin Schuh27b8fb12014-02-22 15:10:05 -0800142 bool any_triggered_last_;
Brian Silvermane0a95462014-02-17 00:41:09 -0800143
Ben Fredricksoneaecbbb2014-02-23 12:12:03 +0000144 const HallEffectTracker* posedge_filter_ = nullptr;
145 const HallEffectTracker* negedge_filter_ = nullptr;
146
Brian Silvermane0a95462014-02-17 00:41:09 -0800147 private:
148 // Does the edges of 1 sensor for GetPositionOfEdge.
149 bool DoGetPositionOfEdge(const constants::Values::Claws::AnglePair &angles,
150 double *edge_encoder, double *edge_angle,
151 const HallEffectTracker &sensor,
Ben Fredricksoneaecbbb2014-02-23 12:12:03 +0000152 const HallEffectTracker &sensorA,
153 const HallEffectTracker &sensorB,
Brian Silvermane0a95462014-02-17 00:41:09 -0800154 const char *hall_effect_name);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800155};
156
Austin Schuhcda86af2014-02-16 16:16:39 -0800157class TopZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
158 public:
159 TopZeroedStateFeedbackLoop(ClawMotor *motor)
160 : ZeroedStateFeedbackLoop("top", motor) {}
161 // Sets the calibration offset given the absolute angle and the corrisponding
162 // encoder value.
163 void SetCalibration(double edge_encoder, double edge_angle);
164
Austin Schuhd27931c2014-02-16 19:18:20 -0800165 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuh27b8fb12014-02-22 15:10:05 -0800166 JointZeroingState zeroing_state);
Brian Silverman084372e2014-04-10 10:55:53 -0700167 double ComputeCalibrationChange(double edge_encoder, double edge_angle);
168 void HandleCalibrationError(
169 const constants::Values::Claws::Claw &claw_values);
Austin Schuhcda86af2014-02-16 16:16:39 -0800170};
171
172class BottomZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
173 public:
174 BottomZeroedStateFeedbackLoop(ClawMotor *motor)
175 : ZeroedStateFeedbackLoop("bottom", motor) {}
176 // Sets the calibration offset given the absolute angle and the corrisponding
177 // encoder value.
178 void SetCalibration(double edge_encoder, double edge_angle);
179
Austin Schuhd27931c2014-02-16 19:18:20 -0800180 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuh27b8fb12014-02-22 15:10:05 -0800181 JointZeroingState zeroing_state);
Brian Silverman084372e2014-04-10 10:55:53 -0700182 double ComputeCalibrationChange(double edge_encoder, double edge_angle);
183 void HandleCalibrationError(
184 const constants::Values::Claws::Claw &claw_values);
Austin Schuhcda86af2014-02-16 16:16:39 -0800185};
Ben Fredrickson9b388422014-02-13 06:15:31 +0000186
Brian Silverman38111502014-04-10 12:36:26 -0700187class ClawMotor : public aos::controls::ControlLoop<
Brian Silvermand8f403a2014-12-13 19:12:04 -0500188 control_loops::ClawGroup, false> {
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800189 public:
190 explicit ClawMotor(control_loops::ClawGroup *my_claw =
191 &control_loops::claw_queue_group);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800192
193 // True if the state machine is ready.
Austin Schuh4cb047f2014-02-16 21:10:19 -0800194 bool capped_goal() const { return capped_goal_; }
195
Austin Schuhe7f90d12014-02-17 00:48:25 -0800196 double uncapped_average_voltage() const {
197 return claw_.uncapped_average_voltage();
198 }
199
200 // True if the claw is zeroing.
201 bool is_zeroing() const;
202
Austin Schuh4cb047f2014-02-16 21:10:19 -0800203 // True if the state machine is ready.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800204 bool is_ready() const;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800205
Austin Schuhcda86af2014-02-16 16:16:39 -0800206 void ChangeTopOffset(double doffset);
207 void ChangeBottomOffset(double doffset);
208
Austin Schuhe7f90d12014-02-17 00:48:25 -0800209 enum CalibrationMode {
210 READY,
211 PREP_FINE_TUNE_TOP,
212 FINE_TUNE_TOP,
213 PREP_FINE_TUNE_BOTTOM,
214 FINE_TUNE_BOTTOM,
215 UNKNOWN_LOCATION
216 };
217
218 CalibrationMode mode() const { return mode_; }
219
Austin Schuh3bb9a442014-02-02 16:01:45 -0800220 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800221 virtual void RunIteration(const control_loops::ClawGroup::Goal *goal,
222 const control_loops::ClawGroup::Position *position,
223 control_loops::ClawGroup::Output *output,
James Kuszmaul9ead1de2014-02-28 21:24:39 -0800224 control_loops::ClawGroup::Status *status);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800225
Austin Schuhcda86af2014-02-16 16:16:39 -0800226 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); }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800230
231 private:
232 // Friend the test classes for acces to the internal state.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800233 friend class testing::WindupClawTest;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800234
235 // The zeroed joint to use.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800236 bool has_top_claw_goal_;
237 double top_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800238 TopZeroedStateFeedbackLoop top_claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800239
240 bool has_bottom_claw_goal_;
241 double bottom_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800242 BottomZeroedStateFeedbackLoop bottom_claw_;
243
244 // The claw loop.
245 ClawLimitedLoop claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800246
247 bool was_enabled_;
Ben Fredrickson9b388422014-02-13 06:15:31 +0000248 bool doing_calibration_fine_tune_;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800249
Brian Silverman7c021c42014-02-17 15:15:56 -0800250 // The initial separation when disabled. Used as the safe separation
Austin Schuhcda86af2014-02-16 16:16:39 -0800251 // distance.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800252 double initial_separation_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800253
Austin Schuh4cb047f2014-02-16 21:10:19 -0800254 bool capped_goal_;
Austin Schuhe7f90d12014-02-17 00:48:25 -0800255 CalibrationMode mode_;
Austin Schuh4cb047f2014-02-16 21:10:19 -0800256
Austin Schuh3bb9a442014-02-02 16:01:45 -0800257 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
258};
259
Austin Schuh069143b2014-02-17 02:46:26 -0800260// 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,
263 const frc971::constants::Values &values);
264
Austin Schuh3bb9a442014-02-02 16:01:45 -0800265} // namespace control_loops
266} // namespace frc971
267
268#endif // FRC971_CONTROL_LOOPS_CLAW_CLAW_H_