blob: bcf00d6743c12449d7d97962be89360aab8db2b6 [file] [log] [blame]
Brian Silverman273d8a32014-05-10 22:19:09 -07001#ifndef FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_H_
2#define FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_H_
Austin Schuhdc1c84a2013-02-23 16:33:10 -08003
Austin Schuh849f0032013-03-03 23:59:53 -08004#include <assert.h>
Austin Schuhdc1c84a2013-02-23 16:33:10 -08005
Brian Silvermanc571e052013-03-13 17:58:56 -07006#include <vector>
Austin Schuh1a387962015-01-31 16:36:20 -08007#include <memory>
Austin Schuhcda86af2014-02-16 16:16:39 -08008#include <iostream>
Brian Silvermanc571e052013-03-13 17:58:56 -07009
Austin Schuhdc1c84a2013-02-23 16:33:10 -080010#include "Eigen/Dense"
11
Austin Schuhcda86af2014-02-16 16:16:39 -080012#include "aos/common/logging/logging.h"
Brian Silverman0a151c92014-05-02 15:28:44 -070013#include "aos/common/macros.h"
14
Brian Silverman5808bcb2014-09-14 21:40:43 -040015// For everything in this file, "inputs" and "outputs" are defined from the
16// perspective of the plant. This means U is an input and Y is an output
17// (because you give the plant U (powers) and it gives you back a Y (sensor
18// values). This is the opposite of what they mean from the perspective of the
19// controller (U is an output because that's what goes to the motors and Y is an
20// input because that's what comes back from the sensors).
21
Austin Schuhdc1c84a2013-02-23 16:33:10 -080022template <int number_of_states, int number_of_inputs, int number_of_outputs>
Austin Schuh64f17a52017-02-25 14:41:58 -080023struct StateFeedbackPlantCoefficients final {
Austin Schuhdc1c84a2013-02-23 16:33:10 -080024 public:
25 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
26
Austin Schuhe3490622013-03-13 01:24:30 -070027 StateFeedbackPlantCoefficients(const StateFeedbackPlantCoefficients &other)
Austin Schuh64f17a52017-02-25 14:41:58 -080028 : A(other.A),
29 A_continuous(other.A_continuous),
30 B(other.B),
31 B_continuous(other.B_continuous),
32 C(other.C),
33 D(other.D),
34 U_min(other.U_min),
35 U_max(other.U_max) {}
Austin Schuhdc1c84a2013-02-23 16:33:10 -080036
Austin Schuhe3490622013-03-13 01:24:30 -070037 StateFeedbackPlantCoefficients(
Austin Schuhdc1c84a2013-02-23 16:33:10 -080038 const Eigen::Matrix<double, number_of_states, number_of_states> &A,
Austin Schuh6c20f202017-02-18 22:31:44 -080039 const Eigen::Matrix<double, number_of_states, number_of_states>
40 &A_continuous,
Austin Schuhdc1c84a2013-02-23 16:33:10 -080041 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B,
Austin Schuh6c20f202017-02-18 22:31:44 -080042 const Eigen::Matrix<double, number_of_states, number_of_inputs>
43 &B_continuous,
Austin Schuhdc1c84a2013-02-23 16:33:10 -080044 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C,
45 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D,
Brian Silverman5808bcb2014-09-14 21:40:43 -040046 const Eigen::Matrix<double, number_of_inputs, 1> &U_max,
47 const Eigen::Matrix<double, number_of_inputs, 1> &U_min)
Austin Schuh64f17a52017-02-25 14:41:58 -080048 : A(A),
49 A_continuous(A_continuous),
50 B(B),
51 B_continuous(B_continuous),
52 C(C),
53 D(D),
54 U_min(U_min),
55 U_max(U_max) {}
Austin Schuhe3490622013-03-13 01:24:30 -070056
Austin Schuh64f17a52017-02-25 14:41:58 -080057 const Eigen::Matrix<double, number_of_states, number_of_states> A;
58 const Eigen::Matrix<double, number_of_states, number_of_states> A_continuous;
59 const Eigen::Matrix<double, number_of_states, number_of_inputs> B;
60 const Eigen::Matrix<double, number_of_states, number_of_inputs> B_continuous;
61 const Eigen::Matrix<double, number_of_outputs, number_of_states> C;
62 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> D;
63 const Eigen::Matrix<double, number_of_inputs, 1> U_min;
64 const Eigen::Matrix<double, number_of_inputs, 1> U_max;
Austin Schuhe3490622013-03-13 01:24:30 -070065};
66
67template <int number_of_states, int number_of_inputs, int number_of_outputs>
68class StateFeedbackPlant {
69 public:
70 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
Brian Silverman0a151c92014-05-02 15:28:44 -070071
72 StateFeedbackPlant(
Austin Schuhb6a6d822016-02-08 00:20:40 -080073 ::std::vector<::std::unique_ptr<StateFeedbackPlantCoefficients<
Austin Schuh66c19882017-02-25 13:36:28 -080074 number_of_states, number_of_inputs, number_of_outputs>>>
75 *coefficients)
Austin Schuh1a387962015-01-31 16:36:20 -080076 : coefficients_(::std::move(*coefficients)), plant_index_(0) {
Brian Silverman0a151c92014-05-02 15:28:44 -070077 Reset();
78 }
79
80 StateFeedbackPlant(StateFeedbackPlant &&other)
81 : plant_index_(other.plant_index_) {
82 ::std::swap(coefficients_, other.coefficients_);
Brian Silverman273d8a32014-05-10 22:19:09 -070083 X_.swap(other.X_);
84 Y_.swap(other.Y_);
Brian Silverman0a151c92014-05-02 15:28:44 -070085 }
86
Austin Schuh1a387962015-01-31 16:36:20 -080087 virtual ~StateFeedbackPlant() {}
Brian Silverman0a151c92014-05-02 15:28:44 -070088
Austin Schuhe3490622013-03-13 01:24:30 -070089 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
Austin Schuh64f17a52017-02-25 14:41:58 -080090 return coefficients().A;
Austin Schuhe3490622013-03-13 01:24:30 -070091 }
92 double A(int i, int j) const { return A()(i, j); }
93 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
Austin Schuh64f17a52017-02-25 14:41:58 -080094 return coefficients().B;
Austin Schuhe3490622013-03-13 01:24:30 -070095 }
96 double B(int i, int j) const { return B()(i, j); }
97 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
Austin Schuh64f17a52017-02-25 14:41:58 -080098 return coefficients().C;
Austin Schuhe3490622013-03-13 01:24:30 -070099 }
100 double C(int i, int j) const { return C()(i, j); }
101 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
Austin Schuh64f17a52017-02-25 14:41:58 -0800102 return coefficients().D;
Austin Schuhe3490622013-03-13 01:24:30 -0700103 }
104 double D(int i, int j) const { return D()(i, j); }
105 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
Austin Schuh64f17a52017-02-25 14:41:58 -0800106 return coefficients().U_min;
Austin Schuhe3490622013-03-13 01:24:30 -0700107 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700108 double U_min(int i, int j) const { return U_min()(i, j); }
Austin Schuhe3490622013-03-13 01:24:30 -0700109 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
Austin Schuh64f17a52017-02-25 14:41:58 -0800110 return coefficients().U_max;
Austin Schuhe3490622013-03-13 01:24:30 -0700111 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700112 double U_max(int i, int j) const { return U_max()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700113
114 const Eigen::Matrix<double, number_of_states, 1> &X() const { return X_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700115 double X(int i, int j) const { return X()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700116 const Eigen::Matrix<double, number_of_outputs, 1> &Y() const { return Y_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700117 double Y(int i, int j) const { return Y()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700118
Brian Silverman0ca790b2014-06-12 21:33:08 -0700119 Eigen::Matrix<double, number_of_states, 1> &mutable_X() { return X_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700120 double &mutable_X(int i, int j) { return mutable_X()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700121 Eigen::Matrix<double, number_of_outputs, 1> &mutable_Y() { return Y_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700122 double &mutable_Y(int i, int j) { return mutable_Y()(i, j); }
Austin Schuhe3490622013-03-13 01:24:30 -0700123
Austin Schuhb6a6d822016-02-08 00:20:40 -0800124 const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
125 number_of_outputs> &
126 coefficients() const {
Austin Schuhe3490622013-03-13 01:24:30 -0700127 return *coefficients_[plant_index_];
128 }
129
130 int plant_index() const { return plant_index_; }
131 void set_plant_index(int plant_index) {
Austin Schuh6ca0f792016-03-12 14:06:14 -0800132 assert(plant_index >= 0);
133 assert(plant_index < static_cast<int>(coefficients_.size()));
134 plant_index_ = plant_index;
Austin Schuhe3490622013-03-13 01:24:30 -0700135 }
136
137 void Reset() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700138 X_.setZero();
139 Y_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800140 }
141
Austin Schuh849f0032013-03-03 23:59:53 -0800142 // Assert that U is within the hardware range.
Austin Schuh66c19882017-02-25 13:36:28 -0800143 virtual void CheckU(const Eigen::Matrix<double, number_of_inputs, 1> &U) {
Brian Silverman5808bcb2014-09-14 21:40:43 -0400144 for (int i = 0; i < kNumInputs; ++i) {
Austin Schuh66c19882017-02-25 13:36:28 -0800145 if (U(i, 0) > U_max(i, 0) + 0.00001 || U(i, 0) < U_min(i, 0) - 0.00001) {
146 LOG(FATAL, "U out of range\n");
147 }
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800148 }
149 }
Austin Schuh849f0032013-03-03 23:59:53 -0800150
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800151 // Computes the new X and Y given the control input.
Austin Schuh66c19882017-02-25 13:36:28 -0800152 void Update(const Eigen::Matrix<double, number_of_inputs, 1> &U) {
Austin Schuh849f0032013-03-03 23:59:53 -0800153 // Powers outside of the range are more likely controller bugs than things
154 // that the plant should deal with.
Austin Schuh66c19882017-02-25 13:36:28 -0800155 CheckU(U);
156 X_ = A() * X() + B() * U;
157 Y_ = C() * X() + D() * U;
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800158 }
159
160 protected:
161 // these are accessible from non-templated subclasses
Austin Schuhb1cdb382013-03-01 22:53:52 -0800162 static const int kNumStates = number_of_states;
163 static const int kNumOutputs = number_of_outputs;
164 static const int kNumInputs = number_of_inputs;
Austin Schuhe3490622013-03-13 01:24:30 -0700165
166 private:
Brian Silverman273d8a32014-05-10 22:19:09 -0700167 Eigen::Matrix<double, number_of_states, 1> X_;
168 Eigen::Matrix<double, number_of_outputs, 1> Y_;
Brian Silverman273d8a32014-05-10 22:19:09 -0700169
Austin Schuhb6a6d822016-02-08 00:20:40 -0800170 ::std::vector<::std::unique_ptr<StateFeedbackPlantCoefficients<
Austin Schuh64f17a52017-02-25 14:41:58 -0800171 number_of_states, number_of_inputs, number_of_outputs>>>
172 coefficients_;
Brian Silverman273d8a32014-05-10 22:19:09 -0700173
Austin Schuhe3490622013-03-13 01:24:30 -0700174 int plant_index_;
Brian Silverman0a151c92014-05-02 15:28:44 -0700175
176 DISALLOW_COPY_AND_ASSIGN(StateFeedbackPlant);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800177};
178
Austin Schuh9644e1c2013-03-12 00:40:36 -0700179// A Controller is a structure which holds a plant and the K and L matrices.
180// This is designed such that multiple controllers can share one set of state to
181// support gain scheduling easily.
182template <int number_of_states, int number_of_inputs, int number_of_outputs>
Austin Schuh66c19882017-02-25 13:36:28 -0800183struct StateFeedbackControllerConstants final {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700184 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
Brian Silverman273d8a32014-05-10 22:19:09 -0700185
Austin Schuh9644e1c2013-03-12 00:40:36 -0700186 const Eigen::Matrix<double, number_of_states, number_of_outputs> L;
Brian Silverman5808bcb2014-09-14 21:40:43 -0400187 const Eigen::Matrix<double, number_of_inputs, number_of_states> K;
Austin Schuh86093ad2016-02-06 14:29:34 -0800188 const Eigen::Matrix<double, number_of_inputs, number_of_states> Kff;
Austin Schuh1a387962015-01-31 16:36:20 -0800189 const Eigen::Matrix<double, number_of_states, number_of_states> A_inv;
Austin Schuhe3490622013-03-13 01:24:30 -0700190 StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
Austin Schuh66c19882017-02-25 13:36:28 -0800191 number_of_outputs>
192 plant;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700193
Austin Schuh66c19882017-02-25 13:36:28 -0800194 StateFeedbackControllerConstants(
Austin Schuh9644e1c2013-03-12 00:40:36 -0700195 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L,
Brian Silverman5808bcb2014-09-14 21:40:43 -0400196 const Eigen::Matrix<double, number_of_inputs, number_of_states> &K,
Austin Schuh86093ad2016-02-06 14:29:34 -0800197 const Eigen::Matrix<double, number_of_inputs, number_of_states> &Kff,
Austin Schuh1a387962015-01-31 16:36:20 -0800198 const Eigen::Matrix<double, number_of_states, number_of_states> &A_inv,
Austin Schuhe3490622013-03-13 01:24:30 -0700199 const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
200 number_of_outputs> &plant)
Austin Schuhb6a6d822016-02-08 00:20:40 -0800201 : L(L), K(K), Kff(Kff), A_inv(A_inv), plant(plant) {}
Austin Schuh9644e1c2013-03-12 00:40:36 -0700202};
203
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800204template <int number_of_states, int number_of_inputs, int number_of_outputs>
205class StateFeedbackLoop {
206 public:
207 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
208
Austin Schuh66c19882017-02-25 13:36:28 -0800209 StateFeedbackLoop(
210 const StateFeedbackControllerConstants<number_of_states, number_of_inputs,
211 number_of_outputs> &controller)
Brian Silverman0a151c92014-05-02 15:28:44 -0700212 : controller_index_(0) {
Austin Schuhb6a6d822016-02-08 00:20:40 -0800213 controllers_.emplace_back(
Austin Schuh66c19882017-02-25 13:36:28 -0800214 new StateFeedbackControllerConstants<number_of_states, number_of_inputs,
215 number_of_outputs>(controller));
Brian Silverman0a151c92014-05-02 15:28:44 -0700216 Reset();
217 }
218
Austin Schuh66c19882017-02-25 13:36:28 -0800219 StateFeedbackLoop(
220 ::std::vector<::std::unique_ptr<StateFeedbackControllerConstants<
221 number_of_states, number_of_inputs, number_of_outputs>>> *controllers)
Austin Schuh1a387962015-01-31 16:36:20 -0800222 : controllers_(::std::move(*controllers)), controller_index_(0) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700223 Reset();
224 }
225
226 StateFeedbackLoop(StateFeedbackLoop &&other) {
227 X_hat_.swap(other.X_hat_);
228 R_.swap(other.R_);
Austin Schuhb6a6d822016-02-08 00:20:40 -0800229 next_R_.swap(other.next_R_);
Brian Silverman273d8a32014-05-10 22:19:09 -0700230 U_.swap(other.U_);
231 U_uncapped_.swap(other.U_uncapped_);
Austin Schuhb6a6d822016-02-08 00:20:40 -0800232 ff_U_.swap(other.ff_U_);
Brian Silverman273d8a32014-05-10 22:19:09 -0700233 ::std::swap(controllers_, other.controllers_);
Brian Silverman273d8a32014-05-10 22:19:09 -0700234 controller_index_ = other.controller_index_;
235 }
236
Austin Schuh1a387962015-01-31 16:36:20 -0800237 virtual ~StateFeedbackLoop() {}
Brian Silverman0a151c92014-05-02 15:28:44 -0700238
Austin Schuh9644e1c2013-03-12 00:40:36 -0700239 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
Austin Schuh64f17a52017-02-25 14:41:58 -0800240 return controller().plant.A;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700241 }
242 double A(int i, int j) const { return A()(i, j); }
243 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
Austin Schuh64f17a52017-02-25 14:41:58 -0800244 return controller().plant.B;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700245 }
Austin Schuhb6a6d822016-02-08 00:20:40 -0800246 const Eigen::Matrix<double, number_of_states, number_of_states> &A_inv()
247 const {
Austin Schuh703b8d42015-02-01 14:56:34 -0800248 return controller().A_inv;
249 }
250 double A_inv(int i, int j) const { return A_inv()(i, j); }
Austin Schuh9644e1c2013-03-12 00:40:36 -0700251 double B(int i, int j) const { return B()(i, j); }
252 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
Austin Schuh64f17a52017-02-25 14:41:58 -0800253 return controller().plant.C;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700254 }
255 double C(int i, int j) const { return C()(i, j); }
256 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
Austin Schuh64f17a52017-02-25 14:41:58 -0800257 return controller().plant.D;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700258 }
259 double D(int i, int j) const { return D()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700260 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
Austin Schuh64f17a52017-02-25 14:41:58 -0800261 return controller().plant.U_min;
Brian Silverman273d8a32014-05-10 22:19:09 -0700262 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700263 double U_min(int i, int j) const { return U_min()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700264 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
Austin Schuh64f17a52017-02-25 14:41:58 -0800265 return controller().plant.U_max;
Brian Silverman273d8a32014-05-10 22:19:09 -0700266 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700267 double U_max(int i, int j) const { return U_max()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700268
Brian Silverman5808bcb2014-09-14 21:40:43 -0400269 const Eigen::Matrix<double, number_of_inputs, number_of_states> &K() const {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700270 return controller().K;
271 }
272 double K(int i, int j) const { return K()(i, j); }
Austin Schuh86093ad2016-02-06 14:29:34 -0800273 const Eigen::Matrix<double, number_of_inputs, number_of_states> &Kff() const {
274 return controller().Kff;
275 }
276 double Kff(int i, int j) const { return Kff()(i, j); }
Austin Schuh9644e1c2013-03-12 00:40:36 -0700277 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L() const {
278 return controller().L;
279 }
280 double L(int i, int j) const { return L()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700281
282 const Eigen::Matrix<double, number_of_states, 1> &X_hat() const {
283 return X_hat_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700284 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700285 double X_hat(int i, int j) const { return X_hat()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700286 const Eigen::Matrix<double, number_of_states, 1> &R() const { return R_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700287 double R(int i, int j) const { return R()(i, j); }
Austin Schuhb6a6d822016-02-08 00:20:40 -0800288 const Eigen::Matrix<double, number_of_states, 1> &next_R() const {
289 return next_R_;
290 }
291 double next_R(int i, int j) const { return next_R()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700292 const Eigen::Matrix<double, number_of_inputs, 1> &U() const { return U_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700293 double U(int i, int j) const { return U()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700294 const Eigen::Matrix<double, number_of_inputs, 1> &U_uncapped() const {
295 return U_uncapped_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700296 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700297 double U_uncapped(int i, int j) const { return U_uncapped()(i, j); }
Austin Schuhb6a6d822016-02-08 00:20:40 -0800298 const Eigen::Matrix<double, number_of_inputs, 1> &ff_U() const {
299 return ff_U_;
300 }
301 double ff_U(int i, int j) const { return ff_U()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700302
Brian Silverman0ca790b2014-06-12 21:33:08 -0700303 Eigen::Matrix<double, number_of_states, 1> &mutable_X_hat() { return X_hat_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700304 double &mutable_X_hat(int i, int j) { return mutable_X_hat()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700305 Eigen::Matrix<double, number_of_states, 1> &mutable_R() { return R_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700306 double &mutable_R(int i, int j) { return mutable_R()(i, j); }
Austin Schuhb6a6d822016-02-08 00:20:40 -0800307 Eigen::Matrix<double, number_of_states, 1> &mutable_next_R() {
308 return next_R_;
309 }
310 double &mutable_next_R(int i, int j) { return mutable_next_R()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700311 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U() { return U_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700312 double &mutable_U(int i, int j) { return mutable_U()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700313 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U_uncapped() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700314 return U_uncapped_;
315 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700316 double &mutable_U_uncapped(int i, int j) {
317 return mutable_U_uncapped()(i, j);
318 }
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800319
Austin Schuh66c19882017-02-25 13:36:28 -0800320 const StateFeedbackControllerConstants<number_of_states, number_of_inputs,
321 number_of_outputs>
322 &controller() const {
Austin Schuhe3490622013-03-13 01:24:30 -0700323 return *controllers_[controller_index_];
Austin Schuh9644e1c2013-03-12 00:40:36 -0700324 }
325
Austin Schuh66c19882017-02-25 13:36:28 -0800326 const StateFeedbackControllerConstants<number_of_states, number_of_inputs,
327 number_of_outputs>
328 &controller(int index) const {
Austin Schuh2054f5f2013-10-27 14:54:10 -0700329 return *controllers_[index];
330 }
331
Austin Schuh9644e1c2013-03-12 00:40:36 -0700332 void Reset() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700333 X_hat_.setZero();
334 R_.setZero();
Austin Schuhb6a6d822016-02-08 00:20:40 -0800335 next_R_.setZero();
Brian Silverman273d8a32014-05-10 22:19:09 -0700336 U_.setZero();
337 U_uncapped_.setZero();
Austin Schuhb6a6d822016-02-08 00:20:40 -0800338 ff_U_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800339 }
340
341 // If U is outside the hardware range, limit it before the plant tries to use
342 // it.
343 virtual void CapU() {
Brian Silverman5808bcb2014-09-14 21:40:43 -0400344 for (int i = 0; i < kNumInputs; ++i) {
Brian Silvermana21c3a22014-06-12 21:49:15 -0700345 if (U(i, 0) > U_max(i, 0)) {
346 U_(i, 0) = U_max(i, 0);
347 } else if (U(i, 0) < U_min(i, 0)) {
348 U_(i, 0) = U_min(i, 0);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800349 }
350 }
351 }
352
Austin Schuhf9286cd2014-02-11 00:51:09 -0800353 // Corrects X_hat given the observation in Y.
354 void Correct(const Eigen::Matrix<double, number_of_outputs, 1> &Y) {
Austin Schuh703b8d42015-02-01 14:56:34 -0800355 X_hat_ += A_inv() * L() * (Y - C() * X_hat_ - D() * U());
Austin Schuhf9286cd2014-02-11 00:51:09 -0800356 }
357
Austin Schuh3f862bb2016-02-27 14:48:05 -0800358 const Eigen::Matrix<double, number_of_states, 1> error() const {
359 return R() - X_hat();
360 }
361
Austin Schuhb6a6d822016-02-08 00:20:40 -0800362 // Returns the calculated controller power.
363 virtual const Eigen::Matrix<double, number_of_inputs, 1> ControllerOutput() {
364 ff_U_ = FeedForward();
Austin Schuh3f862bb2016-02-27 14:48:05 -0800365 return K() * error() + ff_U_;
Austin Schuhb6a6d822016-02-08 00:20:40 -0800366 }
367
368 // Calculates the feed forwards power.
369 virtual const Eigen::Matrix<double, number_of_inputs, 1> FeedForward() {
370 return Kff() * (next_R() - A() * R());
371 }
372
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800373 // stop_motors is whether or not to output all 0s.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800374 void Update(bool stop_motors) {
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800375 if (stop_motors) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700376 U_.setZero();
377 U_uncapped_.setZero();
Austin Schuhb6a6d822016-02-08 00:20:40 -0800378 ff_U_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800379 } else {
Austin Schuhb6a6d822016-02-08 00:20:40 -0800380 U_ = U_uncapped_ = ControllerOutput();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800381 CapU();
382 }
383
Austin Schuhc2b77742015-11-26 16:18:27 -0800384 UpdateObserver(U_);
Austin Schuh093535c2016-03-05 23:21:00 -0800385
386 UpdateFFReference();
387 }
388
389 // Updates R() after any CapU operations happen on U().
390 void UpdateFFReference() {
Austin Schuhb6a6d822016-02-08 00:20:40 -0800391 ff_U_ -= U_uncapped() - U();
392 if (!Kff().isZero(0)) {
393 R_ = A() * R() + B() * ff_U_;
394 }
Ben Fredrickson890c3fe2014-03-02 00:15:16 +0000395 }
396
Austin Schuhc2b77742015-11-26 16:18:27 -0800397 void UpdateObserver(const Eigen::Matrix<double, number_of_inputs, 1> &new_u) {
398 X_hat_ = A() * X_hat() + B() * new_u;
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800399 }
400
Brian Silverman273d8a32014-05-10 22:19:09 -0700401 // Sets the current controller to be index, clamped to be within range.
Austin Schuh9644e1c2013-03-12 00:40:36 -0700402 void set_controller_index(int index) {
Austin Schuhe3490622013-03-13 01:24:30 -0700403 if (index < 0) {
404 controller_index_ = 0;
405 } else if (index >= static_cast<int>(controllers_.size())) {
Brian Silvermanb8cd6892013-03-17 23:36:24 -0700406 controller_index_ = static_cast<int>(controllers_.size()) - 1;
Austin Schuhe3490622013-03-13 01:24:30 -0700407 } else {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700408 controller_index_ = index;
409 }
410 }
411
Austin Schuhd34569d2014-02-18 20:26:38 -0800412 int controller_index() const { return controller_index_; }
Austin Schuh9644e1c2013-03-12 00:40:36 -0700413
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800414 protected:
Austin Schuh66c19882017-02-25 13:36:28 -0800415 ::std::vector<::std::unique_ptr<StateFeedbackControllerConstants<
416 number_of_states, number_of_inputs, number_of_outputs>>>
417 controllers_;
Austin Schuh2054f5f2013-10-27 14:54:10 -0700418
Brian Silverman273d8a32014-05-10 22:19:09 -0700419 // These are accessible from non-templated subclasses.
Austin Schuhf59b6bc2016-03-11 21:26:19 -0800420 static constexpr int kNumStates = number_of_states;
421 static constexpr int kNumOutputs = number_of_outputs;
422 static constexpr int kNumInputs = number_of_inputs;
423
424 // Portion of U which is based on the feed-forwards.
425 Eigen::Matrix<double, number_of_inputs, 1> ff_U_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700426
Brian Silverman273d8a32014-05-10 22:19:09 -0700427 private:
Austin Schuhb6a6d822016-02-08 00:20:40 -0800428 // Internal state estimate.
Brian Silverman273d8a32014-05-10 22:19:09 -0700429 Eigen::Matrix<double, number_of_states, 1> X_hat_;
Austin Schuhb6a6d822016-02-08 00:20:40 -0800430 // Current goal (Used by the feed-back controller).
Brian Silverman273d8a32014-05-10 22:19:09 -0700431 Eigen::Matrix<double, number_of_states, 1> R_;
Austin Schuhb6a6d822016-02-08 00:20:40 -0800432 // Goal to go to in the next cycle (Used by Feed-Forward controller.)
433 Eigen::Matrix<double, number_of_states, 1> next_R_;
434 // Computed output after being capped.
Brian Silverman273d8a32014-05-10 22:19:09 -0700435 Eigen::Matrix<double, number_of_inputs, 1> U_;
Austin Schuhb6a6d822016-02-08 00:20:40 -0800436 // Computed output before being capped.
Brian Silverman273d8a32014-05-10 22:19:09 -0700437 Eigen::Matrix<double, number_of_inputs, 1> U_uncapped_;
438
Austin Schuh9644e1c2013-03-12 00:40:36 -0700439 int controller_index_;
Brian Silverman0a151c92014-05-02 15:28:44 -0700440
Brian Silverman0a151c92014-05-02 15:28:44 -0700441 DISALLOW_COPY_AND_ASSIGN(StateFeedbackLoop);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800442};
443
Brian Silverman273d8a32014-05-10 22:19:09 -0700444#endif // FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_H_