blob: 7e99bfc5ef5a76c6525832ee618a3cbe30ef93ed [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; }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000062
Austin Schuh30537882014-02-18 01:07:23 -080063 void CorrectPosition(double position) {
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000064 Eigen::Matrix<double, 1, 1> Y;
Austin Schuh30537882014-02-18 01:07:23 -080065 Y << position + offset_ - kPositionOffset;
Brian Silverman2508c082014-02-17 15:45:02 -080066 LOG(DEBUG, "Setting position to %f\n", position);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000067 Correct(Y);
68 }
69
Austin Schuh30537882014-02-18 01:07:23 -080070 double goal_position() const { return R(0, 0) + kPositionOffset; }
71 double goal_velocity() const { return R(1, 0); }
72 void InitializeState(double position) {
73 X_hat(0, 0) = position - kPositionOffset;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000074 }
75
Austin Schuh30537882014-02-18 01:07:23 -080076 void SetGoalPosition(double desired_position, double desired_velocity) {
77 LOG(DEBUG, "Goal position: %.2f Goal velocity: %.2f\n", desired_position, desired_velocity);
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000078
Austin Schuh30537882014-02-18 01:07:23 -080079 R << desired_position - kPositionOffset, desired_velocity,
80 -A(1, 0) / A(1, 2) * (desired_position - kPositionOffset) -
81 A(1, 1) / A(1, 2) * desired_velocity;
82 }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000083
Austin Schuh30537882014-02-18 01:07:23 -080084 double position() const { return X_hat(0, 0) - offset_ + kPositionOffset; }
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000085
86 private:
Austin Schuh30537882014-02-18 01:07:23 -080087 // The offset between what is '0' (0 rate on the spring) and the 0 (all the
88 // way cocked).
89 constexpr static double kPositionOffset = 0.305054 + 0.0254;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000090 // The accumulated voltage to apply to the motor.
91 double voltage_;
92 double last_voltage_;
93 double uncapped_voltage_;
94 double offset_;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +000095};
96
joe93778a62014-02-15 13:22:14 -080097class ShooterMotor
Ben Fredricksonedf0e092014-02-16 10:46:50 +000098 : public aos::control_loops::ControlLoop<control_loops::ShooterGroup> {
joe93778a62014-02-15 13:22:14 -080099 public:
Ben Fredrickson22c93322014-02-17 05:56:33 +0000100 explicit ShooterMotor(control_loops::ShooterGroup *my_shooter =
101 &control_loops::shooter_queue_group);
joe93778a62014-02-15 13:22:14 -0800102
103 // True if the goal was moved to avoid goal windup.
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000104 //bool capped_goal() const { return shooter_.capped_goal(); }
joe93778a62014-02-15 13:22:14 -0800105
Austin Schuh30537882014-02-18 01:07:23 -0800106 double PowerToPosition(double power);
Ben Fredrickson4413f3b2014-02-16 23:25:36 +0000107
Ben Fredrickson22c93322014-02-17 05:56:33 +0000108 typedef enum {
109 STATE_INITIALIZE = 0,
110 STATE_REQUEST_LOAD = 1,
111 STATE_LOAD_BACKTRACK = 2,
112 STATE_LOAD = 3,
113 STATE_LOADING_PROBLEM = 4,
114 STATE_PREPARE_SHOT = 5,
115 STATE_READY = 6,
Austin Schuh30537882014-02-18 01:07:23 -0800116 STATE_PREPARE_FIRE = 7,
117 STATE_FIRE = 8,
118 STATE_UNLOAD = 9,
119 STATE_UNLOAD_MOVE = 10,
120 STATE_READY_UNLOAD = 11,
121 STATE_ESTOP = 12
Ben Fredrickson22c93322014-02-17 05:56:33 +0000122 } State;
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000123
Austin Schuh30537882014-02-18 01:07:23 -0800124 State state() { return state_; }
Ben Fredricksona6d77542014-02-17 07:54:43 +0000125
joe93778a62014-02-15 13:22:14 -0800126 protected:
127 virtual void RunIteration(
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000128 const ShooterGroup::Goal *goal,
129 const control_loops::ShooterGroup::Position *position,
Ben Fredrickson22c93322014-02-17 05:56:33 +0000130 ShooterGroup::Output *output, ShooterGroup::Status *status);
joe93778a62014-02-15 13:22:14 -0800131
132 private:
133 // Friend the test classes for acces to the internal state.
134 friend class testing::ShooterTest_NoWindupPositive_Test;
135 friend class testing::ShooterTest_NoWindupNegative_Test;
136
Austin Schuh30537882014-02-18 01:07:23 -0800137 // Enter state STATE_UNLOAD
138 void Unload() {
139 state_ = STATE_UNLOAD;
140 unload_timeout_ = Time::Now() + Time::InSeconds(1);
141 }
142 // Enter state STATE_LOAD
143 void Load() {
144 state_ = STATE_LOAD;
145 load_timeout_ = Time::Now() + Time::InSeconds(1);
146 }
147
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000148 control_loops::ShooterGroup::Position last_position_;
149
Ben Fredrickson1f633ef2014-02-16 05:35:45 +0000150 ZeroedStateFeedbackLoop shooter_;
joe93778a62014-02-15 13:22:14 -0800151
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000152 // state machine state
153 State state_;
154
155 // time to giving up on loading problem
156 Time loading_problem_end_time_;
157
Austin Schuh30537882014-02-18 01:07:23 -0800158 // The end time when loading for it to timeout.
159 Time load_timeout_;
160
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000161 // wait for brake to set
162 Time shooter_brake_set_time_;
Austin Schuh30537882014-02-18 01:07:23 -0800163
164 // The timeout for unloading.
165 Time unload_timeout_;
Ben Fredricksonedf0e092014-02-16 10:46:50 +0000166
167 // we are attempting to take up some of the backlash
168 // in the gears before the plunger hits
169 Time prepare_fire_end_time_;
170
171 // time that shot must have completed
172 Time shot_end_time_;
173
174 // track cycles that we are stuck to detect errors
175 int cycles_not_moved_;
176
Austin Schuh30537882014-02-18 01:07:23 -0800177 double firing_starting_position_;
178
179 // True if the latch should be engaged and the brake should be engaged.
180 bool latch_piston_;
181 bool brake_piston_;
182 int32_t last_distal_posedge_count_;
183 int32_t last_proximal_posedge_count_;
Ben Fredrickson22c93322014-02-17 05:56:33 +0000184
joe93778a62014-02-15 13:22:14 -0800185 DISALLOW_COPY_AND_ASSIGN(ShooterMotor);
186};
187
188} // namespace control_loops
189} // namespace frc971
190
191#endif // FRC971_CONTROL_LOOPS_shooter_shooter_H_