test_algebraic_riccati_discrete.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement
4  *
5  * Copyright (c) 2020,
6  * TU Dortmund - Institute of Control Theory and Systems Engineering.
7  * All rights reserved.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  *
22  * Authors: Christoph Rösmann
23  *********************************************************************/
24 
26 
27 #include <corbo-core/macros.h>
28 
29 #include "gtest/gtest.h"
30 
32 
33 class TestAlgebraicRiccatiDiscrete : public testing::Test
34 {
35  protected:
36  // You can do set-up work for each test here.
38  // You can do clean-up work that doesn't throw exceptions here.
40  // If the constructor and destructor are not enough for setting up
41  // and cleaning up each test, you can define the following methods:
42 
43  // Code here will be called immediately after the constructor (right
44  // before each test).
45  // virtual void SetUp() {}
46  // Code here will be called immediately after each test (right
47  // before the destructor).
48  // virtual void TearDown();
49 };
50 
51 TEST_F(TestAlgebraicRiccatiDiscrete, solve_feasible_2d_stable_real)
52 {
53  Eigen::Matrix2d A;
54  A << -0.05, 0.05, 1, 0; // only real eigenvalues (all stable)
55 
56  Eigen::Vector2d B;
57  B << 1, 0;
58 
60  C << 0, 1;
61 
62  Eigen::MatrixXd Q = C.transpose() * C;
63  Eigen::MatrixXd R(1, 1);
64  R << 1;
65 
66  Eigen::MatrixXd X;
67  Eigen::MatrixXd G;
68  bool solve_success = AlgebraicRiccatiDiscrete::solve(A, B, Q, R, X, &G);
69  EXPECT_TRUE(solve_success);
70 
71  Eigen::Matrix2d X_sol;
72  X_sol << 1.0026, -0.0013, -0.0013, 1.0013;
73  EXPECT_EQ_MATRIX(X, X_sol, 1e-4);
74 
75  // check gain matrix
76  Eigen::MatrixXd G_sol(1, 2);
77  G_sol << -0.025673043427904, 0.025032039904055;
78  EXPECT_EQ_MATRIX(G, G_sol, 1e-4);
79 
80  // check closed-loop stability
81  EXPECT_TRUE(AlgebraicRiccatiDiscrete::isClosedLoopStable(A, B, G));
82 }
83 
84 TEST_F(TestAlgebraicRiccatiDiscrete, solve_feasible_4d_stableA_complex)
85 {
86  Eigen::Matrix4d A;
87  A << -0.05, -0.2, -0.0125, 0.0125, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0; // a complex pair of eigenvalues (all eigenvalues stable)
88 
89  Eigen::Vector4d B;
90  B << 1, 0, 0, 0;
91 
93  C << 0, 0, 0, 1;
94 
95  Eigen::MatrixXd Q = C.transpose() * C;
96 
97  Eigen::MatrixXd R(1, 1);
98  R << 2;
99 
100  Eigen::MatrixXd X;
101  Eigen::MatrixXd G;
102  bool solve_success = AlgebraicRiccatiDiscrete::solve(A, B, Q, R, X, &G);
103  EXPECT_TRUE(solve_success);
104 
105  Eigen::Matrix4d X_sol;
106  X_sol << 1.0289, 0.0075, -0.0013, -0.0004, 0.0075, 1.0277, 0.0016, -0.0017, -0.0013, 0.0016, 1.0002, -0.0001, -0.0004, -0.0017, -0.0001, 1.0001;
107  EXPECT_EQ_MATRIX(X, X_sol, 1e-4);
108 
109  // check gain matrix
110  Eigen::MatrixXd G_sol(1, 4);
111  G_sol << -0.014509214644181, -0.068380590003095, -0.004366017750237, 0.004246262501251;
112  EXPECT_EQ_MATRIX(G, G_sol, 1e-4);
113 
114  // check closed-loop stability
115  EXPECT_TRUE(AlgebraicRiccatiDiscrete::isClosedLoopStable(A, B, G));
116 }
117 
118 TEST_F(TestAlgebraicRiccatiDiscrete, solve_feasible_4d_unstableA_complex)
119 {
120  Eigen::Matrix4d A;
121  A << -1.5, -1.32, 3.742, 2.076, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0; // a complex pair of eigenvalues (some eigenvalues unstable)
122 
123  Eigen::Vector4d B;
124  B << 1, 0, 0, 0;
125 
127  C << 0, 0, 0, 1;
128 
129  Eigen::MatrixXd Q = C.transpose() * C;
130 
131  Eigen::MatrixXd R(1, 1);
132  R << 2;
133 
134  Eigen::MatrixXd X;
135  Eigen::MatrixXd G;
136  bool solve_success = AlgebraicRiccatiDiscrete::solve(A, B, Q, R, X, &G);
137  EXPECT_TRUE(solve_success);
138 
139  Eigen::Matrix4d X_sol;
140  X_sol << 33.8189, 7.5236, -14.3996, -5.0081, 7.5236, 32.4107, 0.1086, -6.8438, -14.3996, 0.1086, 32.7867, 14.0887, -5.0081, -6.8438, 14.0887,
141  9.1383;
142  EXPECT_EQ_MATRIX(X, X_sol, 1e-4);
143 
144  // check gain matrix
145  Eigen::MatrixXd G_sol(1, 4);
146  G_sol << -1.206200888594686, -1.648306965169984, 3.393241337036358, 1.960083490678313;
147  EXPECT_EQ_MATRIX(G, G_sol, 1e-4);
148 
149  // check closed-loop stability
150  EXPECT_TRUE(AlgebraicRiccatiDiscrete::isClosedLoopStable(A, B, G));
151 }
MatrixType A(a, *n, *n, *lda)
TEST_F(TestAlgebraicRiccatiDiscrete, solve_feasible_2d_stable_real)
MatrixType B(b, *n, *nrhs, *ldb)
#define EXPECT_EQ_MATRIX(A, B, tol)
Definition: macros.h:39
#define X
Definition: icosphere.cpp:20
Methods for dealing with discrete-time algebraic Riccati equations.


control_box_rst
Author(s): Christoph Rösmann
autogenerated on Mon Feb 28 2022 22:07:52