blob: dc8e6ba706457a35c206a78e18dbf7fb5338d391 [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 Schuhf84a1302014-02-19 00:23:30 -080074 bool ready() {
75 return front_.ready() && calibration_.ready() && back_.ready();
Austin Schuhf9286cd2014-02-11 00:51:09 -080076 }
77
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
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800106#undef COUNT_SETTER_GETTER
107
Austin Schuhcda86af2014-02-16 16:16:39 -0800108 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800109 // The accumulated voltage to apply to the motor.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800110 double offset_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800111 const char *name_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800112
Austin Schuhcda86af2014-02-16 16:16:39 -0800113 ClawMotor *motor_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800114
Brian Silvermane0a95462014-02-17 00:41:09 -0800115 HallEffectTracker front_, calibration_, back_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800116
117 JointZeroingState zeroing_state_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800118 double posedge_value_;
119 double negedge_value_;
Ben Fredrickson4283bb42014-02-22 08:31:50 +0000120 double last_edge_value_;
Austin Schuh27b8fb12014-02-22 15:10:05 -0800121 double min_hall_effect_on_angle_;
122 double max_hall_effect_on_angle_;
123 double min_hall_effect_off_angle_;
124 double max_hall_effect_off_angle_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800125 double encoder_;
126 double last_encoder_;
Austin Schuhf84a1302014-02-19 00:23:30 -0800127 double last_on_encoder_;
128 double last_off_encoder_;
Austin Schuh27b8fb12014-02-22 15:10:05 -0800129 bool any_triggered_last_;
Brian Silvermane0a95462014-02-17 00:41:09 -0800130
131 private:
132 // Does the edges of 1 sensor for GetPositionOfEdge.
133 bool DoGetPositionOfEdge(const constants::Values::Claws::AnglePair &angles,
134 double *edge_encoder, double *edge_angle,
135 const HallEffectTracker &sensor,
136 const char *hall_effect_name);
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800137};
138
Austin Schuhcda86af2014-02-16 16:16:39 -0800139class TopZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
140 public:
141 TopZeroedStateFeedbackLoop(ClawMotor *motor)
142 : ZeroedStateFeedbackLoop("top", motor) {}
143 // Sets the calibration offset given the absolute angle and the corrisponding
144 // encoder value.
145 void SetCalibration(double edge_encoder, double edge_angle);
146
Austin Schuhd27931c2014-02-16 19:18:20 -0800147 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuh27b8fb12014-02-22 15:10:05 -0800148 JointZeroingState zeroing_state);
Austin Schuhcda86af2014-02-16 16:16:39 -0800149};
150
151class BottomZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
152 public:
153 BottomZeroedStateFeedbackLoop(ClawMotor *motor)
154 : ZeroedStateFeedbackLoop("bottom", 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};
Ben Fredrickson9b388422014-02-13 06:15:31 +0000162
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800163class ClawMotor
164 : public aos::control_loops::ControlLoop<control_loops::ClawGroup> {
165 public:
166 explicit ClawMotor(control_loops::ClawGroup *my_claw =
167 &control_loops::claw_queue_group);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800168
169 // True if the state machine is ready.
Austin Schuh4cb047f2014-02-16 21:10:19 -0800170 bool capped_goal() const { return capped_goal_; }
171
Austin Schuhe7f90d12014-02-17 00:48:25 -0800172 double uncapped_average_voltage() const {
173 return claw_.uncapped_average_voltage();
174 }
175
176 // True if the claw is zeroing.
177 bool is_zeroing() const;
178
Austin Schuh4cb047f2014-02-16 21:10:19 -0800179 // True if the state machine is ready.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800180 bool is_ready() const;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800181
Austin Schuhcda86af2014-02-16 16:16:39 -0800182 void ChangeTopOffset(double doffset);
183 void ChangeBottomOffset(double doffset);
184
Austin Schuhe7f90d12014-02-17 00:48:25 -0800185 enum CalibrationMode {
186 READY,
187 PREP_FINE_TUNE_TOP,
188 FINE_TUNE_TOP,
189 PREP_FINE_TUNE_BOTTOM,
190 FINE_TUNE_BOTTOM,
191 UNKNOWN_LOCATION
192 };
193
194 CalibrationMode mode() const { return mode_; }
195
Austin Schuh3bb9a442014-02-02 16:01:45 -0800196 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800197 virtual void RunIteration(const control_loops::ClawGroup::Goal *goal,
198 const control_loops::ClawGroup::Position *position,
199 control_loops::ClawGroup::Output *output,
200 ::aos::control_loops::Status *status);
201
Austin Schuhcda86af2014-02-16 16:16:39 -0800202 double top_absolute_position() const {
203 return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
204 }
205 double bottom_absolute_position() const { return claw_.X_hat(0, 0); }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800206
207 private:
208 // Friend the test classes for acces to the internal state.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800209 friend class testing::WindupClawTest;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800210
211 // The zeroed joint to use.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800212 bool has_top_claw_goal_;
213 double top_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800214 TopZeroedStateFeedbackLoop top_claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800215
216 bool has_bottom_claw_goal_;
217 double bottom_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800218 BottomZeroedStateFeedbackLoop bottom_claw_;
219
220 // The claw loop.
221 ClawLimitedLoop claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800222
223 bool was_enabled_;
Ben Fredrickson9b388422014-02-13 06:15:31 +0000224 bool doing_calibration_fine_tune_;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800225
Brian Silverman7c021c42014-02-17 15:15:56 -0800226 // The initial separation when disabled. Used as the safe separation
Austin Schuhcda86af2014-02-16 16:16:39 -0800227 // distance.
Austin Schuhe7f90d12014-02-17 00:48:25 -0800228 double initial_separation_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800229
Austin Schuh4cb047f2014-02-16 21:10:19 -0800230 bool capped_goal_;
Austin Schuhe7f90d12014-02-17 00:48:25 -0800231 CalibrationMode mode_;
Austin Schuh4cb047f2014-02-16 21:10:19 -0800232
Austin Schuh3bb9a442014-02-02 16:01:45 -0800233 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
234};
235
Austin Schuh069143b2014-02-17 02:46:26 -0800236// Modifies the bottom and top goal such that they are within the limits and
237// their separation isn't too much or little.
238void LimitClawGoal(double *bottom_goal, double *top_goal,
239 const frc971::constants::Values &values);
240
Austin Schuh3bb9a442014-02-02 16:01:45 -0800241} // namespace control_loops
242} // namespace frc971
243
244#endif // FRC971_CONTROL_LOOPS_CLAW_CLAW_H_