blob: e78a786743f4779d424b0079cbb43a87c28d21e8 [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>
Brian Silverman273d8a32014-05-10 22:19:09 -070023class 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)
Brian Silverman273d8a32014-05-10 22:19:09 -070028 : A_(other.A()),
29 B_(other.B()),
30 C_(other.C()),
31 D_(other.D()),
32 U_min_(other.U_min()),
Austin Schuhb6a6d822016-02-08 00:20:40 -080033 U_max_(other.U_max()) {}
Austin Schuhdc1c84a2013-02-23 16:33:10 -080034
Austin Schuhe3490622013-03-13 01:24:30 -070035 StateFeedbackPlantCoefficients(
Austin Schuhdc1c84a2013-02-23 16:33:10 -080036 const Eigen::Matrix<double, number_of_states, number_of_states> &A,
37 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B,
38 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C,
39 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D,
Brian Silverman5808bcb2014-09-14 21:40:43 -040040 const Eigen::Matrix<double, number_of_inputs, 1> &U_max,
41 const Eigen::Matrix<double, number_of_inputs, 1> &U_min)
Austin Schuhb6a6d822016-02-08 00:20:40 -080042 : A_(A), B_(B), C_(C), D_(D), U_min_(U_min), U_max_(U_max) {}
Austin Schuhe3490622013-03-13 01:24:30 -070043
Brian Silverman273d8a32014-05-10 22:19:09 -070044 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
45 return A_;
46 }
47 double A(int i, int j) const { return A()(i, j); }
48 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
49 return B_;
50 }
51 double B(int i, int j) const { return B()(i, j); }
52 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
53 return C_;
54 }
55 double C(int i, int j) const { return C()(i, j); }
56 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
57 return D_;
58 }
59 double D(int i, int j) const { return D()(i, j); }
60 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
61 return U_min_;
62 }
Brian Silvermana21c3a22014-06-12 21:49:15 -070063 double U_min(int i, int j) const { return U_min()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -070064 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
65 return U_max_;
66 }
Brian Silvermana21c3a22014-06-12 21:49:15 -070067 double U_max(int i, int j) const { return U_max()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -070068
69 private:
70 const Eigen::Matrix<double, number_of_states, number_of_states> A_;
71 const Eigen::Matrix<double, number_of_states, number_of_inputs> B_;
72 const Eigen::Matrix<double, number_of_outputs, number_of_states> C_;
73 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> D_;
74 const Eigen::Matrix<double, number_of_inputs, 1> U_min_;
75 const Eigen::Matrix<double, number_of_inputs, 1> U_max_;
76
77 StateFeedbackPlantCoefficients &operator=(
78 StateFeedbackPlantCoefficients other) = delete;
Austin Schuhe3490622013-03-13 01:24:30 -070079};
80
81template <int number_of_states, int number_of_inputs, int number_of_outputs>
82class StateFeedbackPlant {
83 public:
84 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
Brian Silverman0a151c92014-05-02 15:28:44 -070085
86 StateFeedbackPlant(
Austin Schuhb6a6d822016-02-08 00:20:40 -080087 ::std::vector<::std::unique_ptr<StateFeedbackPlantCoefficients<
Austin Schuh1a387962015-01-31 16:36:20 -080088 number_of_states, number_of_inputs, number_of_outputs>>> *
89 coefficients)
90 : coefficients_(::std::move(*coefficients)), plant_index_(0) {
Brian Silverman0a151c92014-05-02 15:28:44 -070091 Reset();
92 }
93
94 StateFeedbackPlant(StateFeedbackPlant &&other)
95 : plant_index_(other.plant_index_) {
96 ::std::swap(coefficients_, other.coefficients_);
Brian Silverman273d8a32014-05-10 22:19:09 -070097 X_.swap(other.X_);
98 Y_.swap(other.Y_);
99 U_.swap(other.U_);
Brian Silverman0a151c92014-05-02 15:28:44 -0700100 }
101
Austin Schuh1a387962015-01-31 16:36:20 -0800102 virtual ~StateFeedbackPlant() {}
Brian Silverman0a151c92014-05-02 15:28:44 -0700103
Austin Schuhe3490622013-03-13 01:24:30 -0700104 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700105 return coefficients().A();
Austin Schuhe3490622013-03-13 01:24:30 -0700106 }
107 double A(int i, int j) const { return A()(i, j); }
108 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700109 return coefficients().B();
Austin Schuhe3490622013-03-13 01:24:30 -0700110 }
111 double B(int i, int j) const { return B()(i, j); }
112 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700113 return coefficients().C();
Austin Schuhe3490622013-03-13 01:24:30 -0700114 }
115 double C(int i, int j) const { return C()(i, j); }
116 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700117 return coefficients().D();
Austin Schuhe3490622013-03-13 01:24:30 -0700118 }
119 double D(int i, int j) const { return D()(i, j); }
120 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700121 return coefficients().U_min();
Austin Schuhe3490622013-03-13 01:24:30 -0700122 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700123 double U_min(int i, int j) const { return U_min()(i, j); }
Austin Schuhe3490622013-03-13 01:24:30 -0700124 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700125 return coefficients().U_max();
Austin Schuhe3490622013-03-13 01:24:30 -0700126 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700127 double U_max(int i, int j) const { return U_max()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700128
129 const Eigen::Matrix<double, number_of_states, 1> &X() const { return X_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700130 double X(int i, int j) const { return X()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700131 const Eigen::Matrix<double, number_of_outputs, 1> &Y() const { return Y_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700132 double Y(int i, int j) const { return Y()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700133 const Eigen::Matrix<double, number_of_inputs, 1> &U() const { return U_; }
Brian Silverman5808bcb2014-09-14 21:40:43 -0400134 double U(int i, int j) const { return U()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700135
Brian Silverman0ca790b2014-06-12 21:33:08 -0700136 Eigen::Matrix<double, number_of_states, 1> &mutable_X() { return X_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700137 double &mutable_X(int i, int j) { return mutable_X()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700138 Eigen::Matrix<double, number_of_outputs, 1> &mutable_Y() { return Y_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700139 double &mutable_Y(int i, int j) { return mutable_Y()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700140 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U() { return U_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700141 double &mutable_U(int i, int j) { return mutable_U()(i, j); }
Austin Schuhe3490622013-03-13 01:24:30 -0700142
Austin Schuhb6a6d822016-02-08 00:20:40 -0800143 const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
144 number_of_outputs> &
145 coefficients() const {
Austin Schuhe3490622013-03-13 01:24:30 -0700146 return *coefficients_[plant_index_];
147 }
148
149 int plant_index() const { return plant_index_; }
150 void set_plant_index(int plant_index) {
151 if (plant_index < 0) {
152 plant_index_ = 0;
153 } else if (plant_index >= static_cast<int>(coefficients_.size())) {
Brian Silvermanb8cd6892013-03-17 23:36:24 -0700154 plant_index_ = static_cast<int>(coefficients_.size()) - 1;
Austin Schuhe3490622013-03-13 01:24:30 -0700155 } else {
156 plant_index_ = plant_index;
157 }
158 }
159
160 void Reset() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700161 X_.setZero();
162 Y_.setZero();
163 U_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800164 }
165
Austin Schuh849f0032013-03-03 23:59:53 -0800166 // Assert that U is within the hardware range.
167 virtual void CheckU() {
Brian Silverman5808bcb2014-09-14 21:40:43 -0400168 for (int i = 0; i < kNumInputs; ++i) {
Brian Silvermana21c3a22014-06-12 21:49:15 -0700169 assert(U(i, 0) <= U_max(i, 0) + 0.00001);
170 assert(U(i, 0) >= U_min(i, 0) - 0.00001);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800171 }
172 }
Austin Schuh849f0032013-03-03 23:59:53 -0800173
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800174 // Computes the new X and Y given the control input.
175 void Update() {
Austin Schuh849f0032013-03-03 23:59:53 -0800176 // Powers outside of the range are more likely controller bugs than things
177 // that the plant should deal with.
178 CheckU();
Brian Silverman273d8a32014-05-10 22:19:09 -0700179 X_ = A() * X() + B() * U();
180 Y_ = C() * X() + D() * U();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800181 }
182
183 protected:
184 // these are accessible from non-templated subclasses
Austin Schuhb1cdb382013-03-01 22:53:52 -0800185 static const int kNumStates = number_of_states;
186 static const int kNumOutputs = number_of_outputs;
187 static const int kNumInputs = number_of_inputs;
Austin Schuhe3490622013-03-13 01:24:30 -0700188
189 private:
Brian Silverman273d8a32014-05-10 22:19:09 -0700190 Eigen::Matrix<double, number_of_states, 1> X_;
191 Eigen::Matrix<double, number_of_outputs, 1> Y_;
192 Eigen::Matrix<double, number_of_inputs, 1> U_;
193
Austin Schuhb6a6d822016-02-08 00:20:40 -0800194 ::std::vector<::std::unique_ptr<StateFeedbackPlantCoefficients<
Austin Schuh1a387962015-01-31 16:36:20 -0800195 number_of_states, number_of_inputs, number_of_outputs>>> coefficients_;
Brian Silverman273d8a32014-05-10 22:19:09 -0700196
Austin Schuhe3490622013-03-13 01:24:30 -0700197 int plant_index_;
Brian Silverman0a151c92014-05-02 15:28:44 -0700198
199 DISALLOW_COPY_AND_ASSIGN(StateFeedbackPlant);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800200};
201
Austin Schuh9644e1c2013-03-12 00:40:36 -0700202// A Controller is a structure which holds a plant and the K and L matrices.
203// This is designed such that multiple controllers can share one set of state to
204// support gain scheduling easily.
205template <int number_of_states, int number_of_inputs, int number_of_outputs>
Brian Silverman273d8a32014-05-10 22:19:09 -0700206struct StateFeedbackController final {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700207 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
Brian Silverman273d8a32014-05-10 22:19:09 -0700208
Austin Schuh9644e1c2013-03-12 00:40:36 -0700209 const Eigen::Matrix<double, number_of_states, number_of_outputs> L;
Brian Silverman5808bcb2014-09-14 21:40:43 -0400210 const Eigen::Matrix<double, number_of_inputs, number_of_states> K;
Austin Schuh86093ad2016-02-06 14:29:34 -0800211 const Eigen::Matrix<double, number_of_inputs, number_of_states> Kff;
Austin Schuh1a387962015-01-31 16:36:20 -0800212 const Eigen::Matrix<double, number_of_states, number_of_states> A_inv;
Austin Schuhe3490622013-03-13 01:24:30 -0700213 StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
214 number_of_outputs> plant;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700215
216 StateFeedbackController(
217 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L,
Brian Silverman5808bcb2014-09-14 21:40:43 -0400218 const Eigen::Matrix<double, number_of_inputs, number_of_states> &K,
Austin Schuh86093ad2016-02-06 14:29:34 -0800219 const Eigen::Matrix<double, number_of_inputs, number_of_states> &Kff,
Austin Schuh1a387962015-01-31 16:36:20 -0800220 const Eigen::Matrix<double, number_of_states, number_of_states> &A_inv,
Austin Schuhe3490622013-03-13 01:24:30 -0700221 const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
222 number_of_outputs> &plant)
Austin Schuhb6a6d822016-02-08 00:20:40 -0800223 : L(L), K(K), Kff(Kff), A_inv(A_inv), plant(plant) {}
Brian Silverman2a04b262016-02-12 19:52:36 -0500224
225 // TODO(Brian): Remove this overload once they're all converted.
226 StateFeedbackController(
227 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L,
228 const Eigen::Matrix<double, number_of_inputs, number_of_states> &K,
229 const Eigen::Matrix<double, number_of_states, number_of_states> &A_inv,
230 const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
231 number_of_outputs> &plant)
232 : L(L),
233 K(K),
234 Kff(::Eigen::Matrix<double, number_of_inputs,
235 number_of_states>::Zero()),
236 A_inv(A_inv),
237 plant(plant) {}
Austin Schuh9644e1c2013-03-12 00:40:36 -0700238};
239
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800240template <int number_of_states, int number_of_inputs, int number_of_outputs>
241class StateFeedbackLoop {
242 public:
243 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
244
Brian Silverman0a151c92014-05-02 15:28:44 -0700245 StateFeedbackLoop(const StateFeedbackController<
246 number_of_states, number_of_inputs, number_of_outputs> &controller)
247 : controller_index_(0) {
Austin Schuhb6a6d822016-02-08 00:20:40 -0800248 controllers_.emplace_back(
249 new StateFeedbackController<number_of_states, number_of_inputs,
250 number_of_outputs>(controller));
Brian Silverman0a151c92014-05-02 15:28:44 -0700251 Reset();
252 }
253
Austin Schuhb6a6d822016-02-08 00:20:40 -0800254 StateFeedbackLoop(::std::vector<::std::unique_ptr<StateFeedbackController<
Austin Schuh1a387962015-01-31 16:36:20 -0800255 number_of_states, number_of_inputs, number_of_outputs>>> *controllers)
256 : controllers_(::std::move(*controllers)), controller_index_(0) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700257 Reset();
258 }
259
260 StateFeedbackLoop(StateFeedbackLoop &&other) {
261 X_hat_.swap(other.X_hat_);
262 R_.swap(other.R_);
Austin Schuhb6a6d822016-02-08 00:20:40 -0800263 next_R_.swap(other.next_R_);
Brian Silverman273d8a32014-05-10 22:19:09 -0700264 U_.swap(other.U_);
265 U_uncapped_.swap(other.U_uncapped_);
Austin Schuhb6a6d822016-02-08 00:20:40 -0800266 ff_U_.swap(other.ff_U_);
Brian Silverman273d8a32014-05-10 22:19:09 -0700267 ::std::swap(controllers_, other.controllers_);
Brian Silverman273d8a32014-05-10 22:19:09 -0700268 controller_index_ = other.controller_index_;
269 }
270
Austin Schuh1a387962015-01-31 16:36:20 -0800271 virtual ~StateFeedbackLoop() {}
Brian Silverman0a151c92014-05-02 15:28:44 -0700272
Austin Schuh9644e1c2013-03-12 00:40:36 -0700273 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700274 return controller().plant.A();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700275 }
276 double A(int i, int j) const { return A()(i, j); }
277 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700278 return controller().plant.B();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700279 }
Austin Schuhb6a6d822016-02-08 00:20:40 -0800280 const Eigen::Matrix<double, number_of_states, number_of_states> &A_inv()
281 const {
Austin Schuh703b8d42015-02-01 14:56:34 -0800282 return controller().A_inv;
283 }
284 double A_inv(int i, int j) const { return A_inv()(i, j); }
Austin Schuh9644e1c2013-03-12 00:40:36 -0700285 double B(int i, int j) const { return B()(i, j); }
286 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700287 return controller().plant.C();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700288 }
289 double C(int i, int j) const { return C()(i, j); }
290 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700291 return controller().plant.D();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700292 }
293 double D(int i, int j) const { return D()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700294 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
295 return controller().plant.U_min();
296 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700297 double U_min(int i, int j) const { return U_min()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700298 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
299 return controller().plant.U_max();
300 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700301 double U_max(int i, int j) const { return U_max()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700302
Brian Silverman5808bcb2014-09-14 21:40:43 -0400303 const Eigen::Matrix<double, number_of_inputs, number_of_states> &K() const {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700304 return controller().K;
305 }
306 double K(int i, int j) const { return K()(i, j); }
Austin Schuh86093ad2016-02-06 14:29:34 -0800307 const Eigen::Matrix<double, number_of_inputs, number_of_states> &Kff() const {
308 return controller().Kff;
309 }
310 double Kff(int i, int j) const { return Kff()(i, j); }
Austin Schuh9644e1c2013-03-12 00:40:36 -0700311 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L() const {
312 return controller().L;
313 }
314 double L(int i, int j) const { return L()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700315
316 const Eigen::Matrix<double, number_of_states, 1> &X_hat() const {
317 return X_hat_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700318 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700319 double X_hat(int i, int j) const { return X_hat()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700320 const Eigen::Matrix<double, number_of_states, 1> &R() const { return R_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700321 double R(int i, int j) const { return R()(i, j); }
Austin Schuhb6a6d822016-02-08 00:20:40 -0800322 const Eigen::Matrix<double, number_of_states, 1> &next_R() const {
323 return next_R_;
324 }
325 double next_R(int i, int j) const { return next_R()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700326 const Eigen::Matrix<double, number_of_inputs, 1> &U() const { return U_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700327 double U(int i, int j) const { return U()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700328 const Eigen::Matrix<double, number_of_inputs, 1> &U_uncapped() const {
329 return U_uncapped_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700330 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700331 double U_uncapped(int i, int j) const { return U_uncapped()(i, j); }
Austin Schuhb6a6d822016-02-08 00:20:40 -0800332 const Eigen::Matrix<double, number_of_inputs, 1> &ff_U() const {
333 return ff_U_;
334 }
335 double ff_U(int i, int j) const { return ff_U()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700336
Brian Silverman0ca790b2014-06-12 21:33:08 -0700337 Eigen::Matrix<double, number_of_states, 1> &mutable_X_hat() { return X_hat_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700338 double &mutable_X_hat(int i, int j) { return mutable_X_hat()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700339 Eigen::Matrix<double, number_of_states, 1> &mutable_R() { return R_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700340 double &mutable_R(int i, int j) { return mutable_R()(i, j); }
Austin Schuhb6a6d822016-02-08 00:20:40 -0800341 Eigen::Matrix<double, number_of_states, 1> &mutable_next_R() {
342 return next_R_;
343 }
344 double &mutable_next_R(int i, int j) { return mutable_next_R()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700345 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U() { return U_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700346 double &mutable_U(int i, int j) { return mutable_U()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700347 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U_uncapped() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700348 return U_uncapped_;
349 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700350 double &mutable_U_uncapped(int i, int j) {
351 return mutable_U_uncapped()(i, j);
352 }
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800353
Brian Silverman2c590c32013-11-04 18:08:54 -0800354 const StateFeedbackController<number_of_states, number_of_inputs,
Austin Schuhb6a6d822016-02-08 00:20:40 -0800355 number_of_outputs> &
356 controller() const {
Austin Schuhe3490622013-03-13 01:24:30 -0700357 return *controllers_[controller_index_];
Austin Schuh9644e1c2013-03-12 00:40:36 -0700358 }
359
Brian Silverman2c590c32013-11-04 18:08:54 -0800360 const StateFeedbackController<number_of_states, number_of_inputs,
Austin Schuhb6a6d822016-02-08 00:20:40 -0800361 number_of_outputs> &
362 controller(int index) const {
Austin Schuh2054f5f2013-10-27 14:54:10 -0700363 return *controllers_[index];
364 }
365
Austin Schuh9644e1c2013-03-12 00:40:36 -0700366 void Reset() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700367 X_hat_.setZero();
368 R_.setZero();
Austin Schuhb6a6d822016-02-08 00:20:40 -0800369 next_R_.setZero();
Brian Silverman273d8a32014-05-10 22:19:09 -0700370 U_.setZero();
371 U_uncapped_.setZero();
Austin Schuhb6a6d822016-02-08 00:20:40 -0800372 ff_U_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800373 }
374
375 // If U is outside the hardware range, limit it before the plant tries to use
376 // it.
377 virtual void CapU() {
Brian Silverman5808bcb2014-09-14 21:40:43 -0400378 for (int i = 0; i < kNumInputs; ++i) {
Brian Silvermana21c3a22014-06-12 21:49:15 -0700379 if (U(i, 0) > U_max(i, 0)) {
380 U_(i, 0) = U_max(i, 0);
381 } else if (U(i, 0) < U_min(i, 0)) {
382 U_(i, 0) = U_min(i, 0);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800383 }
384 }
385 }
386
Austin Schuhf9286cd2014-02-11 00:51:09 -0800387 // Corrects X_hat given the observation in Y.
388 void Correct(const Eigen::Matrix<double, number_of_outputs, 1> &Y) {
Austin Schuh703b8d42015-02-01 14:56:34 -0800389 X_hat_ += A_inv() * L() * (Y - C() * X_hat_ - D() * U());
Austin Schuhf9286cd2014-02-11 00:51:09 -0800390 }
391
Austin Schuh3f862bb2016-02-27 14:48:05 -0800392 const Eigen::Matrix<double, number_of_states, 1> error() const {
393 return R() - X_hat();
394 }
395
Austin Schuhb6a6d822016-02-08 00:20:40 -0800396 // Returns the calculated controller power.
397 virtual const Eigen::Matrix<double, number_of_inputs, 1> ControllerOutput() {
398 ff_U_ = FeedForward();
Austin Schuh3f862bb2016-02-27 14:48:05 -0800399 return K() * error() + ff_U_;
Austin Schuhb6a6d822016-02-08 00:20:40 -0800400 }
401
402 // Calculates the feed forwards power.
403 virtual const Eigen::Matrix<double, number_of_inputs, 1> FeedForward() {
404 return Kff() * (next_R() - A() * R());
405 }
406
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800407 // stop_motors is whether or not to output all 0s.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800408 void Update(bool stop_motors) {
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800409 if (stop_motors) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700410 U_.setZero();
411 U_uncapped_.setZero();
Austin Schuhb6a6d822016-02-08 00:20:40 -0800412 ff_U_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800413 } else {
Austin Schuhb6a6d822016-02-08 00:20:40 -0800414 U_ = U_uncapped_ = ControllerOutput();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800415 CapU();
416 }
417
Austin Schuhc2b77742015-11-26 16:18:27 -0800418 UpdateObserver(U_);
Austin Schuh093535c2016-03-05 23:21:00 -0800419
420 UpdateFFReference();
421 }
422
423 // Updates R() after any CapU operations happen on U().
424 void UpdateFFReference() {
Austin Schuhb6a6d822016-02-08 00:20:40 -0800425 ff_U_ -= U_uncapped() - U();
426 if (!Kff().isZero(0)) {
427 R_ = A() * R() + B() * ff_U_;
428 }
Ben Fredrickson890c3fe2014-03-02 00:15:16 +0000429 }
430
Austin Schuhc2b77742015-11-26 16:18:27 -0800431 void UpdateObserver(const Eigen::Matrix<double, number_of_inputs, 1> &new_u) {
432 X_hat_ = A() * X_hat() + B() * new_u;
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800433 }
434
Brian Silverman273d8a32014-05-10 22:19:09 -0700435 // Sets the current controller to be index, clamped to be within range.
Austin Schuh9644e1c2013-03-12 00:40:36 -0700436 void set_controller_index(int index) {
Austin Schuhe3490622013-03-13 01:24:30 -0700437 if (index < 0) {
438 controller_index_ = 0;
439 } else if (index >= static_cast<int>(controllers_.size())) {
Brian Silvermanb8cd6892013-03-17 23:36:24 -0700440 controller_index_ = static_cast<int>(controllers_.size()) - 1;
Austin Schuhe3490622013-03-13 01:24:30 -0700441 } else {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700442 controller_index_ = index;
443 }
444 }
445
Austin Schuhd34569d2014-02-18 20:26:38 -0800446 int controller_index() const { return controller_index_; }
Austin Schuh9644e1c2013-03-12 00:40:36 -0700447
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800448 protected:
Austin Schuhb6a6d822016-02-08 00:20:40 -0800449 ::std::vector<::std::unique_ptr<StateFeedbackController<
Austin Schuh1a387962015-01-31 16:36:20 -0800450 number_of_states, number_of_inputs, number_of_outputs>>> controllers_;
Austin Schuh2054f5f2013-10-27 14:54:10 -0700451
Brian Silverman273d8a32014-05-10 22:19:09 -0700452 // These are accessible from non-templated subclasses.
Austin Schuhf59b6bc2016-03-11 21:26:19 -0800453 static constexpr int kNumStates = number_of_states;
454 static constexpr int kNumOutputs = number_of_outputs;
455 static constexpr int kNumInputs = number_of_inputs;
456
457 // Portion of U which is based on the feed-forwards.
458 Eigen::Matrix<double, number_of_inputs, 1> ff_U_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700459
Brian Silverman273d8a32014-05-10 22:19:09 -0700460 private:
Austin Schuhb6a6d822016-02-08 00:20:40 -0800461 // Internal state estimate.
Brian Silverman273d8a32014-05-10 22:19:09 -0700462 Eigen::Matrix<double, number_of_states, 1> X_hat_;
Austin Schuhb6a6d822016-02-08 00:20:40 -0800463 // Current goal (Used by the feed-back controller).
Brian Silverman273d8a32014-05-10 22:19:09 -0700464 Eigen::Matrix<double, number_of_states, 1> R_;
Austin Schuhb6a6d822016-02-08 00:20:40 -0800465 // Goal to go to in the next cycle (Used by Feed-Forward controller.)
466 Eigen::Matrix<double, number_of_states, 1> next_R_;
467 // Computed output after being capped.
Brian Silverman273d8a32014-05-10 22:19:09 -0700468 Eigen::Matrix<double, number_of_inputs, 1> U_;
Austin Schuhb6a6d822016-02-08 00:20:40 -0800469 // Computed output before being capped.
Brian Silverman273d8a32014-05-10 22:19:09 -0700470 Eigen::Matrix<double, number_of_inputs, 1> U_uncapped_;
471
Austin Schuh9644e1c2013-03-12 00:40:36 -0700472 int controller_index_;
Brian Silverman0a151c92014-05-02 15:28:44 -0700473
Brian Silverman0a151c92014-05-02 15:28:44 -0700474 DISALLOW_COPY_AND_ASSIGN(StateFeedbackLoop);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800475};
476
Brian Silverman273d8a32014-05-10 22:19:09 -0700477#endif // FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_H_