blob: b585fbb588943f9a4c060917908f56760bebc37e [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"
10#include "frc971/control_loops/claw/top_claw_motor_plant.h"
11#include "frc971/control_loops/claw/bottom_claw_motor_plant.h"
12
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
25// This class implements the CapU function correctly given all the extra
26// information that we know about from the wrist motor.
27// It does not have any zeroing logic in it, only logic to deal with a delta U
28// controller.
29class ZeroedStateFeedbackLoop : public StateFeedbackLoop<3, 1, 1> {
Austin Schuh3bb9a442014-02-02 16:01:45 -080030 public:
Austin Schuh4b7b5d02014-02-10 21:20:34 -080031 ZeroedStateFeedbackLoop(StateFeedbackLoop<3, 1, 1> loop)
32 : StateFeedbackLoop<3, 1, 1>(loop),
33 voltage_(0.0),
34 last_voltage_(0.0),
35 uncapped_voltage_(0.0),
Austin Schuhf9286cd2014-02-11 00:51:09 -080036 offset_(0.0),
Austin Schuh4b7b5d02014-02-10 21:20:34 -080037 front_hall_effect_posedge_count_(0.0),
38 previous_front_hall_effect_posedge_count_(0.0),
39 front_hall_effect_negedge_count_(0.0),
40 previous_front_hall_effect_negedge_count_(0.0),
41 calibration_hall_effect_posedge_count_(0.0),
42 previous_calibration_hall_effect_posedge_count_(0.0),
43 calibration_hall_effect_negedge_count_(0.0),
44 previous_calibration_hall_effect_negedge_count_(0.0),
45 back_hall_effect_posedge_count_(0.0),
46 previous_back_hall_effect_posedge_count_(0.0),
47 back_hall_effect_negedge_count_(0.0),
48 previous_back_hall_effect_negedge_count_(0.0),
Austin Schuhf9286cd2014-02-11 00:51:09 -080049 zeroing_state_(UNKNOWN_POSITION),
50 posedge_value_(0.0),
51 negedge_value_(0.0),
52 encoder_(0.0),
53 last_encoder_(0.0) {}
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 // Caps U, but this time respects the state of the wrist as well.
58 virtual void CapU();
Austin Schuh3bb9a442014-02-02 16:01:45 -080059
Austin Schuh4b7b5d02014-02-10 21:20:34 -080060 // Returns the accumulated voltage.
61 double voltage() const { return voltage_; }
Austin Schuh3bb9a442014-02-02 16:01:45 -080062
Austin Schuh4b7b5d02014-02-10 21:20:34 -080063 // Returns the uncapped voltage.
64 double uncapped_voltage() const { return uncapped_voltage_; }
65
66 // Zeros the accumulator.
67 void ZeroPower() { voltage_ = 0.0; }
68
69 enum JointZeroingState {
70 // We don't know where the joint is at all.
71 UNKNOWN_POSITION,
72 // We have an approximate position for where the claw is using.
73 APPROXIMATE_CALIBRATION,
74 // We observed the calibration edge while disabled. This is good enough for
75 // autonomous mode.
76 DISABLED_CALIBRATION,
77 // Ready for use during teleop.
78 CALIBRATED
79 };
80
81 void set_zeroing_state(JointZeroingState zeroing_state) {
82 zeroing_state_ = zeroing_state;
83 }
84 JointZeroingState zeroing_state() const { return zeroing_state_; }
85
Austin Schuhf9286cd2014-02-11 00:51:09 -080086 // Sets the calibration offset given the absolute angle and the corrisponding
87 // encoder value.
88 void SetCalibration(double edge_encoder, double edge_angle) {
89 offset_ = edge_angle - edge_encoder;
90 }
91
92 bool SetCalibrationOnEdge(const constants::Values::Claw &claw_values,
93 JointZeroingState zeroing_state) {
94 double edge_encoder;
95 double edge_angle;
96 if (GetPositionOfEdge(claw_values, &edge_encoder, &edge_angle)) {
97 LOG(INFO, "Calibration edge.\n");
98 SetCalibration(edge_encoder, edge_angle);
99 set_zeroing_state(zeroing_state);
100 return true;
101 }
102 return false;
103 }
104
105 void SetPositionValues(const Claw &claw) {
106 set_front_hall_effect_posedge_count(claw.front_hall_effect_posedge_count);
107 set_front_hall_effect_negedge_count(claw.front_hall_effect_negedge_count);
108 set_calibration_hall_effect_posedge_count(
109 claw.calibration_hall_effect_posedge_count);
110 set_calibration_hall_effect_negedge_count(
111 claw.calibration_hall_effect_negedge_count);
112 set_back_hall_effect_posedge_count(claw.back_hall_effect_posedge_count);
113 set_back_hall_effect_negedge_count(claw.back_hall_effect_negedge_count);
114
115 posedge_value_ = claw.posedge_value;
116 negedge_value_ = claw.negedge_value;
117 Eigen::Matrix<double, 1, 1> Y;
118 Y << claw.position;
119 Correct(Y);
120 }
121
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800122#define COUNT_SETTER_GETTER(variable) \
123 void set_##variable(int32_t value) { \
124 previous_##variable##_ = variable##_; \
125 variable##_ = value; \
126 } \
127 int32_t variable() const { return variable##_; } \
128 bool variable##_changed() const { \
129 return previous_##variable##_ != variable##_; \
130 }
131
Austin Schuhf9286cd2014-02-11 00:51:09 -0800132 // TODO(austin): Pull all this out of the new sub structure.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800133 COUNT_SETTER_GETTER(front_hall_effect_posedge_count);
134 COUNT_SETTER_GETTER(front_hall_effect_negedge_count);
135 COUNT_SETTER_GETTER(calibration_hall_effect_posedge_count);
136 COUNT_SETTER_GETTER(calibration_hall_effect_negedge_count);
137 COUNT_SETTER_GETTER(back_hall_effect_posedge_count);
138 COUNT_SETTER_GETTER(back_hall_effect_negedge_count);
139
140 bool any_hall_effect_changed() const {
141 return front_hall_effect_posedge_count_changed() ||
142 front_hall_effect_negedge_count_changed() ||
143 calibration_hall_effect_posedge_count_changed() ||
144 calibration_hall_effect_negedge_count_changed() ||
145 back_hall_effect_posedge_count_changed() ||
146 back_hall_effect_negedge_count_changed();
147 }
148
Austin Schuhf9286cd2014-02-11 00:51:09 -0800149 double position() const { return X_hat(0, 0); }
150 double encoder() const { return encoder_; }
151 double last_encoder() const { return last_encoder_; }
152
153 // Returns true if an edge was detected in the last cycle and then sets the
154 // edge_position to the absolute position of the edge.
155 bool GetPositionOfEdge(const constants::Values::Claw &claw,
156 double *edge_encoder, double *edge_angle);
157
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800158#undef COUNT_SETTER_GETTER
159
160 private:
161 // The accumulated voltage to apply to the motor.
162 double voltage_;
163 double last_voltage_;
164 double uncapped_voltage_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800165 double offset_;
166
167 double previous_position_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800168
169 int32_t front_hall_effect_posedge_count_;
170 int32_t previous_front_hall_effect_posedge_count_;
171 int32_t front_hall_effect_negedge_count_;
172 int32_t previous_front_hall_effect_negedge_count_;
173 int32_t calibration_hall_effect_posedge_count_;
174 int32_t previous_calibration_hall_effect_posedge_count_;
175 int32_t calibration_hall_effect_negedge_count_;
176 int32_t previous_calibration_hall_effect_negedge_count_;
177 int32_t back_hall_effect_posedge_count_;
178 int32_t previous_back_hall_effect_posedge_count_;
179 int32_t back_hall_effect_negedge_count_;
180 int32_t previous_back_hall_effect_negedge_count_;
181
182 JointZeroingState zeroing_state_;
Austin Schuhf9286cd2014-02-11 00:51:09 -0800183 double posedge_value_;
184 double negedge_value_;
185 double encoder_;
186 double last_encoder_;
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800187};
188
189class ClawMotor
190 : public aos::control_loops::ControlLoop<control_loops::ClawGroup> {
191 public:
192 explicit ClawMotor(control_loops::ClawGroup *my_claw =
193 &control_loops::claw_queue_group);
Austin Schuh3bb9a442014-02-02 16:01:45 -0800194
195 // True if the state machine is ready.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800196 bool is_ready() const { return false; }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800197
198 protected:
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800199 virtual void RunIteration(const control_loops::ClawGroup::Goal *goal,
200 const control_loops::ClawGroup::Position *position,
201 control_loops::ClawGroup::Output *output,
202 ::aos::control_loops::Status *status);
203
Austin Schuhf9286cd2014-02-11 00:51:09 -0800204 double top_absolute_position() const { return top_claw_.position(); }
205 double bottom_absolute_position() const { return bottom_claw_.position(); }
Austin Schuh3bb9a442014-02-02 16:01:45 -0800206
207 private:
208 // Friend the test classes for acces to the internal state.
209 friend class testing::ClawTest_NoWindupPositive_Test;
210 friend class testing::ClawTest_NoWindupNegative_Test;
211
212 // The zeroed joint to use.
Austin Schuh4b7b5d02014-02-10 21:20:34 -0800213 bool has_top_claw_goal_;
214 double top_claw_goal_;
215 ZeroedStateFeedbackLoop top_claw_;
216
217 bool has_bottom_claw_goal_;
218 double bottom_claw_goal_;
219 ZeroedStateFeedbackLoop bottom_claw_;
220
221 bool was_enabled_;
Austin Schuh3bb9a442014-02-02 16:01:45 -0800222
223 DISALLOW_COPY_AND_ASSIGN(ClawMotor);
224};
225
226} // namespace control_loops
227} // namespace frc971
228
229#endif // FRC971_CONTROL_LOOPS_CLAW_CLAW_H_