- 3.0.2 optimal control module.
LQOCSolverTest.h
Go to the documentation of this file.
1 /**********************************************************************************************************************
2 This file is part of the Control Toolbox (https://github.com/ethz-adrl/control-toolbox), copyright by ETH Zurich.
3 Licensed under the BSD-2 license (see LICENSE file in main directory)
4 **********************************************************************************************************************/
5 
6 
7 using namespace ct;
8 using namespace ct::optcon;
9 
10 #include "../../testSystems/SpringLoadedMass.h"
11 
12 
13 TEST(LQOCSolverTest, compareHPIPMandRiccati)
14 {
15  const size_t state_dim = 2;
16  const size_t control_dim = 1;
17  const size_t N = 5;
18  const double dt = 0.5;
19 
20  bool verbose = false; // optional verbose output
21 
22  // create instances of HPIPM and an unconstrained Gauss-Newton Riccati solver
23  std::shared_ptr<LQOCSolver<state_dim, control_dim>> hpipmSolver(new HPIPMInterface<state_dim, control_dim>);
24  std::shared_ptr<LQOCSolver<state_dim, control_dim>> gnRiccatiSolver(new GNRiccatiSolver<state_dim, control_dim>);
25 
26  // store them, and identifying names, in a vectors
27  std::vector<std::shared_ptr<LQOCSolver<state_dim, control_dim>>> lqocSolvers;
28  lqocSolvers.push_back(gnRiccatiSolver);
29  lqocSolvers.push_back(hpipmSolver);
30  std::vector<std::string> solverNames = {"Riccati", "HPIPM"};
31 
32  // create linear-quadratic optimal control problem containers
33  std::vector<std::shared_ptr<LQOCProblem<state_dim, control_dim>>> problems;
34  std::shared_ptr<LQOCProblem<state_dim, control_dim>> lqocProblem1(new LQOCProblem<state_dim, control_dim>(N));
35  std::shared_ptr<LQOCProblem<state_dim, control_dim>> lqocProblem2(new LQOCProblem<state_dim, control_dim>(N));
36 
37  problems.push_back(lqocProblem1);
38  problems.push_back(lqocProblem2);
39 
40  // create a continuous-time example system and discretize it
41  std::shared_ptr<core::LinearSystem<state_dim, control_dim>> exampleSystem(new example::SpringLoadedMassLinear());
44 
45  // nominal control
47  u0.setZero(); // by definition
48  // initial state
50  x0.setZero(); // by definition
51  // desired final state
53  xf << -1, 0;
54 
55  // create pointer to a cost function
56  auto costFunction = example::createSpringLoadedMassCostFunction(xf);
57 
59  b << 0.1, 0.1;
60 
61  // initialize the optimal control problems for both solvers
62  problems[0]->setFromTimeInvariantLinearQuadraticProblem(discreteExampleSystem, *costFunction, b, dt);
63  problems[1]->setFromTimeInvariantLinearQuadraticProblem(discreteExampleSystem, *costFunction, b, dt);
64 
65  // set the problem pointers
66  lqocSolvers[0]->setProblem(problems[0]);
67  lqocSolvers[1]->setProblem(problems[1]);
68 
69  // allocate memory (if required)
70  lqocSolvers[0]->initializeAndAllocate();
71  lqocSolvers[1]->initializeAndAllocate();
72 
73  // solve the problems...
74  lqocSolvers[0]->solve();
75  lqocSolvers[1]->solve();
76 
77  // postprocess data
78  lqocSolvers[0]->computeStatesAndControls();
79  lqocSolvers[0]->computeFeedbackMatrices();
80  lqocSolvers[0]->compute_lv();
81  lqocSolvers[1]->computeStatesAndControls();
82  lqocSolvers[1]->computeFeedbackMatrices();
83  lqocSolvers[1]->compute_lv();
84 
85  // retrieve solutions from both solvers
86  auto xSol_riccati = lqocSolvers[0]->getSolutionState();
87  auto uSol_riccati = lqocSolvers[0]->getSolutionControl();
88  ct::core::FeedbackArray<state_dim, control_dim> KSol_riccati = lqocSolvers[0]->getSolutionFeedback();
89  ct::core::ControlVectorArray<control_dim> lv_sol_riccati = lqocSolvers[0]->get_lv();
90  auto xSol_hpipm = lqocSolvers[1]->getSolutionState();
91  auto uSol_hpipm = lqocSolvers[1]->getSolutionControl();
92  ct::core::FeedbackArray<state_dim, control_dim> KSol_hpipm = lqocSolvers[1]->getSolutionFeedback();
93  ct::core::ControlVectorArray<control_dim> lv_sol_hpipm = lqocSolvers[1]->get_lv();
94 
95 
96  for (size_t j = 0; j < xSol_riccati.size(); j++)
97  {
98  if (verbose)
99  {
100  std::cout << "x solution from riccati solver:" << std::endl;
101  std::cout << xSol_riccati[j].transpose() << std::endl;
102  std::cout << "x solution from hpipm solver:" << std::endl;
103  std::cout << xSol_hpipm[j].transpose() << std::endl;
104  }
105  // assert that state trajectories are identical for both solvers
106  ASSERT_NEAR((xSol_riccati[j] - xSol_hpipm[j]).array().abs().maxCoeff(), 0.0, 1e-6);
107  }
108 
109  for (size_t j = 0; j < uSol_riccati.size(); j++)
110  {
111  if (verbose)
112  {
113  std::cout << "u solution from riccati solver:" << std::endl;
114  std::cout << uSol_riccati[j].transpose() << std::endl;
115  std::cout << "u solution from hpipm solver:" << std::endl;
116  std::cout << uSol_hpipm[j].transpose() << std::endl;
117  }
118  // assert that control trajectories are identical for both solvers
119  ASSERT_NEAR((uSol_riccati[j] - uSol_hpipm[j]).array().abs().maxCoeff(), 0.0, 1e-6);
120  }
121 
122  for (size_t j = 0; j < KSol_riccati.size(); j++)
123  {
124  if (verbose)
125  {
126  std::cout << "K solution from riccati solver:" << std::endl;
127  std::cout << KSol_riccati[j] << std::endl << std::endl;
128  std::cout << "K solution from hpipm solver:" << std::endl;
129  std::cout << KSol_hpipm[j] << std::endl << std::endl;
130  }
131  // assert that feedback trajectories are identical for both solvers
132  ASSERT_NEAR((KSol_riccati[j] - KSol_hpipm[j]).array().abs().maxCoeff(), 0.0, 1e-6);
133  }
134 
135  for (size_t j = 0; j < lv_sol_riccati.size(); j++)
136  {
137  if (verbose)
138  {
139  std::cout << "lv solution from riccati solver:" << std::endl;
140  std::cout << lv_sol_riccati[j] << std::endl << std::endl;
141  std::cout << "lv solution from hpipm solver:" << std::endl;
142  std::cout << lv_sol_hpipm[j] << std::endl << std::endl;
143  }
144  // assert that feedforward increments are identical for both solvers
145  ASSERT_NEAR((lv_sol_riccati[j] - lv_sol_hpipm[j]).array().abs().maxCoeff(), 0.0, 1e-6);
146  }
147 }
std::shared_ptr< CostFunctionQuadratic< 2, 1 > > createSpringLoadedMassCostFunction(const core::StateVector< 2 > &x_final)
Definition: SpringLoadedMass.h:67
const size_t state_dim
Definition: ConstraintExampleOutput.cpp:17
const double dt
Definition: LQOCSolverTiming.cpp:18
Linear system class for the GNMS unit test.
Definition: SpringLoadedMass.h:35
Defines a Linear-Quadratic Optimal Control Problem, which is optionally constrained.
Definition: LQOCProblem.hpp:57
Definition: GNRiccatiSolver.hpp:22
TEST(LQOCSolverTest, compareHPIPMandRiccati)
Definition: LQOCSolverTest.h:13
StateVector< state_dim > x0
Definition: ConstrainedNLOCTest.cpp:14
const bool verbose
Definition: ConstraintComparison.h:18
Definition: exampleDir.h:9
const size_t control_dim
Definition: ConstraintExampleOutput.cpp:18