blob: 5761c79e36056a5d61a3f2dcf95e676b0c356def [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"
Philipp Schrader3e281412015-03-01 23:48:23 +00007#include "aos/common/util/trapezoid_profile.h"
Ben Fredrickson6b5ba792015-01-25 17:14:40 -08008#include "frc971/control_loops/state_feedback_loop.h"
9#include "frc971/control_loops/fridge/fridge.q.h"
Austin Schuh703b8d42015-02-01 14:56:34 -080010#include "frc971/zeroing/zeroing.h"
Ben Fredrickson6b5ba792015-01-25 17:14:40 -080011
12namespace frc971 {
13namespace control_loops {
Austin Schuhdbd6bfa2015-02-14 21:25:16 -080014namespace testing {
15class FridgeTest_DisabledGoalTest_Test;
16class FridgeTest_ArmGoalPositiveWindupTest_Test;
17class FridgeTest_ElevatorGoalPositiveWindupTest_Test;
18class FridgeTest_ArmGoalNegativeWindupTest_Test;
19class FridgeTest_ElevatorGoalNegativeWindupTest_Test;
Daniel Pettie1bb13e2015-02-17 13:59:15 -080020class FridgeTest_SafeArmZeroing_Test;
Austin Schuh8de10c72015-02-27 23:33:40 -080021} // namespace testing
Ben Fredrickson6b5ba792015-01-25 17:14:40 -080022
Austin Schuh8de10c72015-02-27 23:33:40 -080023template<int S>
24class CappedStateFeedbackLoop : public StateFeedbackLoop<S, 2, 2> {
Austin Schuh703b8d42015-02-01 14:56:34 -080025 public:
Austin Schuh8de10c72015-02-27 23:33:40 -080026 CappedStateFeedbackLoop(StateFeedbackLoop<S, 2, 2> &&loop)
27 : StateFeedbackLoop<S, 2, 2>(::std::move(loop)), max_voltage_(12.0) {}
Austin Schuh703b8d42015-02-01 14:56:34 -080028
29 void set_max_voltage(double max_voltage) {
Austin Schuh8de10c72015-02-27 23:33:40 -080030 max_voltage_ = ::std::max(0.0, ::std::min(12.0, max_voltage));
Austin Schuh703b8d42015-02-01 14:56:34 -080031 }
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
Philipp Schrader3e281412015-03-01 23:48:23 +0000116 double UseUnlessZero(double target_value, double default_value);
117
Ben Fredrickson6b5ba792015-01-25 17:14:40 -0800118 // The state feedback control loop or loops to talk to.
Austin Schuh8de10c72015-02-27 23:33:40 -0800119 ::std::unique_ptr<CappedStateFeedbackLoop<5>> arm_loop_;
120 ::std::unique_ptr<CappedStateFeedbackLoop<4>> elevator_loop_;
Austin Schuh703b8d42015-02-01 14:56:34 -0800121
122 zeroing::ZeroingEstimator left_arm_estimator_;
123 zeroing::ZeroingEstimator right_arm_estimator_;
124 zeroing::ZeroingEstimator left_elevator_estimator_;
125 zeroing::ZeroingEstimator right_elevator_estimator_;
126
127 // Offsets from the encoder position to the absolute position. Add these to
128 // the encoder position to get the absolute position.
129 double left_elevator_offset_ = 0.0;
130 double right_elevator_offset_ = 0.0;
131 double left_arm_offset_ = 0.0;
132 double right_arm_offset_ = 0.0;
133
134 // Current velocity to move at while zeroing.
135 double elevator_zeroing_velocity_ = 0.0;
136 double arm_zeroing_velocity_ = 0.0;
137
138 // The goals for the elevator and arm.
139 double elevator_goal_ = 0.0;
140 double arm_goal_ = 0.0;
141
142 State state_ = UNINITIALIZED;
143 State last_state_ = UNINITIALIZED;
144
145 control_loops::FridgeQueue::Position current_position_;
Philipp Schrader3e281412015-03-01 23:48:23 +0000146
147 aos::util::TrapezoidProfile arm_profile_;
148 aos::util::TrapezoidProfile elevator_profile_;
Ben Fredrickson6b5ba792015-01-25 17:14:40 -0800149};
150
151} // namespace control_loops
152} // namespace frc971
153
154#endif // FRC971_CONTROL_LOOPS_FRIDGE_H_
155