blob: 2946b67c1fd66d4447dd801cdaceb093c42cf377 [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
Austin Schuh60c56662014-02-17 14:37:19 -080076 bool SetCalibrationOnEdge(const constants::Values::Shooter &shooter_values,
77 JointZeroingState zeroing_state) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000078 double edge_encoder;
79 double known_position;
Ben Fredricksonedf0e092014-02-16 10:46:50 +000080 if (GetPositionOfEdge(shooter_values, &edge_encoder, &known_position)) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000081 LOG(INFO, "Calibration edge.\n");
82 SetCalibration(edge_encoder, known_position);
83 set_zeroing_state(zeroing_state);
84 return true;
85 }
86 return false;
87 }
88
Ben Fredrickson22c93322014-02-17 05:56:33 +000089 void SetPositionDirectly(double position) { X_hat(0, 0) = position; }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000090
Ben Fredricksonedf0e092014-02-16 10:46:50 +000091 void SetPositionValues(double position) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000092 Eigen::Matrix<double, 1, 1> Y;
93 Y << position;
Ben Fredrickson22c93322014-02-17 05:56:33 +000094 LOG(INFO, "Setting position to %f\n", position);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000095 Correct(Y);
96 }
97
Ben Fredrickson22c93322014-02-17 05:56:33 +000098 void SetGoalPosition(double desired_position, double desired_velocity) {
99 // austin said something about which matrix to set, but I didn't under
100 // very much of it
101 //some_matrix = {desired_position, desired_velocity};
102 LOG(INFO, "ZSFL> dp: %.2f dz: %.2f\n", desired_position, desired_velocity);
103 R << desired_position, desired_velocity, 0;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000104 }
105
106 double position() const { return X_hat(0, 0); }
107 double encoder() const { return encoder_; }
108 double last_encoder() const { return last_encoder_; }
109
110 // Returns true if an edge was detected in the last cycle and then sets the
111 // edge_position to the absolute position of the edge.
Austin Schuh60c56662014-02-17 14:37:19 -0800112 bool GetPositionOfEdge(const constants::Values::Shooter &shooter,
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000113 double *edge_encoder, double *known_position);
114
115#undef COUNT_SETTER_GETTER
116
117 private:
118 // The accumulated voltage to apply to the motor.
119 double voltage_;
120 double last_voltage_;
121 double uncapped_voltage_;
122 double offset_;
123
124 double previous_position_;
125
126 JointZeroingState zeroing_state_;
127 double encoder_;
128 double last_encoder_;
129};
130
joe93778a62014-02-15 13:22:14 -0800131class ShooterMotor
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000132 : public aos::control_loops::ControlLoop<control_loops::ShooterGroup> {
joe93778a62014-02-15 13:22:14 -0800133 public:
Ben Fredrickson22c93322014-02-17 05:56:33 +0000134 explicit ShooterMotor(control_loops::ShooterGroup *my_shooter =
135 &control_loops::shooter_queue_group);
joe93778a62014-02-15 13:22:14 -0800136
137 // True if the goal was moved to avoid goal windup.
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000138 //bool capped_goal() const { return shooter_.capped_goal(); }
joe93778a62014-02-15 13:22:14 -0800139
Ben Fredrickson4413f3b2014-02-16 23:25:36 +0000140 double PowerToPosition(double power) {
Ben Fredrickson22c93322014-02-17 05:56:33 +0000141 //LOG(WARNING, "power to position not correctly implemented\n");
Ben Fredrickson4413f3b2014-02-16 23:25:36 +0000142 const frc971::constants::Values &values = constants::GetValues();
143 double new_pos =
144 (power > values.shooter.upper_limit) ? values.shooter.upper_limit
Ben Fredrickson22c93322014-02-17 05:56:33 +0000145 : (power < 0.0)
146 ? 0.0
147 : power;
Ben Fredrickson4413f3b2014-02-16 23:25:36 +0000148
149 return new_pos;
150 }
151
Ben Fredrickson22c93322014-02-17 05:56:33 +0000152 typedef enum {
153 STATE_INITIALIZE = 0,
154 STATE_REQUEST_LOAD = 1,
155 STATE_LOAD_BACKTRACK = 2,
156 STATE_LOAD = 3,
157 STATE_LOADING_PROBLEM = 4,
158 STATE_PREPARE_SHOT = 5,
159 STATE_READY = 6,
160 STATE_REQUEST_FIRE = 7,
161 STATE_PREPARE_FIRE = 8,
162 STATE_FIRE = 9,
163 STATE_UNLOAD = 10,
164 STATE_UNLOAD_MOVE = 11,
165 STATE_READY_UNLOAD = 12
166 } State;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000167
Ben Fredricksona6d77542014-02-17 07:54:43 +0000168 State GetState() {return state_;}
169
170 double GetPosition() { return shooter_.position() - calibration_position_; }
171
joe93778a62014-02-15 13:22:14 -0800172 protected:
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000173
joe93778a62014-02-15 13:22:14 -0800174 virtual void RunIteration(
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000175 const ShooterGroup::Goal *goal,
176 const control_loops::ShooterGroup::Position *position,
Ben Fredrickson22c93322014-02-17 05:56:33 +0000177 ShooterGroup::Output *output, ShooterGroup::Status *status);
joe93778a62014-02-15 13:22:14 -0800178
179 private:
180 // Friend the test classes for acces to the internal state.
181 friend class testing::ShooterTest_NoWindupPositive_Test;
182 friend class testing::ShooterTest_NoWindupNegative_Test;
183
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000184 control_loops::ShooterGroup::Position last_position_;
185
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000186 ZeroedStateFeedbackLoop shooter_;
joe93778a62014-02-15 13:22:14 -0800187
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000188 // position need to zero
189 double calibration_position_;
190
191 // state machine state
192 State state_;
193
194 // time to giving up on loading problem
195 Time loading_problem_end_time_;
196
197 // wait for brake to set
198 Time shooter_brake_set_time_;
199
200 // we are attempting to take up some of the backlash
201 // in the gears before the plunger hits
202 Time prepare_fire_end_time_;
203
204 // time that shot must have completed
205 Time shot_end_time_;
206
207 // track cycles that we are stuck to detect errors
208 int cycles_not_moved_;
209
Ben Fredrickson22c93322014-02-17 05:56:33 +0000210 // setup on the intial loop may involve shortcuts
211 bool initial_loop_;
212
joe93778a62014-02-15 13:22:14 -0800213 DISALLOW_COPY_AND_ASSIGN(ShooterMotor);
214};
215
216} // namespace control_loops
217} // namespace frc971
218
219#endif // FRC971_CONTROL_LOOPS_shooter_shooter_H_