blob: cccb9536ed0e3fb317cd74ea309355b5462e6f70 [file] [log] [blame]
Brian Silverman17f503e2015-08-02 18:17:18 -07001#ifndef Y2014_CONTROL_LOOPS_shooter_shooter_H_
2#define Y2014_CONTROL_LOOPS_shooter_shooter_H_
3
4#include <memory>
5
6#include "aos/common/controls/control_loop.h"
7#include "frc971/control_loops/state_feedback_loop.h"
8#include "aos/common/time.h"
9
10#include "y2014/constants.h"
11#include "y2014/control_loops/shooter/shooter_motor_plant.h"
12#include "y2014/control_loops/shooter/shooter.q.h"
13
Austin Schuh24957102015-11-28 16:04:40 -080014namespace y2014 {
Brian Silverman17f503e2015-08-02 18:17:18 -070015namespace control_loops {
16namespace testing {
17class ShooterTest_UnloadWindupPositive_Test;
18class ShooterTest_UnloadWindupNegative_Test;
19class ShooterTest_RezeroWhileUnloading_Test;
20};
21
22using ::aos::time::Time;
23
24// Note: Everything in this file assumes that there is a 1 cycle delay between
25// power being requested and it showing up at the motor. It assumes that
26// X_hat(2, 1) is the voltage being applied as well. It will go unstable if
27// that isn't true.
28
29// This class implements the CapU function correctly given all the extra
30// information that we know about.
31// It does not have any zeroing logic in it, only logic to deal with a delta U
32// controller.
33class ZeroedStateFeedbackLoop : public StateFeedbackLoop<3, 1, 1> {
34 public:
35 ZeroedStateFeedbackLoop(StateFeedbackLoop<3, 1, 1> &&loop)
36 : StateFeedbackLoop<3, 1, 1>(::std::move(loop)),
37 voltage_(0.0),
38 last_voltage_(0.0),
39 uncapped_voltage_(0.0),
40 offset_(0.0),
41 max_voltage_(12.0),
42 capped_goal_(false) {}
43
44 const static int kZeroingMaxVoltage = 5;
45
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 // Sets the calibration offset given the absolute angle and the corrisponding
58 // encoder value.
59 void SetCalibration(double encoder_val, double known_position);
60
61 double offset() const { return offset_; }
62
63 double absolute_position() const { return X_hat(0, 0) + kPositionOffset; }
64 double absolute_velocity() const { return X_hat(1, 0); }
65
66 void CorrectPosition(double position) {
67 Eigen::Matrix<double, 1, 1> Y;
68 Y << position + offset_ - kPositionOffset;
69 Correct(Y);
70 }
71
72 // Recomputes the power goal for the current controller and position/velocity.
73 void RecalculatePowerGoal();
74
75 double goal_position() const { return R(0, 0) + kPositionOffset; }
76 double goal_velocity() const { return R(1, 0); }
77 void InitializeState(double position) {
78 mutable_X_hat(0, 0) = position - kPositionOffset;
79 mutable_X_hat(1, 0) = 0.0;
80 mutable_X_hat(2, 0) = 0.0;
81 }
82
83 void SetGoalPosition(double desired_position, double desired_velocity) {
84 LOG(DEBUG, "Goal position: %f Goal velocity: %f\n", desired_position,
85 desired_velocity);
86
87 mutable_R() << desired_position - kPositionOffset, desired_velocity,
88 (-A(1, 0) / A(1, 2) * (desired_position - kPositionOffset) -
89 A(1, 1) / A(1, 2) * desired_velocity);
90 }
91
92 double position() const { return X_hat(0, 0) - offset_ + kPositionOffset; }
93
94 void set_max_voltage(double max_voltage) { max_voltage_ = max_voltage; }
95 bool capped_goal() const { return capped_goal_; }
96
97 void CapGoal();
98
99 // Friend the test classes for acces to the internal state.
100 friend class testing::ShooterTest_RezeroWhileUnloading_Test;
101
102 private:
103 // The offset between what is '0' (0 rate on the spring) and the 0 (all the
104 // way cocked).
Austin Schuh9d4aca82015-11-08 14:41:31 -0800105 constexpr static double kPositionOffset =
106 ::y2014::control_loops::shooter::kMaxExtension;
Brian Silverman17f503e2015-08-02 18:17:18 -0700107 // The accumulated voltage to apply to the motor.
108 double voltage_;
109 double last_voltage_;
110 double uncapped_voltage_;
111 double offset_;
112 double max_voltage_;
113 bool capped_goal_;
114};
115
116const Time kUnloadTimeout = Time::InSeconds(10);
Austin Schuhadf2cde2015-11-08 20:35:16 -0800117const Time kLoadTimeout = Time::InSeconds(2.0);
Brian Silverman17f503e2015-08-02 18:17:18 -0700118const Time kLoadProblemEndTimeout = Time::InSeconds(1.0);
119const Time kShooterBrakeSetTime = Time::InSeconds(0.05);
120// Time to wait after releasing the latch piston before winching back again.
121const Time kShotEndTimeout = Time::InSeconds(0.2);
122const Time kPrepareFireEndTime = Time::InMS(40);
123
124class ShooterMotor
Brian Silvermanb601d892015-12-20 18:24:38 -0500125 : public aos::controls::ControlLoop<::y2014::control_loops::ShooterQueue> {
Brian Silverman17f503e2015-08-02 18:17:18 -0700126 public:
Brian Silvermanb601d892015-12-20 18:24:38 -0500127 explicit ShooterMotor(::y2014::control_loops::ShooterQueue *my_shooter =
128 &::y2014::control_loops::shooter_queue);
Brian Silverman17f503e2015-08-02 18:17:18 -0700129
130 // True if the goal was moved to avoid goal windup.
131 bool capped_goal() const { return shooter_.capped_goal(); }
132
133 double PowerToPosition(double power);
134 double PositionToPower(double position);
Austin Schuh24957102015-11-28 16:04:40 -0800135 void CheckCalibrations(
Brian Silvermanb601d892015-12-20 18:24:38 -0500136 const ::y2014::control_loops::ShooterQueue::Position *position);
Brian Silverman17f503e2015-08-02 18:17:18 -0700137
138 typedef enum {
139 STATE_INITIALIZE = 0,
140 STATE_REQUEST_LOAD = 1,
141 STATE_LOAD_BACKTRACK = 2,
142 STATE_LOAD = 3,
143 STATE_LOADING_PROBLEM = 4,
144 STATE_PREPARE_SHOT = 5,
145 STATE_READY = 6,
146 STATE_FIRE = 8,
147 STATE_UNLOAD = 9,
148 STATE_UNLOAD_MOVE = 10,
149 STATE_READY_UNLOAD = 11,
150 STATE_ESTOP = 12
151 } State;
152
153 State state() { return state_; }
154
155 protected:
156 virtual void RunIteration(
Brian Silvermanb601d892015-12-20 18:24:38 -0500157 const ::y2014::control_loops::ShooterQueue::Goal *goal,
158 const ::y2014::control_loops::ShooterQueue::Position *position,
159 ::y2014::control_loops::ShooterQueue::Output *output,
160 ::y2014::control_loops::ShooterQueue::Status *status);
Brian Silverman17f503e2015-08-02 18:17:18 -0700161
162 private:
163 // We have to override this to keep the pistons in the correct positions.
164 virtual void ZeroOutputs();
165
166 // Friend the test classes for acces to the internal state.
167 friend class testing::ShooterTest_UnloadWindupPositive_Test;
168 friend class testing::ShooterTest_UnloadWindupNegative_Test;
169 friend class testing::ShooterTest_RezeroWhileUnloading_Test;
170
171 // Enter state STATE_UNLOAD
172 void Unload() {
173 state_ = STATE_UNLOAD;
174 unload_timeout_ = Time::Now() + kUnloadTimeout;
175 }
176 // Enter state STATE_LOAD
177 void Load() {
178 state_ = STATE_LOAD;
179 load_timeout_ = Time::Now() + kLoadTimeout;
180 }
181
Brian Silvermanb601d892015-12-20 18:24:38 -0500182 ::y2014::control_loops::ShooterQueue::Position last_position_;
Brian Silverman17f503e2015-08-02 18:17:18 -0700183
184 ZeroedStateFeedbackLoop shooter_;
185
186 // state machine state
187 State state_;
188
189 // time to giving up on loading problem
190 Time loading_problem_end_time_;
191
192 // The end time when loading for it to timeout.
193 Time load_timeout_;
194
195 // wait for brake to set
196 Time shooter_brake_set_time_;
197
198 // The timeout for unloading.
199 Time unload_timeout_;
200
201 // time that shot must have completed
202 Time shot_end_time_;
203
204 // track cycles that we are stuck to detect errors
205 int cycles_not_moved_;
206
207 double firing_starting_position_;
208
209 // True if the latch should be engaged and the brake should be engaged.
210 bool latch_piston_;
211 bool brake_piston_;
212 int32_t last_distal_posedge_count_;
213 int32_t last_proximal_posedge_count_;
214 uint32_t shot_count_;
215 bool zeroed_;
216 int distal_posedge_validation_cycles_left_;
217 int proximal_posedge_validation_cycles_left_;
218 bool last_distal_current_;
219 bool last_proximal_current_;
220
221 DISALLOW_COPY_AND_ASSIGN(ShooterMotor);
222};
223
224} // namespace control_loops
Austin Schuh24957102015-11-28 16:04:40 -0800225} // namespace y2014
Brian Silverman17f503e2015-08-02 18:17:18 -0700226
227#endif // Y2014_CONTROL_LOOPS_shooter_shooter_H_