blob: 8c81e62fe171d3ee1c30e3c0d64e9fee0aaf200c [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"
James Kuszmaulf63b0ae2014-03-25 16:52:11 -07007#include "aos/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:
Austin Schuh27b8fb12014-02-22 15:10:05 -080028 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);
Austin Schuhcda86af2014-02-16 16:16:39 -0800167};
168
169class BottomZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
170 public:
171 BottomZeroedStateFeedbackLoop(ClawMotor *motor)
172 : ZeroedStateFeedbackLoop("bottom", motor) {}
173 // Sets the calibration offset given the absolute angle and the corrisponding
174 // encoder value.
175 void SetCalibration(double edge_encoder, double edge_angle);
176
Austin Schuhd27931c2014-02-16 19:18:20 -0800177 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuh27b8fb12014-02-22 15:10:05 -0800178 JointZeroingState zeroing_state);
Austin Schuhcda86af2014-02-16 16:16:39 -0800179};
Ben Fredrickson9b388422014-02-13 06:15:31 +0000180
Brian Silverman71fbee02014-03-13 17:24:54 -0700181class ClawMotor : public aos::control_loops::ControlLoop<
182 control_loops::ClawGroup, true, true, false> {
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800183 public:
184 explicit ClawMotor(control_loops::ClawGroup *my_claw =
185 &control_loops::claw_queue_group);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800186
187 // True if the state machine is ready.
Austin Schuh4cb047f2014-02-16 21:10:19 -0800188 bool capped_goal() const { return capped_goal_; }
189
Austin Schuhe7f90d12014-02-17 00:48:25 -0800190 double uncapped_average_voltage() const {
191 return claw_.uncapped_average_voltage();
192 }
193
194 // True if the claw is zeroing.
195 bool is_zeroing() const;
196
Austin Schuh4cb047f2014-02-16 21:10:19 -0800197 // True if the state machine is ready.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800198 bool is_ready() const;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800199
Austin Schuhcda86af2014-02-16 16:16:39 -0800200 void ChangeTopOffset(double doffset);
201 void ChangeBottomOffset(double doffset);
202
Austin Schuhe7f90d12014-02-17 00:48:25 -0800203 enum CalibrationMode {
204 READY,
205 PREP_FINE_TUNE_TOP,
206 FINE_TUNE_TOP,
207 PREP_FINE_TUNE_BOTTOM,
208 FINE_TUNE_BOTTOM,
209 UNKNOWN_LOCATION
210 };
211
212 CalibrationMode mode() const { return mode_; }
213
Austin Schuh3bb9a442014-02-02 16:01:45 -0800214 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800215 virtual void RunIteration(const control_loops::ClawGroup::Goal *goal,
216 const control_loops::ClawGroup::Position *position,
217 control_loops::ClawGroup::Output *output,
James Kuszmaul9ead1de2014-02-28 21:24:39 -0800218 control_loops::ClawGroup::Status *status);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800219
Austin Schuhcda86af2014-02-16 16:16:39 -0800220 double top_absolute_position() const {
221 return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
222 }
223 double bottom_absolute_position() const { return claw_.X_hat(0, 0); }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800224
225 private:
226 // Friend the test classes for acces to the internal state.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800227 friend class testing::WindupClawTest;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800228
229 // The zeroed joint to use.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800230 bool has_top_claw_goal_;
231 double top_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800232 TopZeroedStateFeedbackLoop top_claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800233
234 bool has_bottom_claw_goal_;
235 double bottom_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800236 BottomZeroedStateFeedbackLoop bottom_claw_;
237
238 // The claw loop.
239 ClawLimitedLoop claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800240
241 bool was_enabled_;
Ben Fredrickson9b388422014-02-13 06:15:31 +0000242 bool doing_calibration_fine_tune_;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800243
Brian Silverman7c021c42014-02-17 15:15:56 -0800244 // The initial separation when disabled. Used as the safe separation
Austin Schuhcda86af2014-02-16 16:16:39 -0800245 // distance.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800246 double initial_separation_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800247
Austin Schuh4cb047f2014-02-16 21:10:19 -0800248 bool capped_goal_;
Austin Schuhe7f90d12014-02-17 00:48:25 -0800249 CalibrationMode mode_;
Austin Schuh4cb047f2014-02-16 21:10:19 -0800250
Austin Schuh3bb9a442014-02-02 16:01:45 -0800251 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
252};
253
Austin Schuh069143b2014-02-17 02:46:26 -0800254// Modifies the bottom and top goal such that they are within the limits and
255// their separation isn't too much or little.
256void LimitClawGoal(double *bottom_goal, double *top_goal,
257 const frc971::constants::Values &values);
258
Austin Schuh3bb9a442014-02-02 16:01:45 -0800259} // namespace control_loops
260} // namespace frc971
261
262#endif // FRC971_CONTROL_LOOPS_CLAW_CLAW_H_