blob: 95f04f8a3013ba8d3959eb426d8629f2a99c4926 [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
6#include "aos/common/controls/control_loop.h"
Austin Schuh10c2d112016-02-14 13:42:28 -08007#include "aos/common/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"
Austin Schuh473a5652017-02-05 01:30:42 -080014#include "y2016/control_loops/superstructure/superstructure.q.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 Schuhc5fceb82017-02-25 16:24:12 -080031 controller(0).Kff * (next_R() - plant().coefficients(0).A * R());
Austin Schuhf59b6bc2016-03-11 21:26:19 -080032 const Eigen::Matrix<double, 2, 1> accelerating_controller =
33 controller(0).K * error() + accelerating_ff;
34
35 const Eigen::Matrix<double, 2, 1> decelerating_ff =
Austin Schuhc5fceb82017-02-25 16:24:12 -080036 controller(1).Kff * (next_R() - plant().coefficients(1).A * R());
Austin Schuhf59b6bc2016-03-11 21:26:19 -080037 const Eigen::Matrix<double, 2, 1> decelerating_controller =
38 controller(1).K * error() + decelerating_ff;
39
40 const double bemf_voltage = X_hat(1, 0) / kV_shoulder;
41 bool use_accelerating_controller = true;
42 LOG(DEBUG, "Accelerating at %f, decel %f, bemf %f\n",
43 accelerating_controller(0, 0), accelerating_controller(1, 0),
44 bemf_voltage);
45 if (IsAccelerating(bemf_voltage, accelerating_controller(0, 0))) {
46 use_accelerating_controller = true;
47 } else {
48 use_accelerating_controller = false;
49 }
50 if (use_accelerating_controller) {
Austin Schuhc5fceb82017-02-25 16:24:12 -080051 set_index(0);
Austin Schuhf59b6bc2016-03-11 21:26:19 -080052 ff_U_ = accelerating_ff;
Austin Schuhf59b6bc2016-03-11 21:26:19 -080053 return accelerating_controller;
54 } else {
Austin Schuhc5fceb82017-02-25 16:24:12 -080055 set_index(1);
Austin Schuhf59b6bc2016-03-11 21:26:19 -080056 ff_U_ = decelerating_ff;
57 return decelerating_controller;
58 }
59 }
60
61 private:
Austin Schuhd7e29942016-03-12 21:35:11 -080062 void CapU() override {
63 // U(0)
64 // U(1) = coupling * U(0) + ...
65 // So, when modifying U(0), remove the coupling.
66 if (U(0, 0) > max_voltage(0)) {
67 const double overage_amount = U(0, 0) - max_voltage(0);
68 mutable_U(0, 0) = max_voltage(0);
69 const double coupled_amount =
Austin Schuhc5fceb82017-02-25 16:24:12 -080070 (Kff().block<1, 2>(1, 2) * plant().B().block<2, 1>(2, 0))(0, 0) *
Austin Schuh473a5652017-02-05 01:30:42 -080071 overage_amount;
Austin Schuhd7e29942016-03-12 21:35:11 -080072 LOG(DEBUG, "Removing coupled amount %f\n", coupled_amount);
73 mutable_U(1, 0) += coupled_amount;
74 }
75 if (U(0, 0) < min_voltage(0)) {
76 const double under_amount = U(0, 0) - min_voltage(0);
77 mutable_U(0, 0) = min_voltage(0);
78 const double coupled_amount =
Austin Schuhc5fceb82017-02-25 16:24:12 -080079 (Kff().block<1, 2>(1, 2) * plant().B().block<2, 1>(2, 0))(0, 0) *
Austin Schuhd7e29942016-03-12 21:35:11 -080080 under_amount;
81 LOG(DEBUG, "Removing coupled amount %f\n", coupled_amount);
82 mutable_U(1, 0) += coupled_amount;
83 }
84
85 // Uncapping U above isn't actually a problem with U for the shoulder.
86 // Reset any change.
87 mutable_U_uncapped(1, 0) = U(1, 0);
88 mutable_U(1, 0) =
89 ::std::min(max_voltage(1), ::std::max(min_voltage(1), U(1, 0)));
90 }
91
Austin Schuhf59b6bc2016-03-11 21:26:19 -080092 bool IsAccelerating(double bemf_voltage, double voltage) {
93 if (bemf_voltage > 0) {
94 return voltage > bemf_voltage;
95 } else {
96 return voltage < bemf_voltage;
97 }
98 }
99};
Diana Vandenberge2843c62016-02-13 17:44:20 -0800100
Brian Silvermanab0b6772017-02-05 16:16:21 -0800101class Intake : public ::frc971::control_loops::SingleDOFProfiledSubsystem<> {
Austin Schuhcb60e292017-01-01 16:07:31 -0800102 public:
103 Intake();
Austin Schuhcb60e292017-01-01 16:07:31 -0800104};
105
Austin Schuh473a5652017-02-05 01:30:42 -0800106
107class 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.
112 void Correct(::frc971::PotAndIndexPosition position_shoulder,
113 ::frc971::PotAndIndexPosition position_wrist);
114
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_