blob: dab1dcada301cfa19723da3e3456634be21fab7b [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; }
32
Austin Schuhcda86af2014-02-16 16:16:39 -080033 void ChangeTopOffset(double doffset);
34 void ChangeBottomOffset(double doffset);
Austin Schuh4cb047f2014-02-16 21:10:19 -080035
36 double uncapped_average_voltage() const { return uncapped_average_voltage_; }
37
38 private:
39 double uncapped_average_voltage_;
40 bool is_zeroing_;
James Kuszmaulf63b0ae2014-03-25 16:52:11 -070041
42 const ::aos::controls::HPolytope<2> U_Poly_;
Austin Schuhcda86af2014-02-16 16:16:39 -080043};
44
45class ClawMotor;
46
Austin Schuh4b7b5d02014-02-10 21:20:34 -080047// This class implements the CapU function correctly given all the extra
48// information that we know about from the wrist motor.
49// It does not have any zeroing logic in it, only logic to deal with a delta U
50// controller.
Austin Schuhcda86af2014-02-16 16:16:39 -080051class ZeroedStateFeedbackLoop {
Austin Schuh3bb9a442014-02-02 16:01:45 -080052 public:
Austin Schuh27b8fb12014-02-22 15:10:05 -080053 ZeroedStateFeedbackLoop(const char *name, ClawMotor *motor);
Austin Schuh3bb9a442014-02-02 16:01:45 -080054
Austin Schuh4b7b5d02014-02-10 21:20:34 -080055 const static int kZeroingMaxVoltage = 5;
Austin Schuh3bb9a442014-02-02 16:01:45 -080056
Austin Schuh4b7b5d02014-02-10 21:20:34 -080057 enum JointZeroingState {
58 // We don't know where the joint is at all.
59 UNKNOWN_POSITION,
60 // We have an approximate position for where the claw is using.
61 APPROXIMATE_CALIBRATION,
62 // We observed the calibration edge while disabled. This is good enough for
63 // autonomous mode.
64 DISABLED_CALIBRATION,
65 // Ready for use during teleop.
66 CALIBRATED
67 };
68
69 void set_zeroing_state(JointZeroingState zeroing_state) {
70 zeroing_state_ = zeroing_state;
71 }
72 JointZeroingState zeroing_state() const { return zeroing_state_; }
73
Austin Schuh27b8fb12014-02-22 15:10:05 -080074 void SetPositionValues(const HalfClawPosition &claw);
Austin Schuhf9286cd2014-02-11 00:51:09 -080075
Austin Schuh27b8fb12014-02-22 15:10:05 -080076 void Reset(const HalfClawPosition &claw);
Ben Fredricksonade3eab2014-02-22 07:30:53 +000077
Austin Schuhcda86af2014-02-16 16:16:39 -080078 double absolute_position() const { return encoder() + offset(); }
79
Brian Silvermane0a95462014-02-17 00:41:09 -080080 const HallEffectTracker &front() const { return front_; }
81 const HallEffectTracker &calibration() const { return calibration_; }
82 const HallEffectTracker &back() const { return back_; }
Austin Schuh4b7b5d02014-02-10 21:20:34 -080083
84 bool any_hall_effect_changed() const {
Brian Silvermane0a95462014-02-17 00:41:09 -080085 return front().either_count_changed() ||
86 calibration().either_count_changed() ||
87 back().either_count_changed();
88 }
89 bool front_or_back_triggered() const {
90 return front().value() || back().value();
Austin Schuh4b7b5d02014-02-10 21:20:34 -080091 }
Austin Schuh27b8fb12014-02-22 15:10:05 -080092 bool any_triggered() const {
93 return calibration().value() || front().value() || back().value();
94 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -080095
Austin Schuhf9286cd2014-02-11 00:51:09 -080096 double encoder() const { return encoder_; }
97 double last_encoder() const { return last_encoder_; }
98
Austin Schuhcda86af2014-02-16 16:16:39 -080099 double offset() const { return offset_; }
100
Austin Schuhf9286cd2014-02-11 00:51:09 -0800101 // Returns true if an edge was detected in the last cycle and then sets the
102 // edge_position to the absolute position of the edge.
Austin Schuhd27931c2014-02-16 19:18:20 -0800103 bool GetPositionOfEdge(const constants::Values::Claws::Claw &claw,
Austin Schuhf9286cd2014-02-11 00:51:09 -0800104 double *edge_encoder, double *edge_angle);
105
Ben Fredricksoneaecbbb2014-02-23 12:12:03 +0000106 bool SawFilteredPosedge(const HallEffectTracker &this_sensor,
107 const HallEffectTracker &sensorA,
108 const HallEffectTracker &sensorB);
109
110 bool SawFilteredNegedge(const HallEffectTracker &this_sensor,
111 const HallEffectTracker &sensorA,
112 const HallEffectTracker &sensorB);
113
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800114#undef COUNT_SETTER_GETTER
115
Austin Schuhcda86af2014-02-16 16:16:39 -0800116 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800117 // The accumulated voltage to apply to the motor.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800118 double offset_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800119 const char *name_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800120
Austin Schuhcda86af2014-02-16 16:16:39 -0800121 ClawMotor *motor_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800122
Brian Silvermane0a95462014-02-17 00:41:09 -0800123 HallEffectTracker front_, calibration_, back_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800124
125 JointZeroingState zeroing_state_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800126 double posedge_value_;
127 double negedge_value_;
Austin Schuh27b8fb12014-02-22 15:10:05 -0800128 double min_hall_effect_on_angle_;
129 double max_hall_effect_on_angle_;
130 double min_hall_effect_off_angle_;
131 double max_hall_effect_off_angle_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800132 double encoder_;
133 double last_encoder_;
Austin Schuhf84a1302014-02-19 00:23:30 -0800134 double last_on_encoder_;
135 double last_off_encoder_;
Austin Schuh27b8fb12014-02-22 15:10:05 -0800136 bool any_triggered_last_;
Brian Silvermane0a95462014-02-17 00:41:09 -0800137
Ben Fredricksoneaecbbb2014-02-23 12:12:03 +0000138 const HallEffectTracker* posedge_filter_ = nullptr;
139 const HallEffectTracker* negedge_filter_ = nullptr;
140
Brian Silvermane0a95462014-02-17 00:41:09 -0800141 private:
142 // Does the edges of 1 sensor for GetPositionOfEdge.
143 bool DoGetPositionOfEdge(const constants::Values::Claws::AnglePair &angles,
144 double *edge_encoder, double *edge_angle,
145 const HallEffectTracker &sensor,
Ben Fredricksoneaecbbb2014-02-23 12:12:03 +0000146 const HallEffectTracker &sensorA,
147 const HallEffectTracker &sensorB,
Brian Silvermane0a95462014-02-17 00:41:09 -0800148 const char *hall_effect_name);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800149};
150
Austin Schuhcda86af2014-02-16 16:16:39 -0800151class TopZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
152 public:
153 TopZeroedStateFeedbackLoop(ClawMotor *motor)
154 : ZeroedStateFeedbackLoop("top", motor) {}
155 // Sets the calibration offset given the absolute angle and the corrisponding
156 // encoder value.
157 void SetCalibration(double edge_encoder, double edge_angle);
158
Austin Schuhd27931c2014-02-16 19:18:20 -0800159 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuh27b8fb12014-02-22 15:10:05 -0800160 JointZeroingState zeroing_state);
Austin Schuhcda86af2014-02-16 16:16:39 -0800161};
162
163class BottomZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
164 public:
165 BottomZeroedStateFeedbackLoop(ClawMotor *motor)
166 : ZeroedStateFeedbackLoop("bottom", motor) {}
167 // Sets the calibration offset given the absolute angle and the corrisponding
168 // encoder value.
169 void SetCalibration(double edge_encoder, double edge_angle);
170
Austin Schuhd27931c2014-02-16 19:18:20 -0800171 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuh27b8fb12014-02-22 15:10:05 -0800172 JointZeroingState zeroing_state);
Austin Schuhcda86af2014-02-16 16:16:39 -0800173};
Ben Fredrickson9b388422014-02-13 06:15:31 +0000174
Brian Silverman71fbee02014-03-13 17:24:54 -0700175class ClawMotor : public aos::control_loops::ControlLoop<
176 control_loops::ClawGroup, true, true, false> {
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800177 public:
178 explicit ClawMotor(control_loops::ClawGroup *my_claw =
179 &control_loops::claw_queue_group);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800180
181 // True if the state machine is ready.
Austin Schuh4cb047f2014-02-16 21:10:19 -0800182 bool capped_goal() const { return capped_goal_; }
183
Austin Schuhe7f90d12014-02-17 00:48:25 -0800184 double uncapped_average_voltage() const {
185 return claw_.uncapped_average_voltage();
186 }
187
188 // True if the claw is zeroing.
189 bool is_zeroing() const;
190
Austin Schuh4cb047f2014-02-16 21:10:19 -0800191 // True if the state machine is ready.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800192 bool is_ready() const;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800193
Austin Schuhcda86af2014-02-16 16:16:39 -0800194 void ChangeTopOffset(double doffset);
195 void ChangeBottomOffset(double doffset);
196
Austin Schuhe7f90d12014-02-17 00:48:25 -0800197 enum CalibrationMode {
198 READY,
199 PREP_FINE_TUNE_TOP,
200 FINE_TUNE_TOP,
201 PREP_FINE_TUNE_BOTTOM,
202 FINE_TUNE_BOTTOM,
203 UNKNOWN_LOCATION
204 };
205
206 CalibrationMode mode() const { return mode_; }
207
Austin Schuh3bb9a442014-02-02 16:01:45 -0800208 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800209 virtual void RunIteration(const control_loops::ClawGroup::Goal *goal,
210 const control_loops::ClawGroup::Position *position,
211 control_loops::ClawGroup::Output *output,
James Kuszmaul9ead1de2014-02-28 21:24:39 -0800212 control_loops::ClawGroup::Status *status);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800213
Austin Schuhcda86af2014-02-16 16:16:39 -0800214 double top_absolute_position() const {
215 return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
216 }
217 double bottom_absolute_position() const { return claw_.X_hat(0, 0); }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800218
219 private:
220 // Friend the test classes for acces to the internal state.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800221 friend class testing::WindupClawTest;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800222
223 // The zeroed joint to use.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800224 bool has_top_claw_goal_;
225 double top_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800226 TopZeroedStateFeedbackLoop top_claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800227
228 bool has_bottom_claw_goal_;
229 double bottom_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800230 BottomZeroedStateFeedbackLoop bottom_claw_;
231
232 // The claw loop.
233 ClawLimitedLoop claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800234
235 bool was_enabled_;
Ben Fredrickson9b388422014-02-13 06:15:31 +0000236 bool doing_calibration_fine_tune_;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800237
Brian Silverman7c021c42014-02-17 15:15:56 -0800238 // The initial separation when disabled. Used as the safe separation
Austin Schuhcda86af2014-02-16 16:16:39 -0800239 // distance.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800240 double initial_separation_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800241
Austin Schuh4cb047f2014-02-16 21:10:19 -0800242 bool capped_goal_;
Austin Schuhe7f90d12014-02-17 00:48:25 -0800243 CalibrationMode mode_;
Austin Schuh4cb047f2014-02-16 21:10:19 -0800244
Austin Schuh3bb9a442014-02-02 16:01:45 -0800245 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
246};
247
Austin Schuh069143b2014-02-17 02:46:26 -0800248// Modifies the bottom and top goal such that they are within the limits and
249// their separation isn't too much or little.
250void LimitClawGoal(double *bottom_goal, double *top_goal,
251 const frc971::constants::Values &values);
252
Austin Schuh3bb9a442014-02-02 16:01:45 -0800253} // namespace control_loops
254} // namespace frc971
255
256#endif // FRC971_CONTROL_LOOPS_CLAW_CLAW_H_