test_lyapunov_continuous.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 TestLyapunovEquationContinuousTime : 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 
52 {
53  Eigen::Matrix2d A;
54  A << 1, 2, -3, -4;
55 
56  Eigen::Matrix2d Q;
57  Q << 3, 1, 1, 1;
58 
59  EXPECT_TRUE(LyapunovContinuous::hasUniqueSolution(A));
60 
61  Eigen::MatrixXd X;
62  bool solve_success = LyapunovContinuous::solve(A, Q, X);
63  EXPECT_TRUE(solve_success);
64 
65  Eigen::Matrix2d X_sol;
66  X_sol << 6.166666, -3.8333333, -3.8333333, 3;
67 
68  EXPECT_EQ_MATRIX(X, X_sol, 1e-5);
69 }
70 
72 {
73  Eigen::Matrix2d A;
74  A << 0, 1, -6, -5;
75 
76  A.transposeInPlace();
77 
78  Eigen::Matrix2d Q = Eigen::Matrix2d::Identity();
79 
80  EXPECT_TRUE(LyapunovContinuous::hasUniqueSolution(A));
81 
82  Eigen::MatrixXd X;
83  bool solve_success = LyapunovContinuous::solve(A, Q, X);
84  EXPECT_TRUE(solve_success);
85 
86  Eigen::Matrix2d X_sol;
87  X_sol << 67.0 / 60.0, 1.0 / 12.0, 1.0 / 12.0, 7.0 / 60.0;
88 
89  EXPECT_EQ_MATRIX(X, X_sol, 1e-5);
90 }
91 
93 {
94  Eigen::Matrix2d A;
95  A << 0, 1, -6, -5;
96 
97  Eigen::Matrix2d Q = Eigen::Matrix2d::Identity();
98 
99  EXPECT_TRUE(LyapunovContinuous::hasUniqueSolution(A));
100 
101  Eigen::MatrixXd X;
102  bool solve_success = LyapunovContinuous::solve(A, Q, X);
103  EXPECT_TRUE(solve_success);
104 
105  Eigen::Matrix2d X_sol;
106  X_sol << 0.533333, -0.5, -0.5, 0.7;
107 
108  EXPECT_EQ_MATRIX(X, X_sol, 1e-5);
109 }
110 
112 {
113  // G(s) = 1/(s+1)/(s+2)/(s+3)/(s+4)/(s+5)
114  Eigen::MatrixXd A(5, 5);
115  A << -15, -85, -225, -274, -120, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0;
116 
117  Eigen::MatrixXd Q(5, 5);
118  // Q = magic(5)/10
119  Q << 1.7, 2.4, 0.1, 0.8, 1.5, 2.3, 0.5, 0.7, 1.4, 1.6, 0.4, 0.6, 1.3, 2.0, 2.2, 1.0, 1.2, 1.9, 2.1, 0.3, 1.1, 1.8, 2.5, 0.2, 0.9;
120 
121  EXPECT_TRUE(LyapunovContinuous::hasUniqueSolution(A));
122 
123  Eigen::MatrixXd X;
124  bool solve_success = LyapunovContinuous::solve(A, Q, X);
125  EXPECT_TRUE(solve_success);
126 
127  Eigen::MatrixXd X_sol(5, 5);
128  X_sol << 489.7681, 0.0322, -35.0314, -0.7613, 6.1874, -0.5322, 34.3314, -0.6387, -7.7874, -1.1722, -34.9314, -0.6613, 5.7874, -1.0278, -3.6708,
129  -0.5387, -7.6874, -1.0722, 3.3708, -0.4565, 5.8874, -1.4278, -3.5708, -0.4435, 7.9881;
130 
131  EXPECT_EQ_MATRIX(X, X_sol, 1e-5);
132 }
133 
135 {
136  // this test differs from solve_feasible 1-4 such that
137  // the underlying Schur solver in the current implementation must be
138  // of complex type (rather than real) in order to find the correct solution.
139  Eigen::MatrixXd A(5, 5);
140  A << -2.5, -2.3, -0.95, -0.1689, -0.095, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0;
141 
142  Eigen::MatrixXd Q = Eigen::MatrixXd::Identity(5, 5);
143 
144  EXPECT_TRUE(LyapunovContinuous::hasUniqueSolution(A));
145 
146  Eigen::MatrixXd X;
147  bool solve_success = LyapunovContinuous::solve(A, Q, X);
148  EXPECT_TRUE(solve_success);
149 
150  Eigen::MatrixXd X_sol(5, 5);
151  X_sol << 1.1495, -0.5000, -0.8201, 0.5000, -5.5701, -0.5000, 0.8201, -0.5000, 5.5701, 0.5000, -0.8201, -0.5000, -5.5701, -0.5000, 85.0134, 0.5000,
152  5.5701, -0.5000, -85.0134, -0.5000, -5.5701, 0.5000, 85.0134, -0.5000, -709.5066;
153 
154  EXPECT_EQ_MATRIX(X, X_sol, 1e-5);
155 }
156 
158 {
159  Eigen::MatrixXd A = Eigen::MatrixXd::Random(5, 4);
160 
161  Eigen::Matrix2d Q;
162  Q << 3, 1, 1, 1;
163 
164  Eigen::MatrixXd X;
165 
166  // EXPECT_DEBUG_DEATH(LyapunovEquationContinuousTime::solve(A, Q, X), "[\\s\\S]*[is_square|have_equal_size][\\s\\S]*");
167  EXPECT_DEBUG_DEATH(LyapunovContinuous::solve(A, Q, X), "");
168 }
169 
171 {
172  Eigen::MatrixXd A = Eigen::MatrixXd::Random(4, 4);
173  Eigen::MatrixXd Q = Eigen::MatrixXd::Random(5, 4);
174 
175  Eigen::MatrixXd X;
176  EXPECT_DEBUG_DEATH(LyapunovContinuous::solve(A, Q, X), "");
177 }
178 
179 TEST_F(TestLyapunovEquationContinuousTime, try_solve_A_Q_dim_mismatch)
180 {
181  Eigen::MatrixXd A = Eigen::MatrixXd::Random(4, 4);
182  Eigen::MatrixXd Q = Eigen::MatrixXd::Random(5, 5);
183 
184  Eigen::MatrixXd X;
185  EXPECT_DEBUG_DEATH(LyapunovContinuous::solve(A, Q, X), "");
186 }
187 
188 TEST_F(TestLyapunovEquationContinuousTime, has_unique_solution_non_square)
189 {
190  Eigen::MatrixXd A = Eigen::MatrixXd::Random(5, 4);
191 
192  Eigen::MatrixXd X;
193  EXPECT_FALSE(LyapunovContinuous::hasUniqueSolution(A));
194 }
195 
196 TEST_F(TestLyapunovEquationContinuousTime, has_unique_solution_infeasible1)
197 {
198  Eigen::Matrix3d A = Eigen::Matrix3d::Ones();
199 
200  EXPECT_FALSE(LyapunovContinuous::hasUniqueSolution(A));
201 }
corbo::LyapunovContinuous
Methods for dealing with continuous-time Lyapunov equations.
Definition: lyapunov_continuous.h:78
TEST_F
TEST_F(TestLyapunovEquationContinuousTime, solve_feasible1)
Definition: test_lyapunov_continuous.cpp:51
macros.h
X
#define X
Definition: icosphere.cpp:20
TestLyapunovEquationContinuousTime::TestLyapunovEquationContinuousTime
TestLyapunovEquationContinuousTime()
Definition: test_lyapunov_continuous.cpp:37
TestLyapunovEquationContinuousTime::~TestLyapunovEquationContinuousTime
virtual ~TestLyapunovEquationContinuousTime()
Definition: test_lyapunov_continuous.cpp:39
lyapunov_continuous.h
EXPECT_EQ_MATRIX
#define EXPECT_EQ_MATRIX(A, B, tol)
Definition: macros.h:61
TestLyapunovEquationContinuousTime
Definition: test_lyapunov_continuous.cpp:33
A
MatrixType A(a, *n, *n, *lda)


control_box_rst
Author(s): Christoph Rösmann
autogenerated on Wed Mar 2 2022 00:07:06