Brick
Loading...
Searching...
No Matches
linear_quadratic_regulator.h
Go to the documentation of this file.
1/**
2 * @file linear_quadratic_regulator.h
3 * @brief A control loop that uses current states, reference states, and cost matrices to find an
4 * optimal gain matrix as an output.
5 *
6 * This is a conventional Linear Quadratic Regulator that uses the Feedback class as an interface.
7 * It calculates the optimal gain matrix using cost matrices, the current states, and the reference
8 * states
9 */
10
11#pragma once
12
13#include "../vendor/eigen/unsupported/Eigen/MatrixFunctions"
15#include "core/math/eigen_interface.h"
16#include "core/math/systems/dare_solver.h"
17#include "core/math/systems/discretization.h"
18#include "core/math/systems/linear_system.h"
19
20using namespace units::literals;
21
22/**
23 * Forms a cost matrix from a set of tolerances for each variable using Bryson's
24 * Rule.
25 *
26 * Q = 1 / tol²
27 *
28 * @tparam DIM The dimensions of the cost matrix.
29 * @param tolerances Vector containing the tolerances for each variable.
30 *
31 * @return The cost matrix.
32 */
33template <int DIM>
34EMat<DIM, DIM> cost_matrix(const EVec<DIM>& tolerances) {
35 EMat<DIM, DIM> Q = EMat<DIM, DIM>::Zero();
36 for (int i = 0; i < DIM; i++) {
37 Q(i, i) = 1.0 / (tolerances(i) * tolerances(i));
38 }
39 return Q;
40}
41
42/**
43 * Class implements an LQR controller. This finds the optimal gain matrix K
44 * where:
45 *
46 * u = K(r - x)
47 *
48 * K is optimized to minimize a cost function:
49 *
50 * ∞
51 * J = ∑ xₖᵀQxₖ + uₖᵀRuₖ
52 * k=0
53 *
54 * Where Q and R are the state and control cost matrices.
55 *
56 * @tparam STATES The number of states in the system.
57 * @tparam INPUTS The number of inputs to the system.
58 */
59template <int STATES, int INPUTS>
60class LinearQuadraticRegulator : public Feedback<EVec<STATES>, EVec<INPUTS>> {
61 public:
62 // Definitions to shorten some lines.
63 using MatrixA = EMat<STATES, STATES>;
64 using MatrixB = EMat<STATES, INPUTS>;
65 using VectorX = EVec<STATES>;
66 using VectorU = EVec<INPUTS>;
67
68 /**
69 * Constructs an LQR given a plant, a vector of tolerances for the states and inputs, and the
70 * timestep in seconds.
71 *
72 * @tparam OUTPUTS The number of outputs of the plant.
73 * @param plant The linear system to control.
74 * @param Qtolerances A vector of tolerances for each state.
75 * @param Rtolerances A vector of tolerances for each input.
76 */
77 template <int OUTPUTS>
79 const VectorU& Rtolerances, const units::Time& dt)
80 : LinearQuadraticRegulator(plant.A(), plant.B(), Qtolerances, Rtolerances, dt) {}
81
82 /**
83 * Constructs an LQR given state and input matrices, a vector of tolerances for the states and
84 * inputs, and the timestep in seconds.
85 *
86 * @param A The state matrix of the linear system.
87 * @param B The input matrix of the linear system.
88 * @param Qtolerances A vector of tolerances for each state.
89 * @param Rtolerances A vector of tolerances for each input.
90 */
91 LinearQuadraticRegulator(const MatrixA& A, const MatrixB& B, const VectorX& Qtolerances,
92 const VectorU& Rtolerances, const units::Time& dt)
93 : LinearQuadraticRegulator(A, B, cost_matrix(Qtolerances), cost_matrix(Rtolerances), dt) {}
94
95 /**
96 * Constructs an LQR given state and input matrices, the cost matrices of states and inputs, and
97 * the timestep in seconds.
98 *
99 * @param A The state matrix of the linear system.
100 * @param B The input matrix of the linear system.
101 * @param Q The cost matrix of the states.
102 * @param R The cost matrix of the inputs.
103 */
104 LinearQuadraticRegulator(const MatrixA& A, const MatrixB& B, const EMat<STATES, STATES>& Q,
105 const EMat<INPUTS, INPUTS>& R, const units::Time& dt) {
106 constexpr auto [Ad, Bd] = discretize_AB(A, B, dt);
107
108 constexpr MatrixA S = DARE<STATES, INPUTS>(Ad, Bd, Q, R);
109
110 // (BᵀSD + R) \ (BᵀSA)
111 K_ = (Bd.transpose() * S * Bd + R).llt().solve(Bd.transpose() * S * Ad);
112 }
113
114 /// Resets the internal state of the LQR
115 void reset() override {
116 this->state_ = VectorX();
117 this->reference_ = VectorX();
118 this->output_ = VectorU();
119 }
120
121 /**
122 * Computes the control input u as:
123 *
124 * u = K(r - x)
125 *
126 * @param x The current state.
127 * @param r The reference state.
128 * @param dt the timestep since the last time this method was called
129 */
130 VectorU update(const VectorX& x, const VectorX& r, const units::Time& dt = 10_ms) override {
131 this->state_ = x;
132 this->reference_ = r;
133 this->output_ = K_ * (this->reference_ - this->state_);
134 return this->output_;
135 }
136
137 /**
138 * Recomputes K to work for a time delayed state.
139 *
140 * Kdelay = K(A - BK)^(delay / dt)
141 *
142 * @tparam OUTPUTS The number of outputs of the plant
143 * @param plant The linear system.
144 * @param dt The timestep in seconds.
145 * @param input_delay The time delay of the system.
146 */
147 template <int OUTPUTS>
149 const units::Time& input_delay) {
150 constexpr auto [Ad, Bd] = discretize_AB(plant.A(), plant.B(), dt);
151
152 // Kdelay = K(A - BK)^(delay / dt)
153 K_ = K_ * (Ad - Bd * K_).pow(input_delay / dt);
154 }
155
156 private:
157 EMat<INPUTS, STATES> K_;
158};
pure virtual class for generic feedback control loops.
Definition feedback.h:21
void latency_compensate(LinearSystem< STATES, INPUTS, OUTPUTS > &plant, const units::Time &dt, const units::Time &input_delay)
Definition linear_quadratic_regulator.h:148
void reset() override
Resets the internal state of the LQR.
Definition linear_quadratic_regulator.h:115
VectorU update(const VectorX &x, const VectorX &r, const units::Time &dt=10_ms) override
Definition linear_quadratic_regulator.h:130
LinearQuadraticRegulator(LinearSystem< STATES, INPUTS, OUTPUTS > &plant, const VectorX &Qtolerances, const VectorU &Rtolerances, const units::Time &dt)
Definition linear_quadratic_regulator.h:78
LinearQuadraticRegulator(const MatrixA &A, const MatrixB &B, const VectorX &Qtolerances, const VectorU &Rtolerances, const units::Time &dt)
Definition linear_quadratic_regulator.h:91
LinearQuadraticRegulator(const MatrixA &A, const MatrixB &B, const EMat< STATES, STATES > &Q, const EMat< INPUTS, INPUTS > &R, const units::Time &dt)
Definition linear_quadratic_regulator.h:104
Definition linear_system.h:16
MatrixB B()
Returns the continuous input matrix B.
Definition linear_system.h:42
MatrixA A()
Returns the continuous system matrix A.
Definition linear_system.h:39
A pure virual class to function as an interface for all feedback control loops.
EMat< DIM, DIM > cost_matrix(const EVec< DIM > &tolerances)
Definition linear_quadratic_regulator.h:34
Definition units.h:691