blob: 48650b4638e564ab44dfcf3a4f23f634b1aa5048 [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 Schuhf84a1302014-02-19 00:23:30 -080078 bool ready() {
79 return front_.ready() && calibration_.ready() && back_.ready();
Austin Schuhf9286cd2014-02-11 00:51:09 -080080 }
81
Austin Schuhcda86af2014-02-16 16:16:39 -080082 double absolute_position() const { return encoder() + offset(); }
83
Brian Silvermane0a95462014-02-17 00:41:09 -080084 const HallEffectTracker &front() const { return front_; }
85 const HallEffectTracker &calibration() const { return calibration_; }
86 const HallEffectTracker &back() const { return back_; }
Austin Schuh4b7b5d02014-02-10 21:20:34 -080087
88 bool any_hall_effect_changed() const {
Brian Silvermane0a95462014-02-17 00:41:09 -080089 return front().either_count_changed() ||
90 calibration().either_count_changed() ||
91 back().either_count_changed();
92 }
93 bool front_or_back_triggered() const {
94 return front().value() || back().value();
Austin Schuh4b7b5d02014-02-10 21:20:34 -080095 }
Austin Schuh27b8fb12014-02-22 15:10:05 -080096 bool any_triggered() const {
97 return calibration().value() || front().value() || back().value();
98 }
Austin Schuh4b7b5d02014-02-10 21:20:34 -080099
Austin Schuhf9286cd2014-02-11 00:51:09 -0800100 double encoder() const { return encoder_; }
101 double last_encoder() const { return last_encoder_; }
102
Austin Schuhcda86af2014-02-16 16:16:39 -0800103 double offset() const { return offset_; }
104
Austin Schuhf9286cd2014-02-11 00:51:09 -0800105 // Returns true if an edge was detected in the last cycle and then sets the
106 // edge_position to the absolute position of the edge.
Austin Schuhd27931c2014-02-16 19:18:20 -0800107 bool GetPositionOfEdge(const constants::Values::Claws::Claw &claw,
Austin Schuhf9286cd2014-02-11 00:51:09 -0800108 double *edge_encoder, double *edge_angle);
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_;
Ben Fredrickson4283bb42014-02-22 08:31:50 +0000124 double last_edge_value_;
Austin Schuh27b8fb12014-02-22 15:10:05 -0800125 double min_hall_effect_on_angle_;
126 double max_hall_effect_on_angle_;
127 double min_hall_effect_off_angle_;
128 double max_hall_effect_off_angle_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800129 double encoder_;
130 double last_encoder_;
Austin Schuhf84a1302014-02-19 00:23:30 -0800131 double last_on_encoder_;
132 double last_off_encoder_;
Austin Schuh27b8fb12014-02-22 15:10:05 -0800133 bool any_triggered_last_;
Brian Silvermane0a95462014-02-17 00:41:09 -0800134
135 private:
136 // Does the edges of 1 sensor for GetPositionOfEdge.
137 bool DoGetPositionOfEdge(const constants::Values::Claws::AnglePair &angles,
138 double *edge_encoder, double *edge_angle,
139 const HallEffectTracker &sensor,
140 const char *hall_effect_name);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800141};
142
Austin Schuhcda86af2014-02-16 16:16:39 -0800143class TopZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
144 public:
145 TopZeroedStateFeedbackLoop(ClawMotor *motor)
146 : ZeroedStateFeedbackLoop("top", motor) {}
147 // Sets the calibration offset given the absolute angle and the corrisponding
148 // encoder value.
149 void SetCalibration(double edge_encoder, double edge_angle);
150
Austin Schuhd27931c2014-02-16 19:18:20 -0800151 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuh27b8fb12014-02-22 15:10:05 -0800152 JointZeroingState zeroing_state);
Austin Schuhcda86af2014-02-16 16:16:39 -0800153};
154
155class BottomZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
156 public:
157 BottomZeroedStateFeedbackLoop(ClawMotor *motor)
158 : ZeroedStateFeedbackLoop("bottom", motor) {}
159 // Sets the calibration offset given the absolute angle and the corrisponding
160 // encoder value.
161 void SetCalibration(double edge_encoder, double edge_angle);
162
Austin Schuhd27931c2014-02-16 19:18:20 -0800163 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuh27b8fb12014-02-22 15:10:05 -0800164 JointZeroingState zeroing_state);
Austin Schuhcda86af2014-02-16 16:16:39 -0800165};
Ben Fredrickson9b388422014-02-13 06:15:31 +0000166
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800167class ClawMotor
168 : public aos::control_loops::ControlLoop<control_loops::ClawGroup> {
169 public:
170 explicit ClawMotor(control_loops::ClawGroup *my_claw =
171 &control_loops::claw_queue_group);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800172
173 // True if the state machine is ready.
Austin Schuh4cb047f2014-02-16 21:10:19 -0800174 bool capped_goal() const { return capped_goal_; }
175
Austin Schuhe7f90d12014-02-17 00:48:25 -0800176 double uncapped_average_voltage() const {
177 return claw_.uncapped_average_voltage();
178 }
179
180 // True if the claw is zeroing.
181 bool is_zeroing() const;
182
Austin Schuh4cb047f2014-02-16 21:10:19 -0800183 // True if the state machine is ready.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800184 bool is_ready() const;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800185
Austin Schuhcda86af2014-02-16 16:16:39 -0800186 void ChangeTopOffset(double doffset);
187 void ChangeBottomOffset(double doffset);
188
Austin Schuhe7f90d12014-02-17 00:48:25 -0800189 enum CalibrationMode {
190 READY,
191 PREP_FINE_TUNE_TOP,
192 FINE_TUNE_TOP,
193 PREP_FINE_TUNE_BOTTOM,
194 FINE_TUNE_BOTTOM,
195 UNKNOWN_LOCATION
196 };
197
198 CalibrationMode mode() const { return mode_; }
199
Austin Schuh3bb9a442014-02-02 16:01:45 -0800200 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800201 virtual void RunIteration(const control_loops::ClawGroup::Goal *goal,
202 const control_loops::ClawGroup::Position *position,
203 control_loops::ClawGroup::Output *output,
204 ::aos::control_loops::Status *status);
205
Austin Schuhcda86af2014-02-16 16:16:39 -0800206 double top_absolute_position() const {
207 return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
208 }
209 double bottom_absolute_position() const { return claw_.X_hat(0, 0); }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800210
211 private:
212 // Friend the test classes for acces to the internal state.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800213 friend class testing::WindupClawTest;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800214
215 // The zeroed joint to use.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800216 bool has_top_claw_goal_;
217 double top_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800218 TopZeroedStateFeedbackLoop top_claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800219
220 bool has_bottom_claw_goal_;
221 double bottom_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800222 BottomZeroedStateFeedbackLoop bottom_claw_;
223
224 // The claw loop.
225 ClawLimitedLoop claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800226
227 bool was_enabled_;
Ben Fredrickson9b388422014-02-13 06:15:31 +0000228 bool doing_calibration_fine_tune_;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800229
Brian Silverman7c021c42014-02-17 15:15:56 -0800230 // The initial separation when disabled. Used as the safe separation
Austin Schuhcda86af2014-02-16 16:16:39 -0800231 // distance.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800232 double initial_separation_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800233
Austin Schuh4cb047f2014-02-16 21:10:19 -0800234 bool capped_goal_;
Austin Schuhe7f90d12014-02-17 00:48:25 -0800235 CalibrationMode mode_;
Austin Schuh4cb047f2014-02-16 21:10:19 -0800236
Austin Schuh3bb9a442014-02-02 16:01:45 -0800237 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
238};
239
Austin Schuh069143b2014-02-17 02:46:26 -0800240// Modifies the bottom and top goal such that they are within the limits and
241// their separation isn't too much or little.
242void LimitClawGoal(double *bottom_goal, double *top_goal,
243 const frc971::constants::Values &values);
244
Austin Schuh3bb9a442014-02-02 16:01:45 -0800245} // namespace control_loops
246} // namespace frc971
247
248#endif // FRC971_CONTROL_LOOPS_CLAW_CLAW_H_