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