blob: 54dc032f7e355b43c9b394f8bcb7f907a15c29a6 [file] [log] [blame]
Ben Fredrickson6b5ba792015-01-25 17:14:40 -08001#ifndef FRC971_CONTROL_LOOPS_FRIDGE_H_
2#define FRC971_CONTROL_LOOPS_FRIDGE_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 "frc971/control_loops/fridge/fridge.q.h"
9#include "frc971/control_loops/fridge/arm_motor_plant.h"
10#include "frc971/control_loops/fridge/elevator_motor_plant.h"
Austin Schuh703b8d42015-02-01 14:56:34 -080011#include "frc971/zeroing/zeroing.h"
Ben Fredrickson6b5ba792015-01-25 17:14:40 -080012
13namespace frc971 {
14namespace control_loops {
Austin Schuhdbd6bfa2015-02-14 21:25:16 -080015namespace testing {
16class FridgeTest_DisabledGoalTest_Test;
17class FridgeTest_ArmGoalPositiveWindupTest_Test;
18class FridgeTest_ElevatorGoalPositiveWindupTest_Test;
19class FridgeTest_ArmGoalNegativeWindupTest_Test;
20class FridgeTest_ElevatorGoalNegativeWindupTest_Test;
21}
Ben Fredrickson6b5ba792015-01-25 17:14:40 -080022
Austin Schuh703b8d42015-02-01 14:56:34 -080023class CappedStateFeedbackLoop : public StateFeedbackLoop<4, 2, 2> {
24 public:
25 CappedStateFeedbackLoop(StateFeedbackLoop<4, 2, 2> &&loop)
26 : StateFeedbackLoop<4, 2, 2>(::std::move(loop)), max_voltage_(12.0) {}
27
28 void set_max_voltage(double max_voltage) {
29 max_voltage_ = ::std::max(-12.0, ::std::min(12.0, max_voltage));
30 }
31
32 void CapU() override;
33
34 // Returns the amount to change the position goals (average and difference) in
35 // order to no longer saturate the controller.
36 Eigen::Matrix<double, 2, 1> UnsaturateOutputGoalChange();
37
38 private:
39 double max_voltage_;
40};
41
Ben Fredrickson6b5ba792015-01-25 17:14:40 -080042class Fridge
Brian Silverman089f5812015-02-15 01:58:19 -050043 : public aos::controls::ControlLoop<control_loops::FridgeQueue> {
Ben Fredrickson6b5ba792015-01-25 17:14:40 -080044 public:
45 explicit Fridge(
46 control_loops::FridgeQueue *fridge_queue = &control_loops::fridge_queue);
47
Austin Schuhdbd6bfa2015-02-14 21:25:16 -080048 enum State {
49 // Waiting to receive data before doing anything.
50 UNINITIALIZED = 0,
51 // Estimating the starting location.
52 INITIALIZING = 1,
53 // Moving the elevator to find an index pulse.
54 ZEROING_ELEVATOR = 2,
55 // Moving the arm to find an index pulse.
56 ZEROING_ARM = 3,
57 // All good!
58 RUNNING = 4,
59 // Internal error caused the fridge to abort.
60 ESTOP = 5,
61 };
62
63 State state() const { return state_; }
64
Ben Fredrickson6b5ba792015-01-25 17:14:40 -080065 protected:
Austin Schuh703b8d42015-02-01 14:56:34 -080066 void RunIteration(const control_loops::FridgeQueue::Goal *goal,
67 const control_loops::FridgeQueue::Position *position,
68 control_loops::FridgeQueue::Output *output,
69 control_loops::FridgeQueue::Status *status) override;
Ben Fredrickson6b5ba792015-01-25 17:14:40 -080070
71 private:
Austin Schuhdbd6bfa2015-02-14 21:25:16 -080072 friend class testing::FridgeTest_DisabledGoalTest_Test;
73 friend class testing::FridgeTest_ElevatorGoalPositiveWindupTest_Test;
74 friend class testing::FridgeTest_ArmGoalPositiveWindupTest_Test;
75 friend class testing::FridgeTest_ElevatorGoalNegativeWindupTest_Test;
76 friend class testing::FridgeTest_ArmGoalNegativeWindupTest_Test;
77
Austin Schuh703b8d42015-02-01 14:56:34 -080078 // Sets state_ to the correct state given the current state of the zeroing
79 // estimators.
80 void UpdateZeroingState();
81
82 void SetElevatorOffset(double left_offset, double right_offset);
83 void SetArmOffset(double left_offset, double right_offset);
84
85 // Getters for the current elevator positions.
86 double left_elevator();
87 double right_elevator();
88 double elevator();
89
90 // Getters for the current arm positions.
91 double left_arm();
92 double right_arm();
93 double arm();
94
95 // Our best guess at the current position of the elevator.
96 double estimated_left_elevator();
97 double estimated_right_elevator();
98 double estimated_elevator();
99
100 // Our best guess at the current position of the arm.
101 double estimated_left_arm();
102 double estimated_right_arm();
103 double estimated_arm();
104
105 // Returns the current zeroing velocity for either subsystem.
106 // If the subsystem is too far away from the center, these will switch
107 // directions.
108 double elevator_zeroing_velocity();
109 double arm_zeroing_velocity();
110
111 // Corrects the Observer with the current position.
112 void Correct();
113
Ben Fredrickson6b5ba792015-01-25 17:14:40 -0800114 // The state feedback control loop or loops to talk to.
Austin Schuh703b8d42015-02-01 14:56:34 -0800115 ::std::unique_ptr<CappedStateFeedbackLoop> arm_loop_;
116 ::std::unique_ptr<CappedStateFeedbackLoop> elevator_loop_;
117
118 zeroing::ZeroingEstimator left_arm_estimator_;
119 zeroing::ZeroingEstimator right_arm_estimator_;
120 zeroing::ZeroingEstimator left_elevator_estimator_;
121 zeroing::ZeroingEstimator right_elevator_estimator_;
122
123 // Offsets from the encoder position to the absolute position. Add these to
124 // the encoder position to get the absolute position.
125 double left_elevator_offset_ = 0.0;
126 double right_elevator_offset_ = 0.0;
127 double left_arm_offset_ = 0.0;
128 double right_arm_offset_ = 0.0;
129
130 // Current velocity to move at while zeroing.
131 double elevator_zeroing_velocity_ = 0.0;
132 double arm_zeroing_velocity_ = 0.0;
133
134 // The goals for the elevator and arm.
135 double elevator_goal_ = 0.0;
136 double arm_goal_ = 0.0;
137
138 State state_ = UNINITIALIZED;
139 State last_state_ = UNINITIALIZED;
140
141 control_loops::FridgeQueue::Position current_position_;
Ben Fredrickson6b5ba792015-01-25 17:14:40 -0800142};
143
144} // namespace control_loops
145} // namespace frc971
146
147#endif // FRC971_CONTROL_LOOPS_FRIDGE_H_
148