17 #include <matlabCppInterface/Engine.hpp> 21 #include <gtest/gtest.h> 30 const size_t stateDim = 2;
31 const size_t controlDim = 1;
33 Eigen::Matrix<double, stateDim, stateDim> A;
34 Eigen::Matrix<double, stateDim, controlDim> B;
35 Eigen::Matrix<double, stateDim, stateDim> Q;
36 Eigen::Matrix<double, controlDim, controlDim> R;
37 Eigen::Matrix<double, controlDim, stateDim> K;
46 Eigen::Matrix<double, stateDim, stateDim> P_test;
47 P_test << 6.932484752255643, 4.332273119899151, 4.332273119899151, 4.55195134961773;
48 ASSERT_LT((P - P_test).array().abs().maxCoeff(), 1e-12);
58 const size_t stateDim = 12;
59 const size_t controlDim = 4;
61 Eigen::Matrix<double, stateDim, stateDim> A;
62 Eigen::Matrix<double, stateDim, controlDim> B;
63 Eigen::Matrix<double, stateDim, stateDim> Q;
64 Eigen::Matrix<double, controlDim, controlDim> R;
65 Eigen::Matrix<double, controlDim, stateDim> K;
66 Eigen::Matrix<double, controlDim, stateDim> Kiterative;
70 Q << 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2000, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0.1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0, 0.1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 R << 100, 0, 0, 0, 0, 1000, 0, 0, 0, 0, 1000, 0, 0, 0, 0, 100;
79 A << 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
80 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
81 0, 0, 9.81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, -0, -0, 0, 0, 0, 0, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0,
86 B << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 1.39665, 0, 0,
87 0, 0, 142.857, -0, 0, 0, 0, 142.857, 0, 0, -0, 0, 83.3333;
93 bool foundSolutionIterative = lqr.
compute(Q, R, A, B, Kiterative,
false,
true);
94 ASSERT_TRUE(foundSolutionIterative);
97 bool foundSolutionDirect = lqr.
compute(Q, R, A, B, K,
false);
98 ASSERT_TRUE(foundSolutionDirect);
99 ASSERT_LT((K - Kiterative).array().abs().maxCoeff(), 1e-4);
104 auto start1 = std::chrono::system_clock::now();
105 for (
int i = 0;
i < nTests;
i++)
107 lqr.
compute(Q, R, A, B, K,
false);
109 auto end1 = std::chrono::system_clock::now();
110 auto elapsed1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start1);
111 std::cout <<
"solved " << nTests <<
" lqr problems with state dimension " << stateDim <<
" in " << elapsed1.count()
112 <<
" ms (average: " << elapsed1.count() /
static_cast<double>(nTests) <<
" ms / lqr)" << std::endl;
115 auto start2 = std::chrono::system_clock::now();
116 for (
int i = 0;
i < nTests;
i++)
118 lqr.
compute(Q, R, A, B, Kiterative,
false,
true);
120 auto end2 = std::chrono::system_clock::now();
121 auto elapsed2 = std::chrono::duration_cast<std::chrono::milliseconds>(end2 - start2);
122 std::cout <<
"solved " << nTests <<
" lqr problems iteratively with state dimension " << stateDim <<
" in " 123 << elapsed2.count() <<
" ms (average: " << elapsed2.count() /
static_cast<double>(nTests) <<
" ms / lqr)" 128 TEST(LQRTest, matlabTest)
130 matlab::Engine engine(
true);
131 ASSERT_TRUE(engine.good());
133 const size_t stateDim = 5;
134 std::string stateDimString = std::to_string(stateDim);
140 Eigen::MatrixXd K_Matlab;
142 Eigen::Matrix<double, stateDim, stateDim> A;
143 Eigen::Matrix<double, stateDim, stateDim> B;
144 Eigen::Matrix<double, stateDim, stateDim> Q;
145 Eigen::Matrix<double, stateDim, stateDim> R;
146 Eigen::Matrix<double, stateDim, stateDim> K_Cpp;
147 Eigen::Matrix<double, stateDim, stateDim> K_Cpp_iteratively;
155 for (
int i = 0;
i < 10;
i++)
157 std::cout <<
"Test " << std::to_string(
i) << std::endl;
158 std::cout <<
"===================================" << std::endl;
160 std::cout <<
"1. Generating problem in Matlab" << std::endl;
161 engine.executeCommand(
"A = magic(" + stateDimString +
");");
162 engine.executeCommand(
"B = magic(" + stateDimString +
");");
163 engine.executeCommand(
"Q = diag(100*rand(" + stateDimString +
",1));");
164 engine.executeCommand(
"R = diag(100*rand(" + stateDimString +
",1));");
165 engine.executeCommand(
"N = zeros(" + stateDimString +
");");
167 std::cout <<
"2. Computing LQR in Matlab" << std::endl;
168 std::cout << engine.executeCommand(
"[K,S,E] = lqr(A,B,Q,R,N);");
170 std::cout <<
"3. Obtaining problem from Matlab" << std::endl;
180 std::cout <<
"4. Obtaining LQR solution from Matlab" << std::endl;
181 engine.get(
"K", K_Matlab);
183 std::cout <<
"5. Computing LQR solution in C++" << std::endl;
185 bool foundSolutionDirect = lqr.
compute(Q, R, A, B, K_Cpp,
false);
186 ASSERT_TRUE(foundSolutionDirect);
188 bool foundSolutionIterative = lqr.
compute(Q, R, A, B, K_Cpp_iteratively,
false,
true);
189 ASSERT_TRUE(foundSolutionIterative);
192 std::cout <<
"7. Comparing both solutions" << std::endl;
193 ASSERT_LT((K_Matlab - K_Cpp).array().abs().maxCoeff(), 1e-4);
194 ASSERT_LT((K_Matlab - K_Cpp_iteratively).array().abs().maxCoeff(), 1e-4);
196 std::cout << std::endl << std::endl << std::endl;
continuous-time infinite-horizon LQR
Definition: LQR.hpp:32
TEST(ConstraintComparison, comparisonAnalyticAD)
Definition: ConstraintComparison.h:158
for i
Definition: mpc_unittest_plotting.m:14
Discrete-Time Algebraic Riccati Equation.
Definition: DARE.hpp:24
bool compute(const state_matrix_t &Q, const control_matrix_t &R, const state_matrix_t &A, const control_gain_matrix_t &B, control_feedback_t &K, bool RisDiagonal=false, bool solveRiccatiIteratively=false)
design the infinite-horizon LQR controller.
Definition: LQR-impl.hpp:16
state_matrix_t computeSteadyStateRiccatiMatrix(const state_matrix_t &Q, const control_matrix_t &R, const state_matrix_t &A, const control_gain_matrix_t &B, control_feedback_t &K, bool verbose=false, const SCALAR eps=1e-6, size_t maxIter=1000)
Definition: DARE-impl.hpp:18