RIT VEXU Core API
Toggle main menu visibility
Loading...
Searching...
No Matches
dare_solver.h
1
#pragma once
2
3
#include "core/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
/*
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
}
include
core
math
systems
dare_solver.h
Generated by
1.18.0