9#include <Eigen/Cholesky>
42 return "Q was not symmetric.";
44 return "Q was not positive semidefinite.";
46 return "R was not symmetric.";
48 return "R was not positive definite.";
50 return "(A, B) pair was not stabilizable.";
52 return "(A, C) pair where Q = CᵀC was not detectable.";
84template <
int States,
int Inputs>
85Eigen::Matrix<double, States, States>
DARE(
86 const Eigen::Matrix<double, States, States>& A,
87 const Eigen::Matrix<double, States, Inputs>& B,
88 const Eigen::Matrix<double, States, States>& Q,
89 const Eigen::LLT<Eigen::Matrix<double, Inputs, Inputs>>& R_llt) {
90 using StateMatrix = Eigen::Matrix<double, States, States>;
103 StateMatrix G_k = B * R_llt.solve(B.transpose());
105 StateMatrix H_k1 = Q;
111 StateMatrix W = StateMatrix::Identity(H_k.rows(), H_k.cols()) + G_k * H_k;
113 auto W_solver = W.lu();
116 StateMatrix V_1 = W_solver.solve(A_k);
135 StateMatrix V_2 = W_solver.solve(G_k);
140 G_k += A_k * V_2 * A_k.transpose();
141 H_k1 = H_k + V_1.transpose() * H_k * A_k;
145 }
while ((H_k1 - H_k).norm() > 1e-10 * H_k1.norm());
168template <
int States,
int Inputs>
170 const Eigen::Matrix<double, States, States>& A,
171 const Eigen::Matrix<double, States, Inputs>& B,
172 const Eigen::Matrix<double, States, States>& Q,
173 const Eigen::Matrix<double, Inputs, Inputs>& R,
174 bool checkPreconditions =
true) {
175 if (checkPreconditions) {
177 if ((R - R.transpose()).norm() > 1e-10) {
183 auto R_llt = R.llt();
184 if (R_llt.info() != Eigen::Success) {
188 if (checkPreconditions) {
190 if ((Q - Q.transpose()).norm() > 1e-10) {
203 auto Q_ldlt = Q.ldlt();
204 if (Q_ldlt.info() != Eigen::Success ||
205 (Q_ldlt.vectorD().array() < 0.0).any()) {
218 Eigen::Matrix<double, States, States> C =
219 Q_ldlt.vectorD().cwiseSqrt().asDiagonal() *
220 Eigen::Matrix<double, States, States>{Q_ldlt.matrixL().transpose()} *
221 Q_ldlt.transpositionsP();
283template <
int States,
int Inputs>
285 const Eigen::Matrix<double, States, States>& A,
286 const Eigen::Matrix<double, States, Inputs>& B,
287 const Eigen::Matrix<double, States, States>& Q,
288 const Eigen::Matrix<double, Inputs, Inputs>& R,
289 const Eigen::Matrix<double, States, Inputs>& N,
290 bool checkPreconditions =
true) {
291 if (checkPreconditions) {
293 if ((R - R.transpose()).norm() > 1e-10) {
299 auto R_llt = R.llt();
300 if (R_llt.info() != Eigen::Success) {
315 Eigen::Matrix<double, States, States> A_2 =
316 A - B * R_llt.solve(N.transpose());
317 Eigen::Matrix<double, States, States> Q_2 =
318 Q - N * R_llt.solve(N.transpose());
320 if (checkPreconditions) {
322 if ((Q_2 - Q_2.transpose()).norm() > 1e-10) {
335 auto Q_ldlt = Q_2.ldlt();
336 if (Q_ldlt.info() != Eigen::Success ||
337 (Q_ldlt.vectorD().array() < 0.0).any()) {
350 Eigen::Matrix<double, States, States> C =
351 Q_ldlt.vectorD().cwiseSqrt().asDiagonal() *
352 Eigen::Matrix<double, States, States>{Q_ldlt.matrixL().transpose()} *
353 Q_ldlt.transpositionsP();
An expected<T, E> object is an object that contains the storage for another object and manages the li...
Definition expected:1250
Converts a string literal into a format string that will be parsed at compile time and converted into...
Definition printf.h:50
Eigen::Matrix< double, States, States > DARE(const Eigen::Matrix< double, States, States > &A, const Eigen::Matrix< double, States, Inputs > &B, const Eigen::Matrix< double, States, States > &Q, const Eigen::LLT< Eigen::Matrix< double, Inputs, Inputs > > &R_llt)
Computes the unique stabilizing solution X to the discrete-time algebraic Riccati equation:
Definition DARE.h:85
Definition SystemServer.h:9
bool IsStabilizable(const Matrixd< States, States > &A, const Matrixd< States, Inputs > &B)
Returns true if (A, B) is a stabilizable pair.
Definition StateSpaceUtil.h:292
wpi::expected< Eigen::Matrix< double, States, States >, DAREError > DARE(const Eigen::Matrix< double, States, States > &A, const Eigen::Matrix< double, States, Inputs > &B, const Eigen::Matrix< double, States, States > &Q, const Eigen::Matrix< double, Inputs, Inputs > &R, bool checkPreconditions=true)
Computes the unique stabilizing solution X to the discrete-time algebraic Riccati equation:
Definition DARE.h:169
constexpr std::string_view to_string(const DAREError &error)
Converts the given DAREError enum to a string.
Definition DARE.h:39
DAREError
Errors the DARE solver can encounter.
Definition DARE.h:21
@ QNotPositiveSemidefinite
Q was not positive semidefinite.
@ RNotSymmetric
R was not symmetric.
@ QNotSymmetric
Q was not symmetric.
@ ACNotDetectable
(A, C) pair where Q = CᵀC was not detectable.
@ RNotPositiveDefinite
R was not positive definite.
@ ABNotStabilizable
(A, B) pair was not stabilizable.
bool IsDetectable(const Matrixd< States, States > &A, const Matrixd< Outputs, States > &C)
Returns true if (A, C) is a detectable pair.
Definition StateSpaceUtil.h:351