blob: a827c006391c2f2bd1890b85e7a5b3114565268e [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/util/trapezoid_profile.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07007#include "frc971/control_loops/control_loop.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#include "frc971/zeroing/zeroing.h"
Austin Schuhf59b6bc2016-03-11 21:26:19 -080012#include "y2016/control_loops/superstructure/integral_arm_plant.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070013#include "y2016/control_loops/superstructure/superstructure_position_generated.h"
Austin Schuh10c2d112016-02-14 13:42:28 -080014
15namespace y2016 {
16namespace control_loops {
17namespace superstructure {
18namespace testing {
19class SuperstructureTest_DisabledGoalTest_Test;
20} // namespace testing
21
Austin Schuhf59b6bc2016-03-11 21:26:19 -080022class ArmControlLoop
23 : public ::frc971::control_loops::SimpleCappedStateFeedbackLoop<6, 2, 2> {
24 public:
25 ArmControlLoop(SimpleCappedStateFeedbackLoop<6, 2, 2> &&loop)
26 : SimpleCappedStateFeedbackLoop<6, 2, 2>(::std::move(loop)) {}
27
28 const Eigen::Matrix<double, 2, 1> ControllerOutput() override {
29 const Eigen::Matrix<double, 2, 1> accelerating_ff =
Austin Schuh32501832017-02-25 18:32:56 -080030 controller().coefficients(0).Kff *
31 (next_R() - plant().coefficients(0).A * R());
Austin Schuhf59b6bc2016-03-11 21:26:19 -080032 const Eigen::Matrix<double, 2, 1> accelerating_controller =
Austin Schuh32501832017-02-25 18:32:56 -080033 controller().coefficients(0).K * error() + accelerating_ff;
Austin Schuhf59b6bc2016-03-11 21:26:19 -080034
35 const Eigen::Matrix<double, 2, 1> decelerating_ff =
Austin Schuh32501832017-02-25 18:32:56 -080036 controller().coefficients(1).Kff *
37 (next_R() - plant().coefficients(1).A * R());
Austin Schuhf59b6bc2016-03-11 21:26:19 -080038 const Eigen::Matrix<double, 2, 1> decelerating_controller =
Austin Schuh32501832017-02-25 18:32:56 -080039 controller().coefficients(1).K * error() + decelerating_ff;
Austin Schuhf59b6bc2016-03-11 21:26:19 -080040
41 const double bemf_voltage = X_hat(1, 0) / kV_shoulder;
42 bool use_accelerating_controller = true;
Austin Schuhf257f3c2019-10-27 21:00:43 -070043 AOS_LOG(DEBUG, "Accelerating at %f, decel %f, bemf %f\n",
44 accelerating_controller(0, 0), accelerating_controller(1, 0),
45 bemf_voltage);
Austin Schuhf59b6bc2016-03-11 21:26:19 -080046 if (IsAccelerating(bemf_voltage, accelerating_controller(0, 0))) {
47 use_accelerating_controller = true;
48 } else {
49 use_accelerating_controller = false;
50 }
51 if (use_accelerating_controller) {
Austin Schuhc5fceb82017-02-25 16:24:12 -080052 set_index(0);
Austin Schuhf59b6bc2016-03-11 21:26:19 -080053 ff_U_ = accelerating_ff;
Austin Schuhf59b6bc2016-03-11 21:26:19 -080054 return accelerating_controller;
55 } else {
Austin Schuhc5fceb82017-02-25 16:24:12 -080056 set_index(1);
Austin Schuhf59b6bc2016-03-11 21:26:19 -080057 ff_U_ = decelerating_ff;
58 return decelerating_controller;
59 }
60 }
61
62 private:
Austin Schuhd7e29942016-03-12 21:35:11 -080063 void CapU() override {
64 // U(0)
65 // U(1) = coupling * U(0) + ...
66 // So, when modifying U(0), remove the coupling.
67 if (U(0, 0) > max_voltage(0)) {
68 const double overage_amount = U(0, 0) - max_voltage(0);
69 mutable_U(0, 0) = max_voltage(0);
Austin Schuh32501832017-02-25 18:32:56 -080070 const double coupled_amount = (controller().Kff().block<1, 2>(1, 2) *
71 plant().B().block<2, 1>(2, 0))(0, 0) *
72 overage_amount;
Austin Schuhf257f3c2019-10-27 21:00:43 -070073 AOS_LOG(DEBUG, "Removing coupled amount %f\n", coupled_amount);
Austin Schuhd7e29942016-03-12 21:35:11 -080074 mutable_U(1, 0) += coupled_amount;
75 }
76 if (U(0, 0) < min_voltage(0)) {
77 const double under_amount = U(0, 0) - min_voltage(0);
78 mutable_U(0, 0) = min_voltage(0);
Austin Schuh32501832017-02-25 18:32:56 -080079 const double coupled_amount = (controller().Kff().block<1, 2>(1, 2) *
80 plant().B().block<2, 1>(2, 0))(0, 0) *
81 under_amount;
Austin Schuhf257f3c2019-10-27 21:00:43 -070082 AOS_LOG(DEBUG, "Removing coupled amount %f\n", coupled_amount);
Austin Schuhd7e29942016-03-12 21:35:11 -080083 mutable_U(1, 0) += coupled_amount;
84 }
85
86 // Uncapping U above isn't actually a problem with U for the shoulder.
87 // Reset any change.
88 mutable_U_uncapped(1, 0) = U(1, 0);
89 mutable_U(1, 0) =
90 ::std::min(max_voltage(1), ::std::max(min_voltage(1), U(1, 0)));
91 }
92
Austin Schuhf59b6bc2016-03-11 21:26:19 -080093 bool IsAccelerating(double bemf_voltage, double voltage) {
94 if (bemf_voltage > 0) {
95 return voltage > bemf_voltage;
96 } else {
97 return voltage < bemf_voltage;
98 }
99 }
100};
Diana Vandenberge2843c62016-02-13 17:44:20 -0800101
Brian Silvermanab0b6772017-02-05 16:16:21 -0800102class Intake : public ::frc971::control_loops::SingleDOFProfiledSubsystem<> {
Austin Schuhcb60e292017-01-01 16:07:31 -0800103 public:
104 Intake();
Austin Schuhcb60e292017-01-01 16:07:31 -0800105};
106
Austin Schuh473a5652017-02-05 01:30:42 -0800107class Arm : public ::frc971::control_loops::ProfiledSubsystem<6, 2> {
Austin Schuhcb60e292017-01-01 16:07:31 -0800108 public:
109 Arm();
Austin Schuh10c2d112016-02-14 13:42:28 -0800110
111 // Updates our estimator with the latest position.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700112 void Correct(const ::frc971::PotAndIndexPosition *position_shoulder,
113 const ::frc971::PotAndIndexPosition *position_wrist);
Austin Schuh10c2d112016-02-14 13:42:28 -0800114
115 // Forces the goal to be the provided goal.
116 void ForceGoal(double unprofiled_goal_shoulder, double unprofiled_goal_wrist);
117 // Sets the unprofiled goal. The profiler will generate a profile to go to
118 // this goal.
119 void set_unprofiled_goal(double unprofiled_goal_shoulder,
120 double unprofiled_goal_wrist);
121
122 // Runs the controller and profile generator for a cycle.
123 void Update(bool disabled);
124
125 // Limits our profiles to a max velocity and acceleration for proper motion.
126 void AdjustProfile(double max_angular_velocity_shoulder,
127 double max_angular_acceleration_shoulder,
128 double max_angular_velocity_wrist,
129 double max_angular_acceleration_wrist);
Austin Schuh10c2d112016-02-14 13:42:28 -0800130
Austin Schuh9f4e8a72016-02-16 15:28:47 -0800131 void set_shoulder_asymetric_limits(double shoulder_min_voltage,
132 double shoulder_max_voltage) {
133 loop_->set_asymetric_voltage(0, shoulder_min_voltage, shoulder_max_voltage);
134 }
135
Austin Schuh10c2d112016-02-14 13:42:28 -0800136 // Returns true if we have exceeded any hard limits.
137 bool CheckHardLimits();
Austin Schuh10c2d112016-02-14 13:42:28 -0800138
Austin Schuh10c2d112016-02-14 13:42:28 -0800139 // Returns the requested shoulder and wrist voltages.
140 double shoulder_voltage() const { return loop_->U(0, 0); }
141 double wrist_voltage() const { return loop_->U(1, 0); }
142
143 // Returns the current positions.
144 double shoulder_angle() const { return Y_(0, 0); }
145 double wrist_angle() const { return Y_(1, 0) + Y_(0, 0); }
146
Diana Vandenberge2843c62016-02-13 17:44:20 -0800147 // For testing:
148 // Triggers an estimator error.
Austin Schuh473a5652017-02-05 01:30:42 -0800149 void TriggerEstimatorError() { estimators_[0].TriggerError(); }
Diana Vandenberge2843c62016-02-13 17:44:20 -0800150
Austin Schuh10c2d112016-02-14 13:42:28 -0800151 private:
152 // Limits the provided goal to the soft limits. Prints "name" when it fails
153 // to aid debugging.
154 void CapGoal(const char *name, Eigen::Matrix<double, 6, 1> *goal);
155
156 // Updates the offset
157 void UpdateWristOffset(double offset);
158 void UpdateShoulderOffset(double offset);
159
160 friend class testing::SuperstructureTest_DisabledGoalTest_Test;
Austin Schuh10c2d112016-02-14 13:42:28 -0800161
162 aos::util::TrapezoidProfile shoulder_profile_, wrist_profile_;
Austin Schuh10c2d112016-02-14 13:42:28 -0800163
164 // Current measurement.
165 Eigen::Matrix<double, 2, 1> Y_;
166 // Current offset. Y_ = offset_ + raw_sensor;
167 Eigen::Matrix<double, 2, 1> offset_;
Austin Schuh10c2d112016-02-14 13:42:28 -0800168};
169
170} // namespace superstructure
171} // namespace control_loops
172} // namespace y2016
173
174#endif // Y2016_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_CONTROLS_H_