blob: 7a04cb9ae6432334724c4bf4866e9eafc44df183 [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()),
33 U_max_(other.U_max()) {
Austin Schuhdc1c84a2013-02-23 16:33:10 -080034 }
35
Austin Schuhe3490622013-03-13 01:24:30 -070036 StateFeedbackPlantCoefficients(
Austin Schuhdc1c84a2013-02-23 16:33:10 -080037 const Eigen::Matrix<double, number_of_states, number_of_states> &A,
38 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B,
39 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C,
40 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D,
Brian Silverman5808bcb2014-09-14 21:40:43 -040041 const Eigen::Matrix<double, number_of_inputs, 1> &U_max,
42 const Eigen::Matrix<double, number_of_inputs, 1> &U_min)
Brian Silverman273d8a32014-05-10 22:19:09 -070043 : A_(A),
44 B_(B),
45 C_(C),
46 D_(D),
47 U_min_(U_min),
48 U_max_(U_max) {
Austin Schuhe3490622013-03-13 01:24:30 -070049 }
50
Brian Silverman273d8a32014-05-10 22:19:09 -070051 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
52 return A_;
53 }
54 double A(int i, int j) const { return A()(i, j); }
55 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
56 return B_;
57 }
58 double B(int i, int j) const { return B()(i, j); }
59 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
60 return C_;
61 }
62 double C(int i, int j) const { return C()(i, j); }
63 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
64 return D_;
65 }
66 double D(int i, int j) const { return D()(i, j); }
67 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
68 return U_min_;
69 }
Brian Silvermana21c3a22014-06-12 21:49:15 -070070 double U_min(int i, int j) const { return U_min()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -070071 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
72 return U_max_;
73 }
Brian Silvermana21c3a22014-06-12 21:49:15 -070074 double U_max(int i, int j) const { return U_max()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -070075
76 private:
77 const Eigen::Matrix<double, number_of_states, number_of_states> A_;
78 const Eigen::Matrix<double, number_of_states, number_of_inputs> B_;
79 const Eigen::Matrix<double, number_of_outputs, number_of_states> C_;
80 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> D_;
81 const Eigen::Matrix<double, number_of_inputs, 1> U_min_;
82 const Eigen::Matrix<double, number_of_inputs, 1> U_max_;
83
84 StateFeedbackPlantCoefficients &operator=(
85 StateFeedbackPlantCoefficients other) = delete;
Austin Schuhe3490622013-03-13 01:24:30 -070086};
87
88template <int number_of_states, int number_of_inputs, int number_of_outputs>
89class StateFeedbackPlant {
90 public:
91 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
Brian Silverman0a151c92014-05-02 15:28:44 -070092
93 StateFeedbackPlant(
Austin Schuh1a387962015-01-31 16:36:20 -080094 ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<
95 number_of_states, number_of_inputs, number_of_outputs>>> *
96 coefficients)
97 : coefficients_(::std::move(*coefficients)), plant_index_(0) {
Brian Silverman0a151c92014-05-02 15:28:44 -070098 Reset();
99 }
100
101 StateFeedbackPlant(StateFeedbackPlant &&other)
102 : plant_index_(other.plant_index_) {
103 ::std::swap(coefficients_, other.coefficients_);
Brian Silverman273d8a32014-05-10 22:19:09 -0700104 X_.swap(other.X_);
105 Y_.swap(other.Y_);
106 U_.swap(other.U_);
Brian Silverman0a151c92014-05-02 15:28:44 -0700107 }
108
Austin Schuh1a387962015-01-31 16:36:20 -0800109 virtual ~StateFeedbackPlant() {}
Brian Silverman0a151c92014-05-02 15:28:44 -0700110
Austin Schuhe3490622013-03-13 01:24:30 -0700111 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700112 return coefficients().A();
Austin Schuhe3490622013-03-13 01:24:30 -0700113 }
114 double A(int i, int j) const { return A()(i, j); }
115 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700116 return coefficients().B();
Austin Schuhe3490622013-03-13 01:24:30 -0700117 }
118 double B(int i, int j) const { return B()(i, j); }
119 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700120 return coefficients().C();
Austin Schuhe3490622013-03-13 01:24:30 -0700121 }
122 double C(int i, int j) const { return C()(i, j); }
123 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700124 return coefficients().D();
Austin Schuhe3490622013-03-13 01:24:30 -0700125 }
126 double D(int i, int j) const { return D()(i, j); }
127 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700128 return coefficients().U_min();
Austin Schuhe3490622013-03-13 01:24:30 -0700129 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700130 double U_min(int i, int j) const { return U_min()(i, j); }
Austin Schuhe3490622013-03-13 01:24:30 -0700131 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700132 return coefficients().U_max();
Austin Schuhe3490622013-03-13 01:24:30 -0700133 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700134 double U_max(int i, int j) const { return U_max()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700135
136 const Eigen::Matrix<double, number_of_states, 1> &X() const { return X_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700137 double X(int i, int j) const { return X()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700138 const Eigen::Matrix<double, number_of_outputs, 1> &Y() const { return Y_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700139 double Y(int i, int j) const { return Y()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700140 const Eigen::Matrix<double, number_of_inputs, 1> &U() const { return U_; }
Brian Silverman5808bcb2014-09-14 21:40:43 -0400141 double U(int i, int j) const { return U()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700142
Brian Silverman0ca790b2014-06-12 21:33:08 -0700143 Eigen::Matrix<double, number_of_states, 1> &mutable_X() { return X_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700144 double &mutable_X(int i, int j) { return mutable_X()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700145 Eigen::Matrix<double, number_of_outputs, 1> &mutable_Y() { return Y_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700146 double &mutable_Y(int i, int j) { return mutable_Y()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700147 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U() { return U_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700148 double &mutable_U(int i, int j) { return mutable_U()(i, j); }
Austin Schuhe3490622013-03-13 01:24:30 -0700149
150 const StateFeedbackPlantCoefficients<
151 number_of_states, number_of_inputs, number_of_outputs>
152 &coefficients() const {
153 return *coefficients_[plant_index_];
154 }
155
156 int plant_index() const { return plant_index_; }
157 void set_plant_index(int plant_index) {
158 if (plant_index < 0) {
159 plant_index_ = 0;
160 } else if (plant_index >= static_cast<int>(coefficients_.size())) {
Brian Silvermanb8cd6892013-03-17 23:36:24 -0700161 plant_index_ = static_cast<int>(coefficients_.size()) - 1;
Austin Schuhe3490622013-03-13 01:24:30 -0700162 } else {
163 plant_index_ = plant_index;
164 }
165 }
166
167 void Reset() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700168 X_.setZero();
169 Y_.setZero();
170 U_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800171 }
172
Austin Schuh849f0032013-03-03 23:59:53 -0800173 // Assert that U is within the hardware range.
174 virtual void CheckU() {
Brian Silverman5808bcb2014-09-14 21:40:43 -0400175 for (int i = 0; i < kNumInputs; ++i) {
Brian Silvermana21c3a22014-06-12 21:49:15 -0700176 assert(U(i, 0) <= U_max(i, 0) + 0.00001);
177 assert(U(i, 0) >= U_min(i, 0) - 0.00001);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800178 }
179 }
Austin Schuh849f0032013-03-03 23:59:53 -0800180
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800181 // Computes the new X and Y given the control input.
182 void Update() {
Austin Schuh849f0032013-03-03 23:59:53 -0800183 // Powers outside of the range are more likely controller bugs than things
184 // that the plant should deal with.
185 CheckU();
Brian Silverman273d8a32014-05-10 22:19:09 -0700186 X_ = A() * X() + B() * U();
187 Y_ = C() * X() + D() * U();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800188 }
189
190 protected:
191 // these are accessible from non-templated subclasses
Austin Schuhb1cdb382013-03-01 22:53:52 -0800192 static const int kNumStates = number_of_states;
193 static const int kNumOutputs = number_of_outputs;
194 static const int kNumInputs = number_of_inputs;
Austin Schuhe3490622013-03-13 01:24:30 -0700195
196 private:
Brian Silverman273d8a32014-05-10 22:19:09 -0700197 Eigen::Matrix<double, number_of_states, 1> X_;
198 Eigen::Matrix<double, number_of_outputs, 1> Y_;
199 Eigen::Matrix<double, number_of_inputs, 1> U_;
200
Austin Schuh1a387962015-01-31 16:36:20 -0800201 ::std::vector< ::std::unique_ptr<StateFeedbackPlantCoefficients<
202 number_of_states, number_of_inputs, number_of_outputs>>> coefficients_;
Brian Silverman273d8a32014-05-10 22:19:09 -0700203
Austin Schuhe3490622013-03-13 01:24:30 -0700204 int plant_index_;
Brian Silverman0a151c92014-05-02 15:28:44 -0700205
206 DISALLOW_COPY_AND_ASSIGN(StateFeedbackPlant);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800207};
208
Austin Schuh9644e1c2013-03-12 00:40:36 -0700209// A Controller is a structure which holds a plant and the K and L matrices.
210// This is designed such that multiple controllers can share one set of state to
211// support gain scheduling easily.
212template <int number_of_states, int number_of_inputs, int number_of_outputs>
Brian Silverman273d8a32014-05-10 22:19:09 -0700213struct StateFeedbackController final {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700214 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
Brian Silverman273d8a32014-05-10 22:19:09 -0700215
Austin Schuh9644e1c2013-03-12 00:40:36 -0700216 const Eigen::Matrix<double, number_of_states, number_of_outputs> L;
Brian Silverman5808bcb2014-09-14 21:40:43 -0400217 const Eigen::Matrix<double, number_of_inputs, number_of_states> K;
Austin Schuh86093ad2016-02-06 14:29:34 -0800218 const Eigen::Matrix<double, number_of_inputs, number_of_states> Kff;
Austin Schuh1a387962015-01-31 16:36:20 -0800219 const Eigen::Matrix<double, number_of_states, number_of_states> A_inv;
Austin Schuhe3490622013-03-13 01:24:30 -0700220 StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
221 number_of_outputs> plant;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700222
223 StateFeedbackController(
224 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L,
Brian Silverman5808bcb2014-09-14 21:40:43 -0400225 const Eigen::Matrix<double, number_of_inputs, number_of_states> &K,
Austin Schuh86093ad2016-02-06 14:29:34 -0800226 const Eigen::Matrix<double, number_of_inputs, number_of_states> &Kff,
Austin Schuh1a387962015-01-31 16:36:20 -0800227 const Eigen::Matrix<double, number_of_states, number_of_states> &A_inv,
Austin Schuhe3490622013-03-13 01:24:30 -0700228 const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
229 number_of_outputs> &plant)
Austin Schuh9644e1c2013-03-12 00:40:36 -0700230 : L(L),
231 K(K),
Austin Schuh86093ad2016-02-06 14:29:34 -0800232 Kff(Kff),
Austin Schuh1a387962015-01-31 16:36:20 -0800233 A_inv(A_inv),
Austin Schuh9644e1c2013-03-12 00:40:36 -0700234 plant(plant) {
235 }
236};
237
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800238template <int number_of_states, int number_of_inputs, int number_of_outputs>
239class StateFeedbackLoop {
240 public:
241 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
242
Brian Silverman0a151c92014-05-02 15:28:44 -0700243 StateFeedbackLoop(const StateFeedbackController<
244 number_of_states, number_of_inputs, number_of_outputs> &controller)
245 : controller_index_(0) {
Austin Schuh1a387962015-01-31 16:36:20 -0800246 controllers_.emplace_back(new StateFeedbackController<
Brian Silverman0a151c92014-05-02 15:28:44 -0700247 number_of_states, number_of_inputs, number_of_outputs>(controller));
248 Reset();
249 }
250
Brian Silverman0a151c92014-05-02 15:28:44 -0700251 StateFeedbackLoop(
252 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L,
Brian Silverman5808bcb2014-09-14 21:40:43 -0400253 const Eigen::Matrix<double, number_of_inputs, number_of_states> &K,
Austin Schuh1a387962015-01-31 16:36:20 -0800254 const Eigen::Matrix<double, number_of_states, number_of_states> &A_inv,
Brian Silverman0a151c92014-05-02 15:28:44 -0700255 const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
256 number_of_outputs> &plant)
257 : controller_index_(0) {
Austin Schuh1a387962015-01-31 16:36:20 -0800258 controllers_.emplace_back(
Brian Silverman0a151c92014-05-02 15:28:44 -0700259 new StateFeedbackController<number_of_states, number_of_inputs,
Austin Schuh1a387962015-01-31 16:36:20 -0800260 number_of_outputs>(L, K, A_inv, plant));
Brian Silverman0a151c92014-05-02 15:28:44 -0700261
262 Reset();
263 }
264
Austin Schuh1a387962015-01-31 16:36:20 -0800265 StateFeedbackLoop(::std::vector< ::std::unique_ptr<StateFeedbackController<
266 number_of_states, number_of_inputs, number_of_outputs>>> *controllers)
267 : controllers_(::std::move(*controllers)), controller_index_(0) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700268 Reset();
269 }
270
271 StateFeedbackLoop(StateFeedbackLoop &&other) {
272 X_hat_.swap(other.X_hat_);
273 R_.swap(other.R_);
274 U_.swap(other.U_);
275 U_uncapped_.swap(other.U_uncapped_);
276 ::std::swap(controllers_, other.controllers_);
Brian Silverman273d8a32014-05-10 22:19:09 -0700277 controller_index_ = other.controller_index_;
278 }
279
Austin Schuh1a387962015-01-31 16:36:20 -0800280 virtual ~StateFeedbackLoop() {}
Brian Silverman0a151c92014-05-02 15:28:44 -0700281
Austin Schuh9644e1c2013-03-12 00:40:36 -0700282 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700283 return controller().plant.A();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700284 }
285 double A(int i, int j) const { return A()(i, j); }
286 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700287 return controller().plant.B();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700288 }
Austin Schuh703b8d42015-02-01 14:56:34 -0800289 const Eigen::Matrix<double, number_of_states, number_of_states> &A_inv() const {
290 return controller().A_inv;
291 }
292 double A_inv(int i, int j) const { return A_inv()(i, j); }
Austin Schuh9644e1c2013-03-12 00:40:36 -0700293 double B(int i, int j) const { return B()(i, j); }
294 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700295 return controller().plant.C();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700296 }
297 double C(int i, int j) const { return C()(i, j); }
298 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700299 return controller().plant.D();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700300 }
301 double D(int i, int j) const { return D()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700302 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
303 return controller().plant.U_min();
304 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700305 double U_min(int i, int j) const { return U_min()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700306 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
307 return controller().plant.U_max();
308 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700309 double U_max(int i, int j) const { return U_max()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700310
Brian Silverman5808bcb2014-09-14 21:40:43 -0400311 const Eigen::Matrix<double, number_of_inputs, number_of_states> &K() const {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700312 return controller().K;
313 }
314 double K(int i, int j) const { return K()(i, j); }
Austin Schuh86093ad2016-02-06 14:29:34 -0800315 const Eigen::Matrix<double, number_of_inputs, number_of_states> &Kff() const {
316 return controller().Kff;
317 }
318 double Kff(int i, int j) const { return Kff()(i, j); }
Austin Schuh9644e1c2013-03-12 00:40:36 -0700319 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L() const {
320 return controller().L;
321 }
322 double L(int i, int j) const { return L()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700323
324 const Eigen::Matrix<double, number_of_states, 1> &X_hat() const {
325 return X_hat_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700326 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700327 double X_hat(int i, int j) const { return X_hat()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700328 const Eigen::Matrix<double, number_of_states, 1> &R() const { return R_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700329 double R(int i, int j) const { return R()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700330 const Eigen::Matrix<double, number_of_inputs, 1> &U() const { return U_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700331 double U(int i, int j) const { return U()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700332 const Eigen::Matrix<double, number_of_inputs, 1> &U_uncapped() const {
333 return U_uncapped_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700334 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700335 double U_uncapped(int i, int j) const { return U_uncapped()(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); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700341 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U() { return U_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700342 double &mutable_U(int i, int j) { return mutable_U()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700343 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U_uncapped() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700344 return U_uncapped_;
345 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700346 double &mutable_U_uncapped(int i, int j) {
347 return mutable_U_uncapped()(i, j);
348 }
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800349
Brian Silverman2c590c32013-11-04 18:08:54 -0800350 const StateFeedbackController<number_of_states, number_of_inputs,
351 number_of_outputs> &controller() const {
Austin Schuhe3490622013-03-13 01:24:30 -0700352 return *controllers_[controller_index_];
Austin Schuh9644e1c2013-03-12 00:40:36 -0700353 }
354
Brian Silverman2c590c32013-11-04 18:08:54 -0800355 const StateFeedbackController<number_of_states, number_of_inputs,
356 number_of_outputs> &controller(
357 int index) const {
Austin Schuh2054f5f2013-10-27 14:54:10 -0700358 return *controllers_[index];
359 }
360
Austin Schuh9644e1c2013-03-12 00:40:36 -0700361 void Reset() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700362 X_hat_.setZero();
363 R_.setZero();
364 U_.setZero();
365 U_uncapped_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800366 }
367
368 // If U is outside the hardware range, limit it before the plant tries to use
369 // it.
370 virtual void CapU() {
Brian Silverman5808bcb2014-09-14 21:40:43 -0400371 for (int i = 0; i < kNumInputs; ++i) {
Brian Silvermana21c3a22014-06-12 21:49:15 -0700372 if (U(i, 0) > U_max(i, 0)) {
373 U_(i, 0) = U_max(i, 0);
374 } else if (U(i, 0) < U_min(i, 0)) {
375 U_(i, 0) = U_min(i, 0);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800376 }
377 }
378 }
379
Austin Schuhf9286cd2014-02-11 00:51:09 -0800380 // Corrects X_hat given the observation in Y.
381 void Correct(const Eigen::Matrix<double, number_of_outputs, 1> &Y) {
Austin Schuh703b8d42015-02-01 14:56:34 -0800382 X_hat_ += A_inv() * L() * (Y - C() * X_hat_ - D() * U());
Austin Schuhf9286cd2014-02-11 00:51:09 -0800383 }
384
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800385 // stop_motors is whether or not to output all 0s.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800386 void Update(bool stop_motors) {
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800387 if (stop_motors) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700388 U_.setZero();
389 U_uncapped_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800390 } else {
Brian Silverman273d8a32014-05-10 22:19:09 -0700391 U_ = U_uncapped_ = K() * (R() - X_hat());
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800392 CapU();
393 }
394
Austin Schuhc2b77742015-11-26 16:18:27 -0800395 UpdateObserver(U_);
Ben Fredrickson890c3fe2014-03-02 00:15:16 +0000396 }
397
Austin Schuhc2b77742015-11-26 16:18:27 -0800398 void UpdateObserver(const Eigen::Matrix<double, number_of_inputs, 1> &new_u) {
399 X_hat_ = A() * X_hat() + B() * new_u;
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800400 }
401
Brian Silverman273d8a32014-05-10 22:19:09 -0700402 // Sets the current controller to be index, clamped to be within range.
Austin Schuh9644e1c2013-03-12 00:40:36 -0700403 void set_controller_index(int index) {
Austin Schuhe3490622013-03-13 01:24:30 -0700404 if (index < 0) {
405 controller_index_ = 0;
406 } else if (index >= static_cast<int>(controllers_.size())) {
Brian Silvermanb8cd6892013-03-17 23:36:24 -0700407 controller_index_ = static_cast<int>(controllers_.size()) - 1;
Austin Schuhe3490622013-03-13 01:24:30 -0700408 } else {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700409 controller_index_ = index;
410 }
411 }
412
Austin Schuhd34569d2014-02-18 20:26:38 -0800413 int controller_index() const { return controller_index_; }
Austin Schuh9644e1c2013-03-12 00:40:36 -0700414
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800415 protected:
Austin Schuh1a387962015-01-31 16:36:20 -0800416 ::std::vector< ::std::unique_ptr<StateFeedbackController<
417 number_of_states, number_of_inputs, number_of_outputs>>> 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 Schuhb1cdb382013-03-01 22:53:52 -0800420 static const int kNumStates = number_of_states;
421 static const int kNumOutputs = number_of_outputs;
422 static const int kNumInputs = number_of_inputs;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700423
Brian Silverman273d8a32014-05-10 22:19:09 -0700424 private:
425 Eigen::Matrix<double, number_of_states, 1> X_hat_;
426 Eigen::Matrix<double, number_of_states, 1> R_;
427 Eigen::Matrix<double, number_of_inputs, 1> U_;
428 Eigen::Matrix<double, number_of_inputs, 1> U_uncapped_;
429
Austin Schuh9644e1c2013-03-12 00:40:36 -0700430 int controller_index_;
Brian Silverman0a151c92014-05-02 15:28:44 -0700431
Brian Silverman0a151c92014-05-02 15:28:44 -0700432 DISALLOW_COPY_AND_ASSIGN(StateFeedbackLoop);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800433};
434
Brian Silverman273d8a32014-05-10 22:19:09 -0700435#endif // FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_H_