blob: 37a17872d3c598915ad070d7470474db1b5fbbdf [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"
Austin Schuhf9286cd2014-02-11 00:51:09 -08007#include "frc971/constants.h"
Austin Schuh3bb9a442014-02-02 16:01:45 -08008#include "frc971/control_loops/state_feedback_loop.h"
9#include "frc971/control_loops/claw/claw.q.h"
Austin Schuhcda86af2014-02-16 16:16:39 -080010#include "frc971/control_loops/claw/claw_motor_plant.h"
Brian Silvermane0a95462014-02-17 00:41:09 -080011#include "frc971/control_loops/hall_effect_tracker.h"
Austin Schuh3bb9a442014-02-02 16:01:45 -080012
Austin Schuh3bb9a442014-02-02 16:01:45 -080013namespace frc971 {
14namespace control_loops {
15namespace testing {
Austin Schuhe7f90d12014-02-17 00:48:25 -080016class WindupClawTest;
Austin Schuh3bb9a442014-02-02 16:01:45 -080017};
18
Austin Schuh4b7b5d02014-02-10 21:20:34 -080019// Note: Everything in this file assumes that there is a 1 cycle delay between
20// power being requested and it showing up at the motor. It assumes that
21// X_hat(2, 1) is the voltage being applied as well. It will go unstable if
22// that isn't true.
23
Austin Schuhcda86af2014-02-16 16:16:39 -080024class ClawLimitedLoop : public StateFeedbackLoop<4, 2, 2> {
25 public:
Austin Schuh27b8fb12014-02-22 15:10:05 -080026 ClawLimitedLoop(StateFeedbackLoop<4, 2, 2> loop);
Austin Schuhcda86af2014-02-16 16:16:39 -080027 virtual void CapU();
28
Austin Schuh4cb047f2014-02-16 21:10:19 -080029 void set_is_zeroing(bool is_zeroing) { is_zeroing_ = is_zeroing; }
30
Austin Schuhcda86af2014-02-16 16:16:39 -080031 void ChangeTopOffset(double doffset);
32 void ChangeBottomOffset(double doffset);
Austin Schuh4cb047f2014-02-16 21:10:19 -080033
34 double uncapped_average_voltage() const { return uncapped_average_voltage_; }
35
36 private:
37 double uncapped_average_voltage_;
38 bool is_zeroing_;
Austin Schuhcda86af2014-02-16 16:16:39 -080039};
40
41class ClawMotor;
42
Austin Schuh4b7b5d02014-02-10 21:20:34 -080043// This class implements the CapU function correctly given all the extra
44// information that we know about from the wrist motor.
45// It does not have any zeroing logic in it, only logic to deal with a delta U
46// controller.
Austin Schuhcda86af2014-02-16 16:16:39 -080047class ZeroedStateFeedbackLoop {
Austin Schuh3bb9a442014-02-02 16:01:45 -080048 public:
Austin Schuh27b8fb12014-02-22 15:10:05 -080049 ZeroedStateFeedbackLoop(const char *name, ClawMotor *motor);
Austin Schuh3bb9a442014-02-02 16:01:45 -080050
Austin Schuh4b7b5d02014-02-10 21:20:34 -080051 const static int kZeroingMaxVoltage = 5;
Austin Schuh3bb9a442014-02-02 16:01:45 -080052
Austin Schuh4b7b5d02014-02-10 21:20:34 -080053 enum JointZeroingState {
54 // We don't know where the joint is at all.
55 UNKNOWN_POSITION,
56 // We have an approximate position for where the claw is using.
57 APPROXIMATE_CALIBRATION,
58 // We observed the calibration edge while disabled. This is good enough for
59 // autonomous mode.
60 DISABLED_CALIBRATION,
61 // Ready for use during teleop.
62 CALIBRATED
63 };
64
65 void set_zeroing_state(JointZeroingState zeroing_state) {
66 zeroing_state_ = zeroing_state;
67 }
68 JointZeroingState zeroing_state() const { return zeroing_state_; }
69
Austin Schuh27b8fb12014-02-22 15:10:05 -080070 void SetPositionValues(const HalfClawPosition &claw);
Austin Schuhf9286cd2014-02-11 00:51:09 -080071
Austin Schuh27b8fb12014-02-22 15:10:05 -080072 void Reset(const HalfClawPosition &claw);
Ben Fredricksonade3eab2014-02-22 07:30:53 +000073
Austin Schuhcda86af2014-02-16 16:16:39 -080074 double absolute_position() const { return encoder() + offset(); }
75
Brian Silvermane0a95462014-02-17 00:41:09 -080076 const HallEffectTracker &front() const { return front_; }
77 const HallEffectTracker &calibration() const { return calibration_; }
78 const HallEffectTracker &back() const { return back_; }
Austin Schuh4b7b5d02014-02-10 21:20:34 -080079
80 bool any_hall_effect_changed() const {
Brian Silvermane0a95462014-02-17 00:41:09 -080081 return front().either_count_changed() ||
82 calibration().either_count_changed() ||
83 back().either_count_changed();
84 }
85 bool front_or_back_triggered() const {
86 return front().value() || back().value();
Austin Schuh4b7b5d02014-02-10 21:20:34 -080087 }
Austin Schuh27b8fb12014-02-22 15:10:05 -080088 bool any_triggered() const {
89 return calibration().value() || front().value() || back().value();
90 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -080091
Austin Schuhf9286cd2014-02-11 00:51:09 -080092 double encoder() const { return encoder_; }
93 double last_encoder() const { return last_encoder_; }
94
Austin Schuhcda86af2014-02-16 16:16:39 -080095 double offset() const { return offset_; }
96
Austin Schuhf9286cd2014-02-11 00:51:09 -080097 // Returns true if an edge was detected in the last cycle and then sets the
98 // edge_position to the absolute position of the edge.
Austin Schuhd27931c2014-02-16 19:18:20 -080099 bool GetPositionOfEdge(const constants::Values::Claws::Claw &claw,
Austin Schuhf9286cd2014-02-11 00:51:09 -0800100 double *edge_encoder, double *edge_angle);
101
Ben Fredricksoneaecbbb2014-02-23 12:12:03 +0000102 bool SawFilteredPosedge(const HallEffectTracker &this_sensor,
103 const HallEffectTracker &sensorA,
104 const HallEffectTracker &sensorB);
105
106 bool SawFilteredNegedge(const HallEffectTracker &this_sensor,
107 const HallEffectTracker &sensorA,
108 const HallEffectTracker &sensorB);
109
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800110#undef COUNT_SETTER_GETTER
111
Austin Schuhcda86af2014-02-16 16:16:39 -0800112 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800113 // The accumulated voltage to apply to the motor.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800114 double offset_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800115 const char *name_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800116
Austin Schuhcda86af2014-02-16 16:16:39 -0800117 ClawMotor *motor_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800118
Brian Silvermane0a95462014-02-17 00:41:09 -0800119 HallEffectTracker front_, calibration_, back_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800120
121 JointZeroingState zeroing_state_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800122 double posedge_value_;
123 double negedge_value_;
Austin Schuh27b8fb12014-02-22 15:10:05 -0800124 double min_hall_effect_on_angle_;
125 double max_hall_effect_on_angle_;
126 double min_hall_effect_off_angle_;
127 double max_hall_effect_off_angle_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800128 double encoder_;
129 double last_encoder_;
Austin Schuhf84a1302014-02-19 00:23:30 -0800130 double last_on_encoder_;
131 double last_off_encoder_;
Austin Schuh27b8fb12014-02-22 15:10:05 -0800132 bool any_triggered_last_;
Brian Silvermane0a95462014-02-17 00:41:09 -0800133
Ben Fredricksoneaecbbb2014-02-23 12:12:03 +0000134 const HallEffectTracker* posedge_filter_ = nullptr;
135 const HallEffectTracker* negedge_filter_ = nullptr;
136
Brian Silvermane0a95462014-02-17 00:41:09 -0800137 private:
138 // Does the edges of 1 sensor for GetPositionOfEdge.
139 bool DoGetPositionOfEdge(const constants::Values::Claws::AnglePair &angles,
140 double *edge_encoder, double *edge_angle,
141 const HallEffectTracker &sensor,
Ben Fredricksoneaecbbb2014-02-23 12:12:03 +0000142 const HallEffectTracker &sensorA,
143 const HallEffectTracker &sensorB,
Brian Silvermane0a95462014-02-17 00:41:09 -0800144 const char *hall_effect_name);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800145};
146
Austin Schuhcda86af2014-02-16 16:16:39 -0800147class TopZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
148 public:
149 TopZeroedStateFeedbackLoop(ClawMotor *motor)
150 : ZeroedStateFeedbackLoop("top", motor) {}
151 // Sets the calibration offset given the absolute angle and the corrisponding
152 // encoder value.
153 void SetCalibration(double edge_encoder, double edge_angle);
154
Austin Schuhd27931c2014-02-16 19:18:20 -0800155 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuh27b8fb12014-02-22 15:10:05 -0800156 JointZeroingState zeroing_state);
Austin Schuhcda86af2014-02-16 16:16:39 -0800157};
158
159class BottomZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
160 public:
161 BottomZeroedStateFeedbackLoop(ClawMotor *motor)
162 : ZeroedStateFeedbackLoop("bottom", motor) {}
163 // Sets the calibration offset given the absolute angle and the corrisponding
164 // encoder value.
165 void SetCalibration(double edge_encoder, double edge_angle);
166
Austin Schuhd27931c2014-02-16 19:18:20 -0800167 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuh27b8fb12014-02-22 15:10:05 -0800168 JointZeroingState zeroing_state);
Austin Schuhcda86af2014-02-16 16:16:39 -0800169};
Ben Fredrickson9b388422014-02-13 06:15:31 +0000170
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800171class ClawMotor
172 : public aos::control_loops::ControlLoop<control_loops::ClawGroup> {
173 public:
174 explicit ClawMotor(control_loops::ClawGroup *my_claw =
175 &control_loops::claw_queue_group);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800176
177 // True if the state machine is ready.
Austin Schuh4cb047f2014-02-16 21:10:19 -0800178 bool capped_goal() const { return capped_goal_; }
179
Austin Schuhe7f90d12014-02-17 00:48:25 -0800180 double uncapped_average_voltage() const {
181 return claw_.uncapped_average_voltage();
182 }
183
184 // True if the claw is zeroing.
185 bool is_zeroing() const;
186
Austin Schuh4cb047f2014-02-16 21:10:19 -0800187 // True if the state machine is ready.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800188 bool is_ready() const;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800189
Austin Schuhcda86af2014-02-16 16:16:39 -0800190 void ChangeTopOffset(double doffset);
191 void ChangeBottomOffset(double doffset);
192
Austin Schuhe7f90d12014-02-17 00:48:25 -0800193 enum CalibrationMode {
194 READY,
195 PREP_FINE_TUNE_TOP,
196 FINE_TUNE_TOP,
197 PREP_FINE_TUNE_BOTTOM,
198 FINE_TUNE_BOTTOM,
199 UNKNOWN_LOCATION
200 };
201
202 CalibrationMode mode() const { return mode_; }
203
Austin Schuh3bb9a442014-02-02 16:01:45 -0800204 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800205 virtual void RunIteration(const control_loops::ClawGroup::Goal *goal,
206 const control_loops::ClawGroup::Position *position,
207 control_loops::ClawGroup::Output *output,
James Kuszmaul9ead1de2014-02-28 21:24:39 -0800208 control_loops::ClawGroup::Status *status);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800209
Austin Schuhcda86af2014-02-16 16:16:39 -0800210 double top_absolute_position() const {
211 return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
212 }
213 double bottom_absolute_position() const { return claw_.X_hat(0, 0); }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800214
215 private:
216 // Friend the test classes for acces to the internal state.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800217 friend class testing::WindupClawTest;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800218
219 // The zeroed joint to use.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800220 bool has_top_claw_goal_;
221 double top_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800222 TopZeroedStateFeedbackLoop top_claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800223
224 bool has_bottom_claw_goal_;
225 double bottom_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800226 BottomZeroedStateFeedbackLoop bottom_claw_;
227
228 // The claw loop.
229 ClawLimitedLoop claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800230
231 bool was_enabled_;
Ben Fredrickson9b388422014-02-13 06:15:31 +0000232 bool doing_calibration_fine_tune_;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800233
Brian Silverman7c021c42014-02-17 15:15:56 -0800234 // The initial separation when disabled. Used as the safe separation
Austin Schuhcda86af2014-02-16 16:16:39 -0800235 // distance.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800236 double initial_separation_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800237
Austin Schuh4cb047f2014-02-16 21:10:19 -0800238 bool capped_goal_;
Austin Schuhe7f90d12014-02-17 00:48:25 -0800239 CalibrationMode mode_;
Austin Schuh4cb047f2014-02-16 21:10:19 -0800240
Austin Schuh3bb9a442014-02-02 16:01:45 -0800241 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
242};
243
Austin Schuh069143b2014-02-17 02:46:26 -0800244// Modifies the bottom and top goal such that they are within the limits and
245// their separation isn't too much or little.
246void LimitClawGoal(double *bottom_goal, double *top_goal,
247 const frc971::constants::Values &values);
248
Austin Schuh3bb9a442014-02-02 16:01:45 -0800249} // namespace control_loops
250} // namespace frc971
251
252#endif // FRC971_CONTROL_LOOPS_CLAW_CLAW_H_