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