blob: d30105488f62cf7c6e02369ece6e52f2086f5a6b [file] [log] [blame]
Austin Schuh10c2d112016-02-14 13:42:28 -08001#ifndef Y2016_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_CONTROLS_H_
2#define Y2016_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_CONTROLS_H_
3
4#include <memory>
5
John Park33858a32018-09-28 23:05:48 -07006#include "aos/controls/control_loop.h"
7#include "aos/util/trapezoid_profile.h"
Austin Schuh473a5652017-02-05 01:30:42 -08008#include "frc971/control_loops/profiled_subsystem.h"
9#include "frc971/control_loops/simple_capped_state_feedback_loop.h"
10#include "frc971/control_loops/state_feedback_loop.h"
Austin Schuh10c2d112016-02-14 13:42:28 -080011
12#include "frc971/zeroing/zeroing.h"
Austin Schuhf59b6bc2016-03-11 21:26:19 -080013#include "y2016/control_loops/superstructure/integral_arm_plant.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070014#include "y2016/control_loops/superstructure/superstructure_position_generated.h"
Austin Schuh10c2d112016-02-14 13:42:28 -080015
16namespace y2016 {
17namespace control_loops {
18namespace superstructure {
19namespace testing {
20class SuperstructureTest_DisabledGoalTest_Test;
21} // namespace testing
22
Austin Schuhf59b6bc2016-03-11 21:26:19 -080023class ArmControlLoop
24 : public ::frc971::control_loops::SimpleCappedStateFeedbackLoop<6, 2, 2> {
25 public:
26 ArmControlLoop(SimpleCappedStateFeedbackLoop<6, 2, 2> &&loop)
27 : SimpleCappedStateFeedbackLoop<6, 2, 2>(::std::move(loop)) {}
28
29 const Eigen::Matrix<double, 2, 1> ControllerOutput() override {
30 const Eigen::Matrix<double, 2, 1> accelerating_ff =
Austin Schuh32501832017-02-25 18:32:56 -080031 controller().coefficients(0).Kff *
32 (next_R() - plant().coefficients(0).A * R());
Austin Schuhf59b6bc2016-03-11 21:26:19 -080033 const Eigen::Matrix<double, 2, 1> accelerating_controller =
Austin Schuh32501832017-02-25 18:32:56 -080034 controller().coefficients(0).K * error() + accelerating_ff;
Austin Schuhf59b6bc2016-03-11 21:26:19 -080035
36 const Eigen::Matrix<double, 2, 1> decelerating_ff =
Austin Schuh32501832017-02-25 18:32:56 -080037 controller().coefficients(1).Kff *
38 (next_R() - plant().coefficients(1).A * R());
Austin Schuhf59b6bc2016-03-11 21:26:19 -080039 const Eigen::Matrix<double, 2, 1> decelerating_controller =
Austin Schuh32501832017-02-25 18:32:56 -080040 controller().coefficients(1).K * error() + decelerating_ff;
Austin Schuhf59b6bc2016-03-11 21:26:19 -080041
42 const double bemf_voltage = X_hat(1, 0) / kV_shoulder;
43 bool use_accelerating_controller = true;
Austin Schuhf257f3c2019-10-27 21:00:43 -070044 AOS_LOG(DEBUG, "Accelerating at %f, decel %f, bemf %f\n",
45 accelerating_controller(0, 0), accelerating_controller(1, 0),
46 bemf_voltage);
Austin Schuhf59b6bc2016-03-11 21:26:19 -080047 if (IsAccelerating(bemf_voltage, accelerating_controller(0, 0))) {
48 use_accelerating_controller = true;
49 } else {
50 use_accelerating_controller = false;
51 }
52 if (use_accelerating_controller) {
Austin Schuhc5fceb82017-02-25 16:24:12 -080053 set_index(0);
Austin Schuhf59b6bc2016-03-11 21:26:19 -080054 ff_U_ = accelerating_ff;
Austin Schuhf59b6bc2016-03-11 21:26:19 -080055 return accelerating_controller;
56 } else {
Austin Schuhc5fceb82017-02-25 16:24:12 -080057 set_index(1);
Austin Schuhf59b6bc2016-03-11 21:26:19 -080058 ff_U_ = decelerating_ff;
59 return decelerating_controller;
60 }
61 }
62
63 private:
Austin Schuhd7e29942016-03-12 21:35:11 -080064 void CapU() override {
65 // U(0)
66 // U(1) = coupling * U(0) + ...
67 // So, when modifying U(0), remove the coupling.
68 if (U(0, 0) > max_voltage(0)) {
69 const double overage_amount = U(0, 0) - max_voltage(0);
70 mutable_U(0, 0) = max_voltage(0);
Austin Schuh32501832017-02-25 18:32:56 -080071 const double coupled_amount = (controller().Kff().block<1, 2>(1, 2) *
72 plant().B().block<2, 1>(2, 0))(0, 0) *
73 overage_amount;
Austin Schuhf257f3c2019-10-27 21:00:43 -070074 AOS_LOG(DEBUG, "Removing coupled amount %f\n", coupled_amount);
Austin Schuhd7e29942016-03-12 21:35:11 -080075 mutable_U(1, 0) += coupled_amount;
76 }
77 if (U(0, 0) < min_voltage(0)) {
78 const double under_amount = U(0, 0) - min_voltage(0);
79 mutable_U(0, 0) = min_voltage(0);
Austin Schuh32501832017-02-25 18:32:56 -080080 const double coupled_amount = (controller().Kff().block<1, 2>(1, 2) *
81 plant().B().block<2, 1>(2, 0))(0, 0) *
82 under_amount;
Austin Schuhf257f3c2019-10-27 21:00:43 -070083 AOS_LOG(DEBUG, "Removing coupled amount %f\n", coupled_amount);
Austin Schuhd7e29942016-03-12 21:35:11 -080084 mutable_U(1, 0) += coupled_amount;
85 }
86
87 // Uncapping U above isn't actually a problem with U for the shoulder.
88 // Reset any change.
89 mutable_U_uncapped(1, 0) = U(1, 0);
90 mutable_U(1, 0) =
91 ::std::min(max_voltage(1), ::std::max(min_voltage(1), U(1, 0)));
92 }
93
Austin Schuhf59b6bc2016-03-11 21:26:19 -080094 bool IsAccelerating(double bemf_voltage, double voltage) {
95 if (bemf_voltage > 0) {
96 return voltage > bemf_voltage;
97 } else {
98 return voltage < bemf_voltage;
99 }
100 }
101};
Diana Vandenberge2843c62016-02-13 17:44:20 -0800102
Brian Silvermanab0b6772017-02-05 16:16:21 -0800103class Intake : public ::frc971::control_loops::SingleDOFProfiledSubsystem<> {
Austin Schuhcb60e292017-01-01 16:07:31 -0800104 public:
105 Intake();
Austin Schuhcb60e292017-01-01 16:07:31 -0800106};
107
Austin Schuh473a5652017-02-05 01:30:42 -0800108
109class Arm : public ::frc971::control_loops::ProfiledSubsystem<6, 2> {
Austin Schuhcb60e292017-01-01 16:07:31 -0800110 public:
111 Arm();
Austin Schuh10c2d112016-02-14 13:42:28 -0800112
113 // Updates our estimator with the latest position.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700114 void Correct(const ::frc971::PotAndIndexPosition *position_shoulder,
115 const ::frc971::PotAndIndexPosition *position_wrist);
Austin Schuh10c2d112016-02-14 13:42:28 -0800116
117 // Forces the goal to be the provided goal.
118 void ForceGoal(double unprofiled_goal_shoulder, double unprofiled_goal_wrist);
119 // Sets the unprofiled goal. The profiler will generate a profile to go to
120 // this goal.
121 void set_unprofiled_goal(double unprofiled_goal_shoulder,
122 double unprofiled_goal_wrist);
123
124 // Runs the controller and profile generator for a cycle.
125 void Update(bool disabled);
126
127 // Limits our profiles to a max velocity and acceleration for proper motion.
128 void AdjustProfile(double max_angular_velocity_shoulder,
129 double max_angular_acceleration_shoulder,
130 double max_angular_velocity_wrist,
131 double max_angular_acceleration_wrist);
Austin Schuh10c2d112016-02-14 13:42:28 -0800132
Austin Schuh9f4e8a72016-02-16 15:28:47 -0800133 void set_shoulder_asymetric_limits(double shoulder_min_voltage,
134 double shoulder_max_voltage) {
135 loop_->set_asymetric_voltage(0, shoulder_min_voltage, shoulder_max_voltage);
136 }
137
Austin Schuh10c2d112016-02-14 13:42:28 -0800138 // Returns true if we have exceeded any hard limits.
139 bool CheckHardLimits();
Austin Schuh10c2d112016-02-14 13:42:28 -0800140
Austin Schuh10c2d112016-02-14 13:42:28 -0800141 // Returns the requested shoulder and wrist voltages.
142 double shoulder_voltage() const { return loop_->U(0, 0); }
143 double wrist_voltage() const { return loop_->U(1, 0); }
144
145 // Returns the current positions.
146 double shoulder_angle() const { return Y_(0, 0); }
147 double wrist_angle() const { return Y_(1, 0) + Y_(0, 0); }
148
Diana Vandenberge2843c62016-02-13 17:44:20 -0800149 // For testing:
150 // Triggers an estimator error.
Austin Schuh473a5652017-02-05 01:30:42 -0800151 void TriggerEstimatorError() { estimators_[0].TriggerError(); }
Diana Vandenberge2843c62016-02-13 17:44:20 -0800152
Austin Schuh10c2d112016-02-14 13:42:28 -0800153 private:
154 // Limits the provided goal to the soft limits. Prints "name" when it fails
155 // to aid debugging.
156 void CapGoal(const char *name, Eigen::Matrix<double, 6, 1> *goal);
157
158 // Updates the offset
159 void UpdateWristOffset(double offset);
160 void UpdateShoulderOffset(double offset);
161
162 friend class testing::SuperstructureTest_DisabledGoalTest_Test;
Austin Schuh10c2d112016-02-14 13:42:28 -0800163
164 aos::util::TrapezoidProfile shoulder_profile_, wrist_profile_;
Austin Schuh10c2d112016-02-14 13:42:28 -0800165
166 // Current measurement.
167 Eigen::Matrix<double, 2, 1> Y_;
168 // Current offset. Y_ = offset_ + raw_sensor;
169 Eigen::Matrix<double, 2, 1> offset_;
Austin Schuh10c2d112016-02-14 13:42:28 -0800170};
171
172} // namespace superstructure
173} // namespace control_loops
174} // namespace y2016
175
176#endif // Y2016_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_CONTROLS_H_