blob: 9ff406ebe6fad406ec80937a579aca32ee09f8e4 [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 {
16class ClawTest_NoWindupPositive_Test;
17class ClawTest_NoWindupNegative_Test;
18};
19
Austin Schuh4b7b5d02014-02-10 21:20:34 -080020// Note: Everything in this file assumes that there is a 1 cycle delay between
21// power being requested and it showing up at the motor. It assumes that
22// X_hat(2, 1) is the voltage being applied as well. It will go unstable if
23// that isn't true.
24
Austin Schuhcda86af2014-02-16 16:16:39 -080025class ClawLimitedLoop : public StateFeedbackLoop<4, 2, 2> {
26 public:
27 ClawLimitedLoop(StateFeedbackLoop<4, 2, 2> loop)
Austin Schuh4cb047f2014-02-16 21:10:19 -080028 : StateFeedbackLoop<4, 2, 2>(loop),
29 uncapped_average_voltage_(0.0),
30 is_zeroing_(true) {}
Austin Schuhcda86af2014-02-16 16:16:39 -080031 virtual void CapU();
32
Austin Schuh4cb047f2014-02-16 21:10:19 -080033 void set_is_zeroing(bool is_zeroing) { is_zeroing_ = is_zeroing; }
34
Austin Schuhcda86af2014-02-16 16:16:39 -080035 void ChangeTopOffset(double doffset);
36 void ChangeBottomOffset(double doffset);
Austin Schuh4cb047f2014-02-16 21:10:19 -080037
38 double uncapped_average_voltage() const { return uncapped_average_voltage_; }
39
40 private:
41 double uncapped_average_voltage_;
42 bool is_zeroing_;
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 Schuhcda86af2014-02-16 16:16:39 -080053 ZeroedStateFeedbackLoop(const char *name, ClawMotor *motor)
54 : offset_(0.0),
55 name_(name),
56 motor_(motor),
Austin Schuhf9286cd2014-02-11 00:51:09 -080057 zeroing_state_(UNKNOWN_POSITION),
58 posedge_value_(0.0),
59 negedge_value_(0.0),
60 encoder_(0.0),
Austin Schuhcda86af2014-02-16 16:16:39 -080061 last_encoder_(0.0) {}
Austin Schuh3bb9a442014-02-02 16:01:45 -080062
Austin Schuh4b7b5d02014-02-10 21:20:34 -080063 const static int kZeroingMaxVoltage = 5;
Austin Schuh3bb9a442014-02-02 16:01:45 -080064
Austin Schuh4b7b5d02014-02-10 21:20:34 -080065 enum JointZeroingState {
66 // We don't know where the joint is at all.
67 UNKNOWN_POSITION,
68 // We have an approximate position for where the claw is using.
69 APPROXIMATE_CALIBRATION,
70 // We observed the calibration edge while disabled. This is good enough for
71 // autonomous mode.
72 DISABLED_CALIBRATION,
73 // Ready for use during teleop.
74 CALIBRATED
75 };
76
77 void set_zeroing_state(JointZeroingState zeroing_state) {
78 zeroing_state_ = zeroing_state;
79 }
80 JointZeroingState zeroing_state() const { return zeroing_state_; }
81
Austin Schuh4339ebb2014-02-11 00:56:44 -080082 void SetPositionValues(const HalfClawPosition &claw) {
Brian Silvermane0a95462014-02-17 00:41:09 -080083 front_.Update(claw.front);
84 calibration_.Update(claw.calibration);
85 back_.Update(claw.back);
Austin Schuhf9286cd2014-02-11 00:51:09 -080086
87 posedge_value_ = claw.posedge_value;
88 negedge_value_ = claw.negedge_value;
Austin Schuhcda86af2014-02-16 16:16:39 -080089 last_encoder_ = encoder_;
90 encoder_ = claw.position;
Austin Schuhf9286cd2014-02-11 00:51:09 -080091 }
92
Austin Schuhcda86af2014-02-16 16:16:39 -080093 double absolute_position() const { return encoder() + offset(); }
94
Brian Silvermane0a95462014-02-17 00:41:09 -080095 const HallEffectTracker &front() const { return front_; }
96 const HallEffectTracker &calibration() const { return calibration_; }
97 const HallEffectTracker &back() const { return back_; }
Austin Schuh4b7b5d02014-02-10 21:20:34 -080098
99 bool any_hall_effect_changed() const {
Brian Silvermane0a95462014-02-17 00:41:09 -0800100 return front().either_count_changed() ||
101 calibration().either_count_changed() ||
102 back().either_count_changed();
103 }
104 bool front_or_back_triggered() const {
105 return front().value() || back().value();
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800106 }
107
Austin Schuhf9286cd2014-02-11 00:51:09 -0800108 double encoder() const { return encoder_; }
109 double last_encoder() const { return last_encoder_; }
110
Austin Schuhcda86af2014-02-16 16:16:39 -0800111 double offset() const { return offset_; }
112
Austin Schuhf9286cd2014-02-11 00:51:09 -0800113 // Returns true if an edge was detected in the last cycle and then sets the
114 // edge_position to the absolute position of the edge.
Austin Schuhd27931c2014-02-16 19:18:20 -0800115 bool GetPositionOfEdge(const constants::Values::Claws::Claw &claw,
Austin Schuhf9286cd2014-02-11 00:51:09 -0800116 double *edge_encoder, double *edge_angle);
117
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800118#undef COUNT_SETTER_GETTER
119
Austin Schuhcda86af2014-02-16 16:16:39 -0800120 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800121 // The accumulated voltage to apply to the motor.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800122 double offset_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800123 const char *name_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800124
Austin Schuhcda86af2014-02-16 16:16:39 -0800125 ClawMotor *motor_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800126
Brian Silvermane0a95462014-02-17 00:41:09 -0800127 HallEffectTracker front_, calibration_, back_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800128
129 JointZeroingState zeroing_state_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800130 double posedge_value_;
131 double negedge_value_;
132 double encoder_;
133 double last_encoder_;
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 Schuhcda86af2014-02-16 16:16:39 -0800152 JointZeroingState zeroing_state) {
153 double edge_encoder;
154 double edge_angle;
155 if (GetPositionOfEdge(claw_values, &edge_encoder, &edge_angle)) {
156 LOG(INFO, "Calibration edge.\n");
157 SetCalibration(edge_encoder, edge_angle);
158 set_zeroing_state(zeroing_state);
159 return true;
160 }
161 return false;
162 }
163};
164
165class BottomZeroedStateFeedbackLoop : public ZeroedStateFeedbackLoop {
166 public:
167 BottomZeroedStateFeedbackLoop(ClawMotor *motor)
168 : ZeroedStateFeedbackLoop("bottom", motor) {}
169 // Sets the calibration offset given the absolute angle and the corrisponding
170 // encoder value.
171 void SetCalibration(double edge_encoder, double edge_angle);
172
Austin Schuhd27931c2014-02-16 19:18:20 -0800173 bool SetCalibrationOnEdge(const constants::Values::Claws::Claw &claw_values,
Austin Schuhcda86af2014-02-16 16:16:39 -0800174 JointZeroingState zeroing_state) {
175 double edge_encoder;
176 double edge_angle;
177 if (GetPositionOfEdge(claw_values, &edge_encoder, &edge_angle)) {
178 LOG(INFO, "Calibration edge.\n");
179 SetCalibration(edge_encoder, edge_angle);
180 set_zeroing_state(zeroing_state);
181 return true;
182 }
183 return false;
184 }
185};
Ben Fredrickson9b388422014-02-13 06:15:31 +0000186
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800187class ClawMotor
188 : public aos::control_loops::ControlLoop<control_loops::ClawGroup> {
189 public:
190 explicit ClawMotor(control_loops::ClawGroup *my_claw =
191 &control_loops::claw_queue_group);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800192
193 // True if the state machine is ready.
Austin Schuh4cb047f2014-02-16 21:10:19 -0800194 bool capped_goal() const { return capped_goal_; }
195
196 // True if the state machine is ready.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800197 bool is_ready() const { return false; }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800198
Austin Schuhcda86af2014-02-16 16:16:39 -0800199 void ChangeTopOffset(double doffset);
200 void ChangeBottomOffset(double doffset);
201
Austin Schuh3bb9a442014-02-02 16:01:45 -0800202 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800203 virtual void RunIteration(const control_loops::ClawGroup::Goal *goal,
204 const control_loops::ClawGroup::Position *position,
205 control_loops::ClawGroup::Output *output,
206 ::aos::control_loops::Status *status);
207
Austin Schuhcda86af2014-02-16 16:16:39 -0800208 double top_absolute_position() const {
209 return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
210 }
211 double bottom_absolute_position() const { return claw_.X_hat(0, 0); }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800212
213 private:
214 // Friend the test classes for acces to the internal state.
215 friend class testing::ClawTest_NoWindupPositive_Test;
216 friend class testing::ClawTest_NoWindupNegative_Test;
217
218 // The zeroed joint to use.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800219 bool has_top_claw_goal_;
220 double top_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800221 TopZeroedStateFeedbackLoop top_claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800222
223 bool has_bottom_claw_goal_;
224 double bottom_claw_goal_;
Austin Schuhcda86af2014-02-16 16:16:39 -0800225 BottomZeroedStateFeedbackLoop bottom_claw_;
226
227 // The claw loop.
228 ClawLimitedLoop claw_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800229
230 bool was_enabled_;
Ben Fredrickson9b388422014-02-13 06:15:31 +0000231 bool doing_calibration_fine_tune_;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800232
Austin Schuhcda86af2014-02-16 16:16:39 -0800233 // The initial seperation when disabled. Used as the safe seperation
234 // distance.
235 double initial_seperation_;
236
Austin Schuh4cb047f2014-02-16 21:10:19 -0800237 bool capped_goal_;
238
Austin Schuh3bb9a442014-02-02 16:01:45 -0800239 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
240};
241
242} // namespace control_loops
243} // namespace frc971
244
245#endif // FRC971_CONTROL_LOOPS_CLAW_CLAW_H_