blob: c19328fbc82e8db572fc7e449c6193493f4d059b [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),
41 last_encoder_(0.0){}
42
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
64
65 void set_zeroing_state(JointZeroingState zeroing_state) {
66 zeroing_state_ = zeroing_state;
67 }
68
69
70 JointZeroingState zeroing_state() const { return zeroing_state_; }
71
72
73 // Sets the calibration offset given the absolute angle and the corrisponding
74 // encoder value.
75 void SetCalibration(double encoder_val, double known_position) {
76 offset_ = known_position - encoder_val;
77 }
78
79
Ben Fredricksonedf0e092014-02-16 10:46:50 +000080 bool SetCalibrationOnEdge(const constants::Values::ShooterLimits &shooter_values,
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000081 JointZeroingState zeroing_state) {
82 double edge_encoder;
83 double known_position;
Ben Fredricksonedf0e092014-02-16 10:46:50 +000084 if (GetPositionOfEdge(shooter_values, &edge_encoder, &known_position)) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000085 LOG(INFO, "Calibration edge.\n");
86 SetCalibration(edge_encoder, known_position);
87 set_zeroing_state(zeroing_state);
88 return true;
89 }
90 return false;
91 }
92
93
Ben Fredricksonedf0e092014-02-16 10:46:50 +000094 void SetPositionValues(double position) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000095 Eigen::Matrix<double, 1, 1> Y;
96 Y << position;
97 Correct(Y);
98 }
99
100
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000101 void SetGoalPosition(double desired_position,
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000102 double desired_velocity) {
103 // austin said something about which matrix to set, but I didn't under
104 // very much of it
105 //some_matrix = {desired_position, desired_velocity};
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000106 printf("%s:%d : seg fault (%.2f, %.2f)\n", __FILE__, __LINE__,
107 desired_position, desired_velocity);
108 *(const char **)(NULL) = "seg fault";
109 }
110
111 // apply a small amout of voltage outside the loop so we can
112 // take up backlash in gears
113 void ApplySomeVoltage() {
114 printf("%s:%d : seg fault\n", __FILE__, __LINE__);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000115 *(const char **)(NULL) = "seg fault";
116 }
117
118 double position() const { return X_hat(0, 0); }
119 double encoder() const { return encoder_; }
120 double last_encoder() const { return last_encoder_; }
121
122 // Returns true if an edge was detected in the last cycle and then sets the
123 // edge_position to the absolute position of the edge.
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000124 bool GetPositionOfEdge(const constants::Values::ShooterLimits &shooter,
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000125 double *edge_encoder, double *known_position);
126
127#undef COUNT_SETTER_GETTER
128
129 private:
130 // The accumulated voltage to apply to the motor.
131 double voltage_;
132 double last_voltage_;
133 double uncapped_voltage_;
134 double offset_;
135
136 double previous_position_;
137
138 JointZeroingState zeroing_state_;
139 double encoder_;
140 double last_encoder_;
141};
142
143
joe93778a62014-02-15 13:22:14 -0800144class ShooterMotor
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000145 : public aos::control_loops::ControlLoop<control_loops::ShooterGroup> {
joe93778a62014-02-15 13:22:14 -0800146 public:
147 explicit ShooterMotor(
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000148 control_loops::ShooterGroup *my_shooter = &control_loops::shooter_queue_group);
joe93778a62014-02-15 13:22:14 -0800149
150 // True if the goal was moved to avoid goal windup.
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000151 //bool capped_goal() const { return shooter_.capped_goal(); }
joe93778a62014-02-15 13:22:14 -0800152
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000153typedef enum {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000154 STATE_INITIALIZE,
155 STATE_REQUEST_LOAD,
156 STATE_LOAD_BACKTRACK,
157 STATE_LOAD,
158 STATE_LOADING_PROBLEM,
159 STATE_PREPARE_SHOT,
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000160 STATE_READY,
161 STATE_REQUEST_FIRE,
162 STATE_PREPARE_FIRE,
163 STATE_FIRE,
164 STATE_UNLOAD,
165 STATE_UNLOAD_MOVE,
166 STATE_READY_UNLOAD
167} State;
168
joe93778a62014-02-15 13:22:14 -0800169 protected:
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000170
171 double PowerToPosition(double power) { return power; }
172
joe93778a62014-02-15 13:22:14 -0800173 virtual void RunIteration(
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000174 const ShooterGroup::Goal *goal,
175 const control_loops::ShooterGroup::Position *position,
176 ShooterGroup::Output *output,
177 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
joe93778a62014-02-15 13:22:14 -0800210 DISALLOW_COPY_AND_ASSIGN(ShooterMotor);
211};
212
213} // namespace control_loops
214} // namespace frc971
215
216#endif // FRC971_CONTROL_LOOPS_shooter_shooter_H_