blob: 9d134aff0b9d767246cfd4ea82d4514628ac225a [file] [log] [blame]
joe93778a62014-02-15 13:22:14 -08001#ifndef FRC971_CONTROL_LOOPS_shooter_shooter_H_
2#define FRC971_CONTROL_LOOPS_shooter_shooter_H_
3
4#include <memory>
5
6#include "aos/common/control_loop/ControlLoop.h"
7#include "frc971/control_loops/state_feedback_loop.h"
Ben Fredricksonedf0e092014-02-16 10:46:50 +00008#include "aos/common/time.h"
joe93778a62014-02-15 13:22:14 -08009
Ben Fredricksonedf0e092014-02-16 10:46:50 +000010#include "frc971/constants.h"
joe93778a62014-02-15 13:22:14 -080011#include "frc971/control_loops/shooter/shooter_motor_plant.h"
12#include "frc971/control_loops/shooter/shooter.q.h"
13
joe93778a62014-02-15 13:22:14 -080014namespace frc971 {
15namespace control_loops {
16namespace testing {
17class ShooterTest_NoWindupPositive_Test;
18class ShooterTest_NoWindupNegative_Test;
19};
20
Ben Fredricksonedf0e092014-02-16 10:46:50 +000021using ::aos::time::Time;
22
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000023// Note: Everything in this file assumes that there is a 1 cycle delay between
24// power being requested and it showing up at the motor. It assumes that
25// X_hat(2, 1) is the voltage being applied as well. It will go unstable if
26// that isn't true.
27
28// This class implements the CapU function correctly given all the extra
29// information that we know about from the wrist motor.
30// It does not have any zeroing logic in it, only logic to deal with a delta U
31// controller.
32class ZeroedStateFeedbackLoop : public StateFeedbackLoop<3, 1, 1> {
33 public:
34 ZeroedStateFeedbackLoop(StateFeedbackLoop<3, 1, 1> loop)
35 : StateFeedbackLoop<3, 1, 1>(loop),
36 voltage_(0.0),
37 last_voltage_(0.0),
38 uncapped_voltage_(0.0),
39 offset_(0.0),
40 encoder_(0.0),
Ben Fredrickson22c93322014-02-17 05:56:33 +000041 last_encoder_(0.0) {}
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000042
43 const static int kZeroingMaxVoltage = 5;
44
45 // Caps U, but this time respects the state of the wrist as well.
46 virtual void CapU();
47
48 // Returns the accumulated voltage.
49 double voltage() const { return voltage_; }
50
51 // Returns the uncapped voltage.
52 double uncapped_voltage() const { return uncapped_voltage_; }
53
54 // Zeros the accumulator.
55 void ZeroPower() { voltage_ = 0.0; }
56
57 enum JointZeroingState {
58 // We don't know where the joint is at all.
59 UNKNOWN_POSITION,
60 // Ready for use during teleop.
61 CALIBRATED
62 };
63
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000064 void set_zeroing_state(JointZeroingState zeroing_state) {
65 zeroing_state_ = zeroing_state;
66 }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000067
68 JointZeroingState zeroing_state() const { return zeroing_state_; }
69
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000070 // Sets the calibration offset given the absolute angle and the corrisponding
71 // encoder value.
72 void SetCalibration(double encoder_val, double known_position) {
73 offset_ = known_position - encoder_val;
74 }
75
Ben Fredrickson22c93322014-02-17 05:56:33 +000076 bool SetCalibrationOnEdge(
77 const constants::Values::ShooterLimits &shooter_values,
78 JointZeroingState zeroing_state) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000079 double edge_encoder;
80 double known_position;
Ben Fredricksonedf0e092014-02-16 10:46:50 +000081 if (GetPositionOfEdge(shooter_values, &edge_encoder, &known_position)) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000082 LOG(INFO, "Calibration edge.\n");
83 SetCalibration(edge_encoder, known_position);
84 set_zeroing_state(zeroing_state);
85 return true;
86 }
87 return false;
88 }
89
Ben Fredrickson22c93322014-02-17 05:56:33 +000090 void SetPositionDirectly(double position) { X_hat(0, 0) = position; }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000091
Ben Fredricksonedf0e092014-02-16 10:46:50 +000092 void SetPositionValues(double position) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000093 Eigen::Matrix<double, 1, 1> Y;
94 Y << position;
Ben Fredrickson22c93322014-02-17 05:56:33 +000095 LOG(INFO, "Setting position to %f\n", position);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000096 Correct(Y);
97 }
98
Ben Fredrickson22c93322014-02-17 05:56:33 +000099 void SetGoalPosition(double desired_position, double desired_velocity) {
100 // austin said something about which matrix to set, but I didn't under
101 // very much of it
102 //some_matrix = {desired_position, desired_velocity};
103 LOG(INFO, "ZSFL> dp: %.2f dz: %.2f\n", desired_position, desired_velocity);
104 R << desired_position, desired_velocity, 0;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000105 }
106
107 double position() const { return X_hat(0, 0); }
108 double encoder() const { return encoder_; }
109 double last_encoder() const { return last_encoder_; }
110
111 // Returns true if an edge was detected in the last cycle and then sets the
112 // edge_position to the absolute position of the edge.
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000113 bool GetPositionOfEdge(const constants::Values::ShooterLimits &shooter,
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000114 double *edge_encoder, double *known_position);
115
116#undef COUNT_SETTER_GETTER
117
118 private:
119 // The accumulated voltage to apply to the motor.
120 double voltage_;
121 double last_voltage_;
122 double uncapped_voltage_;
123 double offset_;
124
125 double previous_position_;
126
127 JointZeroingState zeroing_state_;
128 double encoder_;
129 double last_encoder_;
130};
131
joe93778a62014-02-15 13:22:14 -0800132class ShooterMotor
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000133 : public aos::control_loops::ControlLoop<control_loops::ShooterGroup> {
joe93778a62014-02-15 13:22:14 -0800134 public:
Ben Fredrickson22c93322014-02-17 05:56:33 +0000135 explicit ShooterMotor(control_loops::ShooterGroup *my_shooter =
136 &control_loops::shooter_queue_group);
joe93778a62014-02-15 13:22:14 -0800137
138 // True if the goal was moved to avoid goal windup.
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000139 //bool capped_goal() const { return shooter_.capped_goal(); }
joe93778a62014-02-15 13:22:14 -0800140
Ben Fredrickson4413f3b2014-02-16 23:25:36 +0000141 double PowerToPosition(double power) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000142 //LOG(WARNING, "power to position not correctly implemented\n");
Ben Fredrickson4413f3b2014-02-16 23:25:36 +0000143 const frc971::constants::Values &values = constants::GetValues();
144 double new_pos =
145 (power > values.shooter.upper_limit) ? values.shooter.upper_limit
Ben Fredrickson22c93322014-02-17 05:56:33 +0000146 : (power < 0.0)
147 ? 0.0
148 : power;
Ben Fredrickson4413f3b2014-02-16 23:25:36 +0000149
150 return new_pos;
151 }
152
Ben Fredrickson22c93322014-02-17 05:56:33 +0000153 typedef enum {
154 STATE_INITIALIZE = 0,
155 STATE_REQUEST_LOAD = 1,
156 STATE_LOAD_BACKTRACK = 2,
157 STATE_LOAD = 3,
158 STATE_LOADING_PROBLEM = 4,
159 STATE_PREPARE_SHOT = 5,
160 STATE_READY = 6,
161 STATE_REQUEST_FIRE = 7,
162 STATE_PREPARE_FIRE = 8,
163 STATE_FIRE = 9,
164 STATE_UNLOAD = 10,
165 STATE_UNLOAD_MOVE = 11,
166 STATE_READY_UNLOAD = 12
167 } State;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000168
Ben Fredricksona6d77542014-02-17 07:54:43 +0000169 State GetState() {return state_;}
170
171 double GetPosition() { return shooter_.position() - calibration_position_; }
172
joe93778a62014-02-15 13:22:14 -0800173 protected:
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000174
joe93778a62014-02-15 13:22:14 -0800175 virtual void RunIteration(
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000176 const ShooterGroup::Goal *goal,
177 const control_loops::ShooterGroup::Position *position,
Ben Fredrickson22c93322014-02-17 05:56:33 +0000178 ShooterGroup::Output *output, ShooterGroup::Status *status);
joe93778a62014-02-15 13:22:14 -0800179
180 private:
181 // Friend the test classes for acces to the internal state.
182 friend class testing::ShooterTest_NoWindupPositive_Test;
183 friend class testing::ShooterTest_NoWindupNegative_Test;
184
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000185 control_loops::ShooterGroup::Position last_position_;
186
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000187 ZeroedStateFeedbackLoop shooter_;
joe93778a62014-02-15 13:22:14 -0800188
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000189 // position need to zero
190 double calibration_position_;
191
192 // state machine state
193 State state_;
194
195 // time to giving up on loading problem
196 Time loading_problem_end_time_;
197
198 // wait for brake to set
199 Time shooter_brake_set_time_;
200
201 // we are attempting to take up some of the backlash
202 // in the gears before the plunger hits
203 Time prepare_fire_end_time_;
204
205 // time that shot must have completed
206 Time shot_end_time_;
207
208 // track cycles that we are stuck to detect errors
209 int cycles_not_moved_;
210
Ben Fredrickson22c93322014-02-17 05:56:33 +0000211 // setup on the intial loop may involve shortcuts
212 bool initial_loop_;
213
joe93778a62014-02-15 13:22:14 -0800214 DISALLOW_COPY_AND_ASSIGN(ShooterMotor);
215};
216
217} // namespace control_loops
218} // namespace frc971
219
220#endif // FRC971_CONTROL_LOOPS_shooter_shooter_H_