RIT VEXU Core API
Loading...
Searching...
No Matches
dare_solver.h
1#pragma once
2
3#include "core/math/eigen_interface.h"
4
36template <int STATES, int INPUTS>
37EMat<STATES, STATES> DARE(
38 const EMat<STATES, STATES> &A, const EMat<STATES, INPUTS> &B, const EMat<STATES, STATES> &Q,
39 const EMat<INPUTS, INPUTS> &R
40) {
41 const Eigen::LLT<EMat<INPUTS, INPUTS>> R_llt = R.llt();
42 using StateMatrix = EMat<STATES, STATES>;
43
44 /*
45 * Implements SDA algorithm on p. 5 of [1] (initial A, G, H are from (4)).
46 *
47 * [1] E. K.-W. Chu, H.-Y. Fan, W.-W. Lin & C.-S. Wang "Structure-Preserving
48 * Algorithms for Periodic Discrete-Time Algebraic Riccati Equations",
49 * International Journal of Control, 77:8, 767-788, 2004.
50 * DOI: 10.1080/00207170410001714988
51 *
52 * A₀ = A
53 * G₀ = BR⁻¹Bᵀ
54 * H₀ = Q
55 */
56 StateMatrix A_k = A;
57 StateMatrix G_k = B * R_llt.solve(B.transpose());
58 StateMatrix H_k;
59 StateMatrix H_k1 = Q;
60
61
62
63 do {
64 H_k = H_k1;
65
66 // W = I + GₖHₖ
67 StateMatrix W = StateMatrix::Identity(H_k.rows(), H_k.cols()) + G_k * H_k;
68
69 auto W_solver = W.lu();
70
71 // Solve WV₁ = Aₖ for V₁
72 StateMatrix V_1 = W_solver.solve(A_k);
73 /*
74 * Solve V₂Wᵀ = Gₖ for V₂
75 *
76 * We want to put V₂Wᵀ = Gₖ into Ax = b form so we can solve it more
77 * efficiently.
78 *
79 * V₂Wᵀ = Gₖ
80 * (V₂Wᵀ)ᵀ = Gₖᵀ
81 * WV₂ᵀ = Gₖᵀ
82 *
83 * The solution of Ax = b can be found via x = A.solve(b).
84 *
85 * V₂ᵀ = W.solve(Gₖᵀ)
86 * V₂ = W.solve(Gₖᵀ)ᵀ
87 */
88 StateMatrix V_2 = W_solver.solve(G_k.transpose()).transpose();
89 /*
90 * Gₖ₊₁ = Gₖ + AₖV₂Aₖᵀ
91 * Hₖ₊₁ = Hₖ + V₁ᵀHₖAₖ
92 * Aₖ₊₁ = AₖV₁
93 */
94 G_k += A_k * V_2 * A_k.transpose();
95 H_k1 = H_k + V_1.transpose() * H_k * A_k;
96 A_k *= V_1;
97
98
99 // while |Hₖ₊₁ − Hₖ| > ε |Hₖ₊₁|
100 } while ((H_k1 - H_k).norm() > 1e-10 * H_k1.norm());
101
102 return H_k1;
103}