blob: 9bd01655353484a28009ad9cebb41e06059a3308 [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 Schuhcda86af2014-02-16 16:16:39 -08007#include <iostream>
Brian Silvermanc571e052013-03-13 17:58:56 -07008
Austin Schuhdc1c84a2013-02-23 16:33:10 -08009#include "Eigen/Dense"
10
Austin Schuhcda86af2014-02-16 16:16:39 -080011#include "aos/common/logging/logging.h"
Brian Silverman0a151c92014-05-02 15:28:44 -070012#include "aos/common/macros.h"
13
Austin Schuhdc1c84a2013-02-23 16:33:10 -080014template <int number_of_states, int number_of_inputs, int number_of_outputs>
Brian Silverman273d8a32014-05-10 22:19:09 -070015class StateFeedbackPlantCoefficients final {
Austin Schuhdc1c84a2013-02-23 16:33:10 -080016 public:
17 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
18
Austin Schuhe3490622013-03-13 01:24:30 -070019 StateFeedbackPlantCoefficients(const StateFeedbackPlantCoefficients &other)
Brian Silverman273d8a32014-05-10 22:19:09 -070020 : A_(other.A()),
21 B_(other.B()),
22 C_(other.C()),
23 D_(other.D()),
24 U_min_(other.U_min()),
25 U_max_(other.U_max()) {
Austin Schuhdc1c84a2013-02-23 16:33:10 -080026 }
27
Austin Schuhe3490622013-03-13 01:24:30 -070028 StateFeedbackPlantCoefficients(
Austin Schuhdc1c84a2013-02-23 16:33:10 -080029 const Eigen::Matrix<double, number_of_states, number_of_states> &A,
30 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B,
31 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C,
32 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D,
33 const Eigen::Matrix<double, number_of_outputs, 1> &U_max,
34 const Eigen::Matrix<double, number_of_outputs, 1> &U_min)
Brian Silverman273d8a32014-05-10 22:19:09 -070035 : A_(A),
36 B_(B),
37 C_(C),
38 D_(D),
39 U_min_(U_min),
40 U_max_(U_max) {
Austin Schuhe3490622013-03-13 01:24:30 -070041 }
42
Brian Silverman273d8a32014-05-10 22:19:09 -070043 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
44 return A_;
45 }
46 double A(int i, int j) const { return A()(i, j); }
47 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
48 return B_;
49 }
50 double B(int i, int j) const { return B()(i, j); }
51 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
52 return C_;
53 }
54 double C(int i, int j) const { return C()(i, j); }
55 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
56 return D_;
57 }
58 double D(int i, int j) const { return D()(i, j); }
59 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
60 return U_min_;
61 }
62 double U_min(int i) const { return U_min()(i, 0); }
63 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
64 return U_max_;
65 }
66 double U_max(int i) const { return U_max()(i, 0); }
67
68 private:
69 const Eigen::Matrix<double, number_of_states, number_of_states> A_;
70 const Eigen::Matrix<double, number_of_states, number_of_inputs> B_;
71 const Eigen::Matrix<double, number_of_outputs, number_of_states> C_;
72 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> D_;
73 const Eigen::Matrix<double, number_of_inputs, 1> U_min_;
74 const Eigen::Matrix<double, number_of_inputs, 1> U_max_;
75
76 StateFeedbackPlantCoefficients &operator=(
77 StateFeedbackPlantCoefficients other) = delete;
Austin Schuhe3490622013-03-13 01:24:30 -070078};
79
80template <int number_of_states, int number_of_inputs, int number_of_outputs>
81class StateFeedbackPlant {
82 public:
83 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
Brian Silverman0a151c92014-05-02 15:28:44 -070084
85 StateFeedbackPlant(
86 const ::std::vector<StateFeedbackPlantCoefficients<
87 number_of_states, number_of_inputs,
88 number_of_outputs> *> &coefficients)
89 : coefficients_(coefficients),
90 plant_index_(0) {
91 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
102 virtual ~StateFeedbackPlant() {
103 for (auto c : coefficients_) {
104 delete c;
105 }
106 }
107
Austin Schuhe3490622013-03-13 01:24:30 -0700108 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700109 return coefficients().A();
Austin Schuhe3490622013-03-13 01:24:30 -0700110 }
111 double A(int i, int j) const { return A()(i, j); }
112 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700113 return coefficients().B();
Austin Schuhe3490622013-03-13 01:24:30 -0700114 }
115 double B(int i, int j) const { return B()(i, j); }
116 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700117 return coefficients().C();
Austin Schuhe3490622013-03-13 01:24:30 -0700118 }
119 double C(int i, int j) const { return C()(i, j); }
120 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700121 return coefficients().D();
Austin Schuhe3490622013-03-13 01:24:30 -0700122 }
123 double D(int i, int j) const { return D()(i, j); }
124 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700125 return coefficients().U_min();
Austin Schuhe3490622013-03-13 01:24:30 -0700126 }
Brian Silverman273d8a32014-05-10 22:19:09 -0700127 double U_min(int i) const { return U_min()(i, 0); }
Austin Schuhe3490622013-03-13 01:24:30 -0700128 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700129 return coefficients().U_max();
Austin Schuhe3490622013-03-13 01:24:30 -0700130 }
Brian Silverman273d8a32014-05-10 22:19:09 -0700131 double U_max(int i) const { return U_max()(i, 0); }
132
133 const Eigen::Matrix<double, number_of_states, 1> &X() const { return X_; }
134 double X(int i) const { return X()(i, 0); }
135 const Eigen::Matrix<double, number_of_outputs, 1> &Y() const { return Y_; }
136 double Y(int i) const { return Y()(i, 0); }
137 const Eigen::Matrix<double, number_of_inputs, 1> &U() const { return U_; }
138 double U(int i) const { return X()(i, 0); }
139
Brian Silverman0ca790b2014-06-12 21:33:08 -0700140 Eigen::Matrix<double, number_of_states, 1> &mutable_X() { return X_; }
141 double &mutable_X(int i) { return mutable_X()(i, 0); }
142 Eigen::Matrix<double, number_of_outputs, 1> &mutable_Y() { return Y_; }
143 double &mutable_Y(int i) { return mutable_Y()(i, 0); }
144 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U() { return U_; }
145 double &mutable_U(int i) { return mutable_U()(i, 0); }
Austin Schuhe3490622013-03-13 01:24:30 -0700146
147 const StateFeedbackPlantCoefficients<
148 number_of_states, number_of_inputs, number_of_outputs>
149 &coefficients() const {
150 return *coefficients_[plant_index_];
151 }
152
153 int plant_index() const { return plant_index_; }
154 void set_plant_index(int plant_index) {
155 if (plant_index < 0) {
156 plant_index_ = 0;
157 } else if (plant_index >= static_cast<int>(coefficients_.size())) {
Brian Silvermanb8cd6892013-03-17 23:36:24 -0700158 plant_index_ = static_cast<int>(coefficients_.size()) - 1;
Austin Schuhe3490622013-03-13 01:24:30 -0700159 } else {
160 plant_index_ = plant_index;
161 }
162 }
163
164 void Reset() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700165 X_.setZero();
166 Y_.setZero();
167 U_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800168 }
169
Austin Schuh849f0032013-03-03 23:59:53 -0800170 // Assert that U is within the hardware range.
171 virtual void CheckU() {
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800172 for (int i = 0; i < kNumOutputs; ++i) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700173 assert(U(i) <= U_max(i) + 0.00001);
174 assert(U(i) >= U_min(i) - 0.00001);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800175 }
176 }
Austin Schuh849f0032013-03-03 23:59:53 -0800177
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800178 // Computes the new X and Y given the control input.
179 void Update() {
Austin Schuh849f0032013-03-03 23:59:53 -0800180 // Powers outside of the range are more likely controller bugs than things
181 // that the plant should deal with.
182 CheckU();
Brian Silverman273d8a32014-05-10 22:19:09 -0700183 X_ = A() * X() + B() * U();
184 Y_ = C() * X() + D() * U();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800185 }
186
187 protected:
188 // these are accessible from non-templated subclasses
Austin Schuhb1cdb382013-03-01 22:53:52 -0800189 static const int kNumStates = number_of_states;
190 static const int kNumOutputs = number_of_outputs;
191 static const int kNumInputs = number_of_inputs;
Austin Schuhe3490622013-03-13 01:24:30 -0700192
193 private:
Brian Silverman273d8a32014-05-10 22:19:09 -0700194 Eigen::Matrix<double, number_of_states, 1> X_;
195 Eigen::Matrix<double, number_of_outputs, 1> Y_;
196 Eigen::Matrix<double, number_of_inputs, 1> U_;
197
198 ::std::vector<StateFeedbackPlantCoefficients<
199 number_of_states, number_of_inputs, number_of_outputs> *> coefficients_;
200
Austin Schuhe3490622013-03-13 01:24:30 -0700201 int plant_index_;
Brian Silverman0a151c92014-05-02 15:28:44 -0700202
203 DISALLOW_COPY_AND_ASSIGN(StateFeedbackPlant);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800204};
205
Austin Schuh9644e1c2013-03-12 00:40:36 -0700206// A Controller is a structure which holds a plant and the K and L matrices.
207// This is designed such that multiple controllers can share one set of state to
208// support gain scheduling easily.
209template <int number_of_states, int number_of_inputs, int number_of_outputs>
Brian Silverman273d8a32014-05-10 22:19:09 -0700210struct StateFeedbackController final {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700211 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
Brian Silverman273d8a32014-05-10 22:19:09 -0700212
Austin Schuh9644e1c2013-03-12 00:40:36 -0700213 const Eigen::Matrix<double, number_of_states, number_of_outputs> L;
214 const Eigen::Matrix<double, number_of_outputs, number_of_states> K;
Austin Schuhe3490622013-03-13 01:24:30 -0700215 StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
216 number_of_outputs> plant;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700217
218 StateFeedbackController(
219 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L,
220 const Eigen::Matrix<double, number_of_outputs, number_of_states> &K,
Austin Schuhe3490622013-03-13 01:24:30 -0700221 const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
222 number_of_outputs> &plant)
Austin Schuh9644e1c2013-03-12 00:40:36 -0700223 : L(L),
224 K(K),
225 plant(plant) {
226 }
227};
228
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800229template <int number_of_states, int number_of_inputs, int number_of_outputs>
230class StateFeedbackLoop {
231 public:
232 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
233
Brian Silverman0a151c92014-05-02 15:28:44 -0700234 StateFeedbackLoop(const StateFeedbackController<
235 number_of_states, number_of_inputs, number_of_outputs> &controller)
236 : controller_index_(0) {
237 controllers_.push_back(new StateFeedbackController<
238 number_of_states, number_of_inputs, number_of_outputs>(controller));
239 Reset();
240 }
241
Brian Silverman0a151c92014-05-02 15:28:44 -0700242 StateFeedbackLoop(
243 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L,
244 const Eigen::Matrix<double, number_of_outputs, number_of_states> &K,
245 const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
246 number_of_outputs> &plant)
247 : controller_index_(0) {
248 controllers_.push_back(
249 new StateFeedbackController<number_of_states, number_of_inputs,
250 number_of_outputs>(L, K, plant));
251
252 Reset();
253 }
254
Brian Silverman273d8a32014-05-10 22:19:09 -0700255 StateFeedbackLoop(const ::std::vector<StateFeedbackController<
256 number_of_states, number_of_inputs, number_of_outputs> *> &controllers)
257 : controllers_(controllers), controller_index_(0) {
258 Reset();
259 }
260
261 StateFeedbackLoop(StateFeedbackLoop &&other) {
262 X_hat_.swap(other.X_hat_);
263 R_.swap(other.R_);
264 U_.swap(other.U_);
265 U_uncapped_.swap(other.U_uncapped_);
266 ::std::swap(controllers_, other.controllers_);
267 Y_.swap(other.Y_);
268 new_y_ = other.new_y_;
269 controller_index_ = other.controller_index_;
270 }
271
Brian Silverman0a151c92014-05-02 15:28:44 -0700272 virtual ~StateFeedbackLoop() {
273 for (auto c : controllers_) {
274 delete c;
275 }
276 }
277
Austin Schuh9644e1c2013-03-12 00:40:36 -0700278 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700279 return controller().plant.A();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700280 }
281 double A(int i, int j) const { return A()(i, j); }
282 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700283 return controller().plant.B();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700284 }
285 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 }
297 double U_min(int i) const { return U_min()(i, 0); }
298 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
299 return controller().plant.U_max();
300 }
301 double U_max(int i) const { return U_max()(i, 0); }
302
Austin Schuh9644e1c2013-03-12 00:40:36 -0700303 const Eigen::Matrix<double, number_of_outputs, number_of_states> &K() const {
304 return controller().K;
305 }
306 double K(int i, int j) const { return K()(i, j); }
307 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L() const {
308 return controller().L;
309 }
310 double L(int i, int j) const { return L()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700311
312 const Eigen::Matrix<double, number_of_states, 1> &X_hat() const {
313 return X_hat_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700314 }
Brian Silverman273d8a32014-05-10 22:19:09 -0700315 double X_hat(int i) const { return X_hat()(i, 0); }
316 const Eigen::Matrix<double, number_of_states, 1> &R() const { return R_; }
317 double R(int i) const { return R()(i, 0); }
318 const Eigen::Matrix<double, number_of_inputs, 1> &U() const { return U_; }
319 double U(int i) const { return U()(i, 0); }
320 const Eigen::Matrix<double, number_of_inputs, 1> &U_uncapped() const {
321 return U_uncapped_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700322 }
Brian Silverman273d8a32014-05-10 22:19:09 -0700323 double U_uncapped(int i) const { return U_uncapped()(i, 0); }
324 const Eigen::Matrix<double, number_of_outputs, 1> &Y() const { return Y_; }
325 double Y(int i) const { return Y()(i, 0); }
326
Brian Silverman0ca790b2014-06-12 21:33:08 -0700327 Eigen::Matrix<double, number_of_states, 1> &mutable_X_hat() { return X_hat_; }
328 double &mutable_X_hat(int i) { return mutable_X_hat()(i, 0); }
329 Eigen::Matrix<double, number_of_states, 1> &mutable_R() { return R_; }
330 double &mutable_R(int i) { return mutable_R()(i, 0); }
331 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U() { return U_; }
332 double &mutable_U(int i) { return mutable_U()(i, 0); }
333 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U_uncapped() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700334 return U_uncapped_;
335 }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700336 double &mutable_U_uncapped(int i) { return mutable_U_uncapped()(i, 0); }
337 Eigen::Matrix<double, number_of_outputs, 1> &mutable_Y() { return Y_; }
338 double &mutable_Y(int i) { return mutable_Y()(i, 0); }
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800339
Brian Silverman2c590c32013-11-04 18:08:54 -0800340 const StateFeedbackController<number_of_states, number_of_inputs,
341 number_of_outputs> &controller() const {
Austin Schuhe3490622013-03-13 01:24:30 -0700342 return *controllers_[controller_index_];
Austin Schuh9644e1c2013-03-12 00:40:36 -0700343 }
344
Brian Silverman2c590c32013-11-04 18:08:54 -0800345 const StateFeedbackController<number_of_states, number_of_inputs,
346 number_of_outputs> &controller(
347 int index) const {
Austin Schuh2054f5f2013-10-27 14:54:10 -0700348 return *controllers_[index];
349 }
350
Austin Schuh9644e1c2013-03-12 00:40:36 -0700351 void Reset() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700352 X_hat_.setZero();
353 R_.setZero();
354 U_.setZero();
355 U_uncapped_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800356 }
357
358 // If U is outside the hardware range, limit it before the plant tries to use
359 // it.
360 virtual void CapU() {
361 for (int i = 0; i < kNumOutputs; ++i) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700362 if (U(i) > U_max(i)) {
363 U_(i, 0) = U_max(i);
364 } else if (U(i) < U_min(i)) {
365 U_(i, 0) = U_min(i);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800366 }
367 }
368 }
369
Austin Schuhf9286cd2014-02-11 00:51:09 -0800370 // Corrects X_hat given the observation in Y.
371 void Correct(const Eigen::Matrix<double, number_of_outputs, 1> &Y) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800372 /*
373 auto eye =
374 Eigen::Matrix<double, number_of_states, number_of_states>::Identity();
375 //LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
376 ::std::cout << "Identity " << eye << ::std::endl;
377 ::std::cout << "X_hat " << X_hat << ::std::endl;
378 ::std::cout << "LC " << L() * C() << ::std::endl;
379 ::std::cout << "L " << L() << ::std::endl;
380 ::std::cout << "C " << C() << ::std::endl;
381 ::std::cout << "y " << Y << ::std::endl;
382 ::std::cout << "z " << (Y - C() * X_hat) << ::std::endl;
383 ::std::cout << "correction " << L() * (Y - C() * X_hat) << ::std::endl;
384 X_hat = (eye - L() * C()) * X_hat + L() * Y;
385 ::std::cout << "X_hat after " << X_hat << ::std::endl;
386 ::std::cout << ::std::endl;
387 */
388 //LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
Austin Schuhf9286cd2014-02-11 00:51:09 -0800389 Y_ = Y;
390 new_y_ = true;
391 }
392
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800393 // stop_motors is whether or not to output all 0s.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800394 void Update(bool stop_motors) {
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800395 if (stop_motors) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700396 U_.setZero();
397 U_uncapped_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800398 } else {
Brian Silverman273d8a32014-05-10 22:19:09 -0700399 U_ = U_uncapped_ = K() * (R() - X_hat());
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800400 CapU();
401 }
402
Ben Fredrickson890c3fe2014-03-02 00:15:16 +0000403 UpdateObserver();
404 }
405
406 void UpdateObserver() {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800407 if (new_y_) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700408 X_hat_ = (A() - L() * C()) * X_hat() + L() * Y() + B() * U();
Austin Schuhf9286cd2014-02-11 00:51:09 -0800409 new_y_ = false;
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800410 } else {
Brian Silverman273d8a32014-05-10 22:19:09 -0700411 X_hat_ = A() * X_hat() + B() * U();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800412 }
413 }
414
Brian Silverman273d8a32014-05-10 22:19:09 -0700415 // Sets the current controller to be index, clamped to be within range.
Austin Schuh9644e1c2013-03-12 00:40:36 -0700416 void set_controller_index(int index) {
Austin Schuhe3490622013-03-13 01:24:30 -0700417 if (index < 0) {
418 controller_index_ = 0;
419 } else if (index >= static_cast<int>(controllers_.size())) {
Brian Silvermanb8cd6892013-03-17 23:36:24 -0700420 controller_index_ = static_cast<int>(controllers_.size()) - 1;
Austin Schuhe3490622013-03-13 01:24:30 -0700421 } else {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700422 controller_index_ = index;
423 }
424 }
425
Austin Schuhd34569d2014-02-18 20:26:38 -0800426 int controller_index() const { return controller_index_; }
Austin Schuh9644e1c2013-03-12 00:40:36 -0700427
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800428 protected:
Austin Schuh2054f5f2013-10-27 14:54:10 -0700429 ::std::vector<StateFeedbackController<number_of_states, number_of_inputs,
430 number_of_outputs> *> controllers_;
431
Brian Silverman273d8a32014-05-10 22:19:09 -0700432 // These are accessible from non-templated subclasses.
Austin Schuhb1cdb382013-03-01 22:53:52 -0800433 static const int kNumStates = number_of_states;
434 static const int kNumOutputs = number_of_outputs;
435 static const int kNumInputs = number_of_inputs;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700436
Brian Silverman273d8a32014-05-10 22:19:09 -0700437 private:
438 Eigen::Matrix<double, number_of_states, 1> X_hat_;
439 Eigen::Matrix<double, number_of_states, 1> R_;
440 Eigen::Matrix<double, number_of_inputs, 1> U_;
441 Eigen::Matrix<double, number_of_inputs, 1> U_uncapped_;
442
Austin Schuhf9286cd2014-02-11 00:51:09 -0800443 // Temporary storage for a measurement until I can figure out why I can't
444 // correct when the measurement is made.
445 Eigen::Matrix<double, number_of_outputs, 1> Y_;
446 bool new_y_ = false;
447
Austin Schuh9644e1c2013-03-12 00:40:36 -0700448 int controller_index_;
Brian Silverman0a151c92014-05-02 15:28:44 -0700449
Brian Silverman0a151c92014-05-02 15:28:44 -0700450 DISALLOW_COPY_AND_ASSIGN(StateFeedbackLoop);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800451};
452
Brian Silverman273d8a32014-05-10 22:19:09 -0700453#endif // FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_H_