blob: ad37f4932693db24173bbd4a1d22327e8a061d01 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#ifndef FRC971_CONTROL_LOOPS_STATEFEEDBACKLOOP_H_
2#define FRC971_CONTROL_LOOPS_STATEFEEDBACKLOOP_H_
3
4// wikipedia article is <http://en.wikipedia.org/wiki/State_observer>
5
6#include "Eigen/Dense"
7
8template <int number_of_states, int number_of_outputs>
9class StateFeedbackPlant {
10 public:
11 Eigen::Matrix<double, number_of_states, 1> X;
12 Eigen::Matrix<double, number_of_outputs, 1> Y;
13 Eigen::Matrix<double, number_of_outputs, 1> U;
14 Eigen::Matrix<double, number_of_outputs, 1> U_max;
15 Eigen::Matrix<double, number_of_outputs, 1> U_min;
16 Eigen::Matrix<double, number_of_states, number_of_states> A;
17 Eigen::Matrix<double, number_of_states, number_of_outputs> B;
18 Eigen::Matrix<double, number_of_outputs, number_of_states> C;
19 Eigen::Matrix<double, number_of_outputs, number_of_outputs> D;
20 // TODO(aschuh): These following 2 lines are here because MATRIX_INIT
21 // assumes that you have a controller as well as a plant.
22 Eigen::Matrix<double, number_of_states, number_of_outputs> L;
23 Eigen::Matrix<double, number_of_outputs, number_of_states> K;
24
25 StateFeedbackPlant() {
26 X.setZero();
27 Y.setZero();
28 U.setZero();
29 }
30
31 virtual ~StateFeedbackPlant() {}
32
33 // If U is outside the hardware range, limit it before the plant tries to use
34 // it.
35 virtual void CapU() {
36 for (int i = 0; i < number_of_outputs; ++i) {
37 if (U[i] > U_max[i]) {
38 U[i] = U_max[i];
39 } else if (U[i] < U_min[i]) {
40 U[i] = U_min[i];
41 }
42 }
43 }
44 // Computes the new X and Y given the control input.
45 void Update() {
46 CapU();
47 X = A * X + B * U;
48 Y = C * X + D * U;
49 }
50
51 protected:
52 // these are accessible from non-templated subclasses
53 static const int number_of_states_var = number_of_states;
54 static const int number_of_outputs_var = number_of_outputs;
55};
56
57template <int number_of_states, int number_of_outputs>
58class StateFeedbackLoop {
59 public:
60 Eigen::Matrix<double, number_of_states, 1> X;
61 Eigen::Matrix<double, number_of_states, 1> X_hat;
62 Eigen::Matrix<double, number_of_outputs, 1> Y;
63 Eigen::Matrix<double, number_of_states, 1> R;
64 Eigen::Matrix<double, number_of_outputs, 1> U;
65 Eigen::Matrix<double, number_of_outputs, 1> U_max;
66 Eigen::Matrix<double, number_of_outputs, 1> U_min;
67 Eigen::Matrix<double, number_of_outputs, 1> U_ff;
68 Eigen::Matrix<double, number_of_states, number_of_states> A;
69 Eigen::Matrix<double, number_of_states, number_of_outputs> B;
70 // K in wikipedia article
71 Eigen::Matrix<double, number_of_outputs, number_of_states> C;
72 Eigen::Matrix<double, number_of_outputs, number_of_outputs> D;
73 // B in wikipedia article
74 Eigen::Matrix<double, number_of_states, number_of_outputs> L;
75 // C in wikipedia article
76 Eigen::Matrix<double, number_of_outputs, number_of_states> K;
77
78 StateFeedbackLoop() {
79 // You have to initialize all the matrices to 0 or else all their elements
80 // are undefined.
81 X.setZero();
82 X_hat.setZero();
83 Y.setZero();
84 R.setZero();
85 U.setZero();
86 U_ff.setZero();
87 }
88 virtual ~StateFeedbackLoop() {}
89
90 virtual void FeedForward() {
91 for (int i = 0; i < number_of_outputs; ++i) {
92 U_ff[i] = 0.0;
93 }
94 }
95 // If U is outside the hardware range, limit it before it
96 // gets added to the observer.
97 virtual void CapU() {
98 for (int i = 0; i < number_of_outputs; ++i) {
99 if (U[i] > U_max[i]) {
100 U[i] = U_max[i];
101 } else if (U[i] < U_min[i]) {
102 U[i] = U_min[i];
103 }
104 }
105 }
106 // update_observer is whether or not to use the values in Y.
107 // stop_motors is whether or not to output all 0s.
108 void Update(bool update_observer, bool stop_motors) {
109 if (stop_motors) {
110 for (int i = 0; i < number_of_outputs; ++i) {
111 U[i] = 0.0;
112 }
113 } else {
114 // new power = constant * (goal - current prediction)
115 U.noalias() = K * (R - X_hat);
116 CapU();
117 }
118
119 if (update_observer) {
120 X_hat = (A - L * C) * X_hat + L * Y + B * U;
121 } else {
122 X_hat = A * X_hat + B * U;
123 }
124 }
125
126 protected:
127 // these are accessible from non-templated subclasses
128 static const int number_of_states_var = number_of_states;
129 static const int number_of_outputs_var = number_of_outputs;
130};
131#endif // FRC971_CONTROL_LOOPS_STATEFEEDBACKLOOP_H_