blob: efb4480205adfab8a94fed00ee5ceb804be494ef [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),
Austin Schuh30537882014-02-18 01:07:23 -080039 offset_(0.0) {}
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000040
41 const static int kZeroingMaxVoltage = 5;
42
43 // Caps U, but this time respects the state of the wrist as well.
44 virtual void CapU();
45
46 // Returns the accumulated voltage.
47 double voltage() const { return voltage_; }
48
49 // Returns the uncapped voltage.
50 double uncapped_voltage() const { return uncapped_voltage_; }
51
52 // Zeros the accumulator.
53 void ZeroPower() { voltage_ = 0.0; }
54
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000055 // Sets the calibration offset given the absolute angle and the corrisponding
56 // encoder value.
Austin Schuh30537882014-02-18 01:07:23 -080057 void SetCalibration(double encoder_val, double known_position);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000058
Austin Schuh30537882014-02-18 01:07:23 -080059 double offset() const { return offset_; }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000060
Austin Schuh30537882014-02-18 01:07:23 -080061 double absolute_position() const { return X_hat(0, 0) + kPositionOffset; }
Austin Schuhbe1401f2014-02-18 03:18:41 -080062 double absolute_velocity() const { return X_hat(1, 0); }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000063
Austin Schuh30537882014-02-18 01:07:23 -080064 void CorrectPosition(double position) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000065 Eigen::Matrix<double, 1, 1> Y;
Austin Schuh30537882014-02-18 01:07:23 -080066 Y << position + offset_ - kPositionOffset;
Brian Silverman2508c082014-02-17 15:45:02 -080067 LOG(DEBUG, "Setting position to %f\n", position);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000068 Correct(Y);
69 }
70
Austin Schuh30537882014-02-18 01:07:23 -080071 double goal_position() const { return R(0, 0) + kPositionOffset; }
72 double goal_velocity() const { return R(1, 0); }
73 void InitializeState(double position) {
74 X_hat(0, 0) = position - kPositionOffset;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000075 }
76
Austin Schuh30537882014-02-18 01:07:23 -080077 void SetGoalPosition(double desired_position, double desired_velocity) {
Austin Schuhbe1401f2014-02-18 03:18:41 -080078 LOG(DEBUG, "Goal position: %f Goal velocity: %f\n", desired_position, desired_velocity);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000079
Austin Schuh30537882014-02-18 01:07:23 -080080 R << desired_position - kPositionOffset, desired_velocity,
Austin Schuhbe1401f2014-02-18 03:18:41 -080081 (-A(1, 0) / A(1, 2) * (desired_position - kPositionOffset) -
82 A(1, 1) / A(1, 2) * desired_velocity);
Austin Schuh30537882014-02-18 01:07:23 -080083 }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000084
Austin Schuh30537882014-02-18 01:07:23 -080085 double position() const { return X_hat(0, 0) - offset_ + kPositionOffset; }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000086
87 private:
Austin Schuh30537882014-02-18 01:07:23 -080088 // The offset between what is '0' (0 rate on the spring) and the 0 (all the
89 // way cocked).
90 constexpr static double kPositionOffset = 0.305054 + 0.0254;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000091 // The accumulated voltage to apply to the motor.
92 double voltage_;
93 double last_voltage_;
94 double uncapped_voltage_;
95 double offset_;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000096};
97
joe93778a62014-02-15 13:22:14 -080098class ShooterMotor
Ben Fredricksonedf0e092014-02-16 10:46:50 +000099 : public aos::control_loops::ControlLoop<control_loops::ShooterGroup> {
joe93778a62014-02-15 13:22:14 -0800100 public:
Ben Fredrickson22c93322014-02-17 05:56:33 +0000101 explicit ShooterMotor(control_loops::ShooterGroup *my_shooter =
102 &control_loops::shooter_queue_group);
joe93778a62014-02-15 13:22:14 -0800103
104 // True if the goal was moved to avoid goal windup.
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000105 //bool capped_goal() const { return shooter_.capped_goal(); }
joe93778a62014-02-15 13:22:14 -0800106
Austin Schuh30537882014-02-18 01:07:23 -0800107 double PowerToPosition(double power);
Ben Fredrickson4413f3b2014-02-16 23:25:36 +0000108
Ben Fredrickson22c93322014-02-17 05:56:33 +0000109 typedef enum {
110 STATE_INITIALIZE = 0,
111 STATE_REQUEST_LOAD = 1,
112 STATE_LOAD_BACKTRACK = 2,
113 STATE_LOAD = 3,
114 STATE_LOADING_PROBLEM = 4,
115 STATE_PREPARE_SHOT = 5,
116 STATE_READY = 6,
Austin Schuh30537882014-02-18 01:07:23 -0800117 STATE_PREPARE_FIRE = 7,
118 STATE_FIRE = 8,
119 STATE_UNLOAD = 9,
120 STATE_UNLOAD_MOVE = 10,
121 STATE_READY_UNLOAD = 11,
122 STATE_ESTOP = 12
Ben Fredrickson22c93322014-02-17 05:56:33 +0000123 } State;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000124
Austin Schuh30537882014-02-18 01:07:23 -0800125 State state() { return state_; }
Ben Fredricksona6d77542014-02-17 07:54:43 +0000126
joe93778a62014-02-15 13:22:14 -0800127 protected:
128 virtual void RunIteration(
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000129 const ShooterGroup::Goal *goal,
130 const control_loops::ShooterGroup::Position *position,
Ben Fredrickson22c93322014-02-17 05:56:33 +0000131 ShooterGroup::Output *output, ShooterGroup::Status *status);
joe93778a62014-02-15 13:22:14 -0800132
133 private:
134 // Friend the test classes for acces to the internal state.
135 friend class testing::ShooterTest_NoWindupPositive_Test;
136 friend class testing::ShooterTest_NoWindupNegative_Test;
137
Austin Schuh30537882014-02-18 01:07:23 -0800138 // Enter state STATE_UNLOAD
139 void Unload() {
140 state_ = STATE_UNLOAD;
141 unload_timeout_ = Time::Now() + Time::InSeconds(1);
142 }
143 // Enter state STATE_LOAD
144 void Load() {
145 state_ = STATE_LOAD;
146 load_timeout_ = Time::Now() + Time::InSeconds(1);
147 }
148
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000149 control_loops::ShooterGroup::Position last_position_;
150
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000151 ZeroedStateFeedbackLoop shooter_;
joe93778a62014-02-15 13:22:14 -0800152
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000153 // state machine state
154 State state_;
155
156 // time to giving up on loading problem
157 Time loading_problem_end_time_;
158
Austin Schuh30537882014-02-18 01:07:23 -0800159 // The end time when loading for it to timeout.
160 Time load_timeout_;
161
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000162 // wait for brake to set
163 Time shooter_brake_set_time_;
Austin Schuh30537882014-02-18 01:07:23 -0800164
165 // The timeout for unloading.
166 Time unload_timeout_;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000167
168 // we are attempting to take up some of the backlash
169 // in the gears before the plunger hits
170 Time prepare_fire_end_time_;
171
172 // time that shot must have completed
173 Time shot_end_time_;
174
175 // track cycles that we are stuck to detect errors
176 int cycles_not_moved_;
177
Austin Schuh30537882014-02-18 01:07:23 -0800178 double firing_starting_position_;
179
180 // True if the latch should be engaged and the brake should be engaged.
181 bool latch_piston_;
182 bool brake_piston_;
183 int32_t last_distal_posedge_count_;
184 int32_t last_proximal_posedge_count_;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000185
joe93778a62014-02-15 13:22:14 -0800186 DISALLOW_COPY_AND_ASSIGN(ShooterMotor);
187};
188
189} // namespace control_loops
190} // namespace frc971
191
192#endif // FRC971_CONTROL_LOOPS_shooter_shooter_H_