blob: 8dcce5a5f5d7e5c2ee904a1ee9b0a47a54e9aa42 [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
Brian Silverman5808bcb2014-09-14 21:40:43 -040014// For everything in this file, "inputs" and "outputs" are defined from the
15// perspective of the plant. This means U is an input and Y is an output
16// (because you give the plant U (powers) and it gives you back a Y (sensor
17// values). This is the opposite of what they mean from the perspective of the
18// controller (U is an output because that's what goes to the motors and Y is an
19// input because that's what comes back from the sensors).
20
Austin Schuhdc1c84a2013-02-23 16:33:10 -080021template <int number_of_states, int number_of_inputs, int number_of_outputs>
Brian Silverman273d8a32014-05-10 22:19:09 -070022class StateFeedbackPlantCoefficients final {
Austin Schuhdc1c84a2013-02-23 16:33:10 -080023 public:
24 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
25
Austin Schuhe3490622013-03-13 01:24:30 -070026 StateFeedbackPlantCoefficients(const StateFeedbackPlantCoefficients &other)
Brian Silverman273d8a32014-05-10 22:19:09 -070027 : A_(other.A()),
28 B_(other.B()),
29 C_(other.C()),
30 D_(other.D()),
31 U_min_(other.U_min()),
32 U_max_(other.U_max()) {
Austin Schuhdc1c84a2013-02-23 16:33:10 -080033 }
34
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)
Brian Silverman273d8a32014-05-10 22:19:09 -070042 : A_(A),
43 B_(B),
44 C_(C),
45 D_(D),
46 U_min_(U_min),
47 U_max_(U_max) {
Austin Schuhe3490622013-03-13 01:24:30 -070048 }
49
Brian Silverman273d8a32014-05-10 22:19:09 -070050 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
51 return A_;
52 }
53 double A(int i, int j) const { return A()(i, j); }
54 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
55 return B_;
56 }
57 double B(int i, int j) const { return B()(i, j); }
58 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
59 return C_;
60 }
61 double C(int i, int j) const { return C()(i, j); }
62 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
63 return D_;
64 }
65 double D(int i, int j) const { return D()(i, j); }
66 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
67 return U_min_;
68 }
Brian Silvermana21c3a22014-06-12 21:49:15 -070069 double U_min(int i, int j) const { return U_min()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -070070 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
71 return U_max_;
72 }
Brian Silvermana21c3a22014-06-12 21:49:15 -070073 double U_max(int i, int j) const { return U_max()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -070074
75 private:
76 const Eigen::Matrix<double, number_of_states, number_of_states> A_;
77 const Eigen::Matrix<double, number_of_states, number_of_inputs> B_;
78 const Eigen::Matrix<double, number_of_outputs, number_of_states> C_;
79 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> D_;
80 const Eigen::Matrix<double, number_of_inputs, 1> U_min_;
81 const Eigen::Matrix<double, number_of_inputs, 1> U_max_;
82
83 StateFeedbackPlantCoefficients &operator=(
84 StateFeedbackPlantCoefficients other) = delete;
Austin Schuhe3490622013-03-13 01:24:30 -070085};
86
87template <int number_of_states, int number_of_inputs, int number_of_outputs>
88class StateFeedbackPlant {
89 public:
90 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
Brian Silverman0a151c92014-05-02 15:28:44 -070091
92 StateFeedbackPlant(
93 const ::std::vector<StateFeedbackPlantCoefficients<
94 number_of_states, number_of_inputs,
95 number_of_outputs> *> &coefficients)
96 : coefficients_(coefficients),
97 plant_index_(0) {
98 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
109 virtual ~StateFeedbackPlant() {
110 for (auto c : coefficients_) {
111 delete c;
112 }
113 }
114
Austin Schuhe3490622013-03-13 01:24:30 -0700115 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700116 return coefficients().A();
Austin Schuhe3490622013-03-13 01:24:30 -0700117 }
118 double A(int i, int j) const { return A()(i, j); }
119 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700120 return coefficients().B();
Austin Schuhe3490622013-03-13 01:24:30 -0700121 }
122 double B(int i, int j) const { return B()(i, j); }
123 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700124 return coefficients().C();
Austin Schuhe3490622013-03-13 01:24:30 -0700125 }
126 double C(int i, int j) const { return C()(i, j); }
127 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700128 return coefficients().D();
Austin Schuhe3490622013-03-13 01:24:30 -0700129 }
130 double D(int i, int j) const { return D()(i, j); }
131 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700132 return coefficients().U_min();
Austin Schuhe3490622013-03-13 01:24:30 -0700133 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700134 double U_min(int i, int j) const { return U_min()(i, j); }
Austin Schuhe3490622013-03-13 01:24:30 -0700135 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700136 return coefficients().U_max();
Austin Schuhe3490622013-03-13 01:24:30 -0700137 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700138 double U_max(int i, int j) const { return U_max()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700139
140 const Eigen::Matrix<double, number_of_states, 1> &X() const { return X_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700141 double X(int i, int j) const { return X()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700142 const Eigen::Matrix<double, number_of_outputs, 1> &Y() const { return Y_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700143 double Y(int i, int j) const { return Y()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700144 const Eigen::Matrix<double, number_of_inputs, 1> &U() const { return U_; }
Brian Silverman5808bcb2014-09-14 21:40:43 -0400145 double U(int i, int j) const { return U()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700146
Brian Silverman0ca790b2014-06-12 21:33:08 -0700147 Eigen::Matrix<double, number_of_states, 1> &mutable_X() { return X_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700148 double &mutable_X(int i, int j) { return mutable_X()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700149 Eigen::Matrix<double, number_of_outputs, 1> &mutable_Y() { return Y_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700150 double &mutable_Y(int i, int j) { return mutable_Y()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700151 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U() { return U_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700152 double &mutable_U(int i, int j) { return mutable_U()(i, j); }
Austin Schuhe3490622013-03-13 01:24:30 -0700153
154 const StateFeedbackPlantCoefficients<
155 number_of_states, number_of_inputs, number_of_outputs>
156 &coefficients() const {
157 return *coefficients_[plant_index_];
158 }
159
160 int plant_index() const { return plant_index_; }
161 void set_plant_index(int plant_index) {
162 if (plant_index < 0) {
163 plant_index_ = 0;
164 } else if (plant_index >= static_cast<int>(coefficients_.size())) {
Brian Silvermanb8cd6892013-03-17 23:36:24 -0700165 plant_index_ = static_cast<int>(coefficients_.size()) - 1;
Austin Schuhe3490622013-03-13 01:24:30 -0700166 } else {
167 plant_index_ = plant_index;
168 }
169 }
170
171 void Reset() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700172 X_.setZero();
173 Y_.setZero();
174 U_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800175 }
176
Austin Schuh849f0032013-03-03 23:59:53 -0800177 // Assert that U is within the hardware range.
178 virtual void CheckU() {
Brian Silverman5808bcb2014-09-14 21:40:43 -0400179 for (int i = 0; i < kNumInputs; ++i) {
Brian Silvermana21c3a22014-06-12 21:49:15 -0700180 assert(U(i, 0) <= U_max(i, 0) + 0.00001);
181 assert(U(i, 0) >= U_min(i, 0) - 0.00001);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800182 }
183 }
Austin Schuh849f0032013-03-03 23:59:53 -0800184
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800185 // Computes the new X and Y given the control input.
186 void Update() {
Austin Schuh849f0032013-03-03 23:59:53 -0800187 // Powers outside of the range are more likely controller bugs than things
188 // that the plant should deal with.
189 CheckU();
Brian Silverman273d8a32014-05-10 22:19:09 -0700190 X_ = A() * X() + B() * U();
191 Y_ = C() * X() + D() * U();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800192 }
193
194 protected:
195 // these are accessible from non-templated subclasses
Austin Schuhb1cdb382013-03-01 22:53:52 -0800196 static const int kNumStates = number_of_states;
197 static const int kNumOutputs = number_of_outputs;
198 static const int kNumInputs = number_of_inputs;
Austin Schuhe3490622013-03-13 01:24:30 -0700199
200 private:
Brian Silverman273d8a32014-05-10 22:19:09 -0700201 Eigen::Matrix<double, number_of_states, 1> X_;
202 Eigen::Matrix<double, number_of_outputs, 1> Y_;
203 Eigen::Matrix<double, number_of_inputs, 1> U_;
204
205 ::std::vector<StateFeedbackPlantCoefficients<
206 number_of_states, number_of_inputs, number_of_outputs> *> coefficients_;
207
Austin Schuhe3490622013-03-13 01:24:30 -0700208 int plant_index_;
Brian Silverman0a151c92014-05-02 15:28:44 -0700209
210 DISALLOW_COPY_AND_ASSIGN(StateFeedbackPlant);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800211};
212
Austin Schuh9644e1c2013-03-12 00:40:36 -0700213// A Controller is a structure which holds a plant and the K and L matrices.
214// This is designed such that multiple controllers can share one set of state to
215// support gain scheduling easily.
216template <int number_of_states, int number_of_inputs, int number_of_outputs>
Brian Silverman273d8a32014-05-10 22:19:09 -0700217struct StateFeedbackController final {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700218 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
Brian Silverman273d8a32014-05-10 22:19:09 -0700219
Austin Schuh9644e1c2013-03-12 00:40:36 -0700220 const Eigen::Matrix<double, number_of_states, number_of_outputs> L;
Brian Silverman5808bcb2014-09-14 21:40:43 -0400221 const Eigen::Matrix<double, number_of_inputs, number_of_states> K;
Austin Schuhe3490622013-03-13 01:24:30 -0700222 StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
223 number_of_outputs> plant;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700224
225 StateFeedbackController(
226 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L,
Brian Silverman5808bcb2014-09-14 21:40:43 -0400227 const Eigen::Matrix<double, number_of_inputs, number_of_states> &K,
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),
232 plant(plant) {
233 }
234};
235
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800236template <int number_of_states, int number_of_inputs, int number_of_outputs>
237class StateFeedbackLoop {
238 public:
239 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
240
Brian Silverman0a151c92014-05-02 15:28:44 -0700241 StateFeedbackLoop(const StateFeedbackController<
242 number_of_states, number_of_inputs, number_of_outputs> &controller)
243 : controller_index_(0) {
244 controllers_.push_back(new StateFeedbackController<
245 number_of_states, number_of_inputs, number_of_outputs>(controller));
246 Reset();
247 }
248
Brian Silverman0a151c92014-05-02 15:28:44 -0700249 StateFeedbackLoop(
250 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L,
Brian Silverman5808bcb2014-09-14 21:40:43 -0400251 const Eigen::Matrix<double, number_of_inputs, number_of_states> &K,
Brian Silverman0a151c92014-05-02 15:28:44 -0700252 const StateFeedbackPlantCoefficients<number_of_states, number_of_inputs,
253 number_of_outputs> &plant)
254 : controller_index_(0) {
255 controllers_.push_back(
256 new StateFeedbackController<number_of_states, number_of_inputs,
257 number_of_outputs>(L, K, plant));
258
259 Reset();
260 }
261
Brian Silverman273d8a32014-05-10 22:19:09 -0700262 StateFeedbackLoop(const ::std::vector<StateFeedbackController<
263 number_of_states, number_of_inputs, number_of_outputs> *> &controllers)
264 : controllers_(controllers), controller_index_(0) {
265 Reset();
266 }
267
268 StateFeedbackLoop(StateFeedbackLoop &&other) {
269 X_hat_.swap(other.X_hat_);
270 R_.swap(other.R_);
271 U_.swap(other.U_);
272 U_uncapped_.swap(other.U_uncapped_);
273 ::std::swap(controllers_, other.controllers_);
274 Y_.swap(other.Y_);
275 new_y_ = other.new_y_;
276 controller_index_ = other.controller_index_;
277 }
278
Brian Silverman0a151c92014-05-02 15:28:44 -0700279 virtual ~StateFeedbackLoop() {
280 for (auto c : controllers_) {
281 delete c;
282 }
283 }
284
Austin Schuh9644e1c2013-03-12 00:40:36 -0700285 const Eigen::Matrix<double, number_of_states, number_of_states> &A() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700286 return controller().plant.A();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700287 }
288 double A(int i, int j) const { return A()(i, j); }
289 const Eigen::Matrix<double, number_of_states, number_of_inputs> &B() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700290 return controller().plant.B();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700291 }
292 double B(int i, int j) const { return B()(i, j); }
293 const Eigen::Matrix<double, number_of_outputs, number_of_states> &C() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700294 return controller().plant.C();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700295 }
296 double C(int i, int j) const { return C()(i, j); }
297 const Eigen::Matrix<double, number_of_outputs, number_of_inputs> &D() const {
Brian Silverman273d8a32014-05-10 22:19:09 -0700298 return controller().plant.D();
Austin Schuh9644e1c2013-03-12 00:40:36 -0700299 }
300 double D(int i, int j) const { return D()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700301 const Eigen::Matrix<double, number_of_inputs, 1> &U_min() const {
302 return controller().plant.U_min();
303 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700304 double U_min(int i, int j) const { return U_min()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700305 const Eigen::Matrix<double, number_of_inputs, 1> &U_max() const {
306 return controller().plant.U_max();
307 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700308 double U_max(int i, int j) const { return U_max()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700309
Brian Silverman5808bcb2014-09-14 21:40:43 -0400310 const Eigen::Matrix<double, number_of_inputs, number_of_states> &K() const {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700311 return controller().K;
312 }
313 double K(int i, int j) const { return K()(i, j); }
314 const Eigen::Matrix<double, number_of_states, number_of_outputs> &L() const {
315 return controller().L;
316 }
317 double L(int i, int j) const { return L()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700318
319 const Eigen::Matrix<double, number_of_states, 1> &X_hat() const {
320 return X_hat_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700321 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700322 double X_hat(int i, int j) const { return X_hat()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700323 const Eigen::Matrix<double, number_of_states, 1> &R() const { return R_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700324 double R(int i, int j) const { return R()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700325 const Eigen::Matrix<double, number_of_inputs, 1> &U() const { return U_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700326 double U(int i, int j) const { return U()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700327 const Eigen::Matrix<double, number_of_inputs, 1> &U_uncapped() const {
328 return U_uncapped_;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700329 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700330 double U_uncapped(int i, int j) const { return U_uncapped()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700331 const Eigen::Matrix<double, number_of_outputs, 1> &Y() const { return Y_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700332 double Y(int i, int j) const { return Y()(i, j); }
Brian Silverman273d8a32014-05-10 22:19:09 -0700333
Brian Silverman0ca790b2014-06-12 21:33:08 -0700334 Eigen::Matrix<double, number_of_states, 1> &mutable_X_hat() { return X_hat_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700335 double &mutable_X_hat(int i, int j) { return mutable_X_hat()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700336 Eigen::Matrix<double, number_of_states, 1> &mutable_R() { return R_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700337 double &mutable_R(int i, int j) { return mutable_R()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700338 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U() { return U_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700339 double &mutable_U(int i, int j) { return mutable_U()(i, j); }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700340 Eigen::Matrix<double, number_of_inputs, 1> &mutable_U_uncapped() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700341 return U_uncapped_;
342 }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700343 double &mutable_U_uncapped(int i, int j) {
344 return mutable_U_uncapped()(i, j);
345 }
Brian Silverman0ca790b2014-06-12 21:33:08 -0700346 Eigen::Matrix<double, number_of_outputs, 1> &mutable_Y() { return Y_; }
Brian Silvermana21c3a22014-06-12 21:49:15 -0700347 double &mutable_Y(int i, int j) { return mutable_Y()(i, j); }
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800348
Brian Silverman2c590c32013-11-04 18:08:54 -0800349 const StateFeedbackController<number_of_states, number_of_inputs,
350 number_of_outputs> &controller() const {
Austin Schuhe3490622013-03-13 01:24:30 -0700351 return *controllers_[controller_index_];
Austin Schuh9644e1c2013-03-12 00:40:36 -0700352 }
353
Brian Silverman2c590c32013-11-04 18:08:54 -0800354 const StateFeedbackController<number_of_states, number_of_inputs,
355 number_of_outputs> &controller(
356 int index) const {
Austin Schuh2054f5f2013-10-27 14:54:10 -0700357 return *controllers_[index];
358 }
359
Austin Schuh9644e1c2013-03-12 00:40:36 -0700360 void Reset() {
Brian Silverman273d8a32014-05-10 22:19:09 -0700361 X_hat_.setZero();
362 R_.setZero();
363 U_.setZero();
364 U_uncapped_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800365 }
366
367 // If U is outside the hardware range, limit it before the plant tries to use
368 // it.
369 virtual void CapU() {
Brian Silverman5808bcb2014-09-14 21:40:43 -0400370 for (int i = 0; i < kNumInputs; ++i) {
Brian Silvermana21c3a22014-06-12 21:49:15 -0700371 if (U(i, 0) > U_max(i, 0)) {
372 U_(i, 0) = U_max(i, 0);
373 } else if (U(i, 0) < U_min(i, 0)) {
374 U_(i, 0) = U_min(i, 0);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800375 }
376 }
377 }
378
Austin Schuhf9286cd2014-02-11 00:51:09 -0800379 // Corrects X_hat given the observation in Y.
380 void Correct(const Eigen::Matrix<double, number_of_outputs, 1> &Y) {
Austin Schuhcda86af2014-02-16 16:16:39 -0800381 /*
382 auto eye =
383 Eigen::Matrix<double, number_of_states, number_of_states>::Identity();
384 //LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
385 ::std::cout << "Identity " << eye << ::std::endl;
386 ::std::cout << "X_hat " << X_hat << ::std::endl;
387 ::std::cout << "LC " << L() * C() << ::std::endl;
388 ::std::cout << "L " << L() << ::std::endl;
389 ::std::cout << "C " << C() << ::std::endl;
390 ::std::cout << "y " << Y << ::std::endl;
391 ::std::cout << "z " << (Y - C() * X_hat) << ::std::endl;
392 ::std::cout << "correction " << L() * (Y - C() * X_hat) << ::std::endl;
393 X_hat = (eye - L() * C()) * X_hat + L() * Y;
394 ::std::cout << "X_hat after " << X_hat << ::std::endl;
395 ::std::cout << ::std::endl;
396 */
397 //LOG(DEBUG, "X_hat(2, 0) = %f\n", X_hat(2, 0));
Austin Schuhf9286cd2014-02-11 00:51:09 -0800398 Y_ = Y;
399 new_y_ = true;
400 }
401
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800402 // stop_motors is whether or not to output all 0s.
Austin Schuhf9286cd2014-02-11 00:51:09 -0800403 void Update(bool stop_motors) {
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800404 if (stop_motors) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700405 U_.setZero();
406 U_uncapped_.setZero();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800407 } else {
Brian Silverman273d8a32014-05-10 22:19:09 -0700408 U_ = U_uncapped_ = K() * (R() - X_hat());
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800409 CapU();
410 }
411
Ben Fredrickson890c3fe2014-03-02 00:15:16 +0000412 UpdateObserver();
413 }
414
415 void UpdateObserver() {
Austin Schuhf9286cd2014-02-11 00:51:09 -0800416 if (new_y_) {
Brian Silverman273d8a32014-05-10 22:19:09 -0700417 X_hat_ = (A() - L() * C()) * X_hat() + L() * Y() + B() * U();
Austin Schuhf9286cd2014-02-11 00:51:09 -0800418 new_y_ = false;
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800419 } else {
Brian Silverman273d8a32014-05-10 22:19:09 -0700420 X_hat_ = A() * X_hat() + B() * U();
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800421 }
422 }
423
Brian Silverman273d8a32014-05-10 22:19:09 -0700424 // Sets the current controller to be index, clamped to be within range.
Austin Schuh9644e1c2013-03-12 00:40:36 -0700425 void set_controller_index(int index) {
Austin Schuhe3490622013-03-13 01:24:30 -0700426 if (index < 0) {
427 controller_index_ = 0;
428 } else if (index >= static_cast<int>(controllers_.size())) {
Brian Silvermanb8cd6892013-03-17 23:36:24 -0700429 controller_index_ = static_cast<int>(controllers_.size()) - 1;
Austin Schuhe3490622013-03-13 01:24:30 -0700430 } else {
Austin Schuh9644e1c2013-03-12 00:40:36 -0700431 controller_index_ = index;
432 }
433 }
434
Austin Schuhd34569d2014-02-18 20:26:38 -0800435 int controller_index() const { return controller_index_; }
Austin Schuh9644e1c2013-03-12 00:40:36 -0700436
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800437 protected:
Austin Schuh2054f5f2013-10-27 14:54:10 -0700438 ::std::vector<StateFeedbackController<number_of_states, number_of_inputs,
439 number_of_outputs> *> controllers_;
440
Brian Silverman273d8a32014-05-10 22:19:09 -0700441 // These are accessible from non-templated subclasses.
Austin Schuhb1cdb382013-03-01 22:53:52 -0800442 static const int kNumStates = number_of_states;
443 static const int kNumOutputs = number_of_outputs;
444 static const int kNumInputs = number_of_inputs;
Austin Schuh9644e1c2013-03-12 00:40:36 -0700445
Brian Silverman273d8a32014-05-10 22:19:09 -0700446 private:
447 Eigen::Matrix<double, number_of_states, 1> X_hat_;
448 Eigen::Matrix<double, number_of_states, 1> R_;
449 Eigen::Matrix<double, number_of_inputs, 1> U_;
450 Eigen::Matrix<double, number_of_inputs, 1> U_uncapped_;
451
Austin Schuhf9286cd2014-02-11 00:51:09 -0800452 // Temporary storage for a measurement until I can figure out why I can't
453 // correct when the measurement is made.
454 Eigen::Matrix<double, number_of_outputs, 1> Y_;
455 bool new_y_ = false;
456
Austin Schuh9644e1c2013-03-12 00:40:36 -0700457 int controller_index_;
Brian Silverman0a151c92014-05-02 15:28:44 -0700458
Brian Silverman0a151c92014-05-02 15:28:44 -0700459 DISALLOW_COPY_AND_ASSIGN(StateFeedbackLoop);
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800460};
461
Brian Silverman273d8a32014-05-10 22:19:09 -0700462#endif // FRC971_CONTROL_LOOPS_STATE_FEEDBACK_LOOP_H_