GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/////////////////////////////////////////////////////////////////////////////// |
||
2 |
// BSD 3-Clause License |
||
3 |
// |
||
4 |
// Copyright (C) 2019-2021, LAAS-CNRS, New York University, |
||
5 |
// Max Planck Gesellschaft, University of Edinburgh, |
||
6 |
// INRIA |
||
7 |
// Copyright note valid unless otherwise stated in individual files. |
||
8 |
// All rights reserved. |
||
9 |
/////////////////////////////////////////////////////////////////////////////// |
||
10 |
|||
11 |
#define BOOST_TEST_NO_MAIN |
||
12 |
#define BOOST_TEST_ALTERNATIVE_INIT_API |
||
13 |
|||
14 |
#include "crocoddyl/core/utils/callbacks.hpp" |
||
15 |
#include "factory/solver.hpp" |
||
16 |
#include "unittest_common.hpp" |
||
17 |
|||
18 |
using namespace boost::unit_test; |
||
19 |
using namespace crocoddyl::unittest; |
||
20 |
|||
21 |
//____________________________________________________________________________// |
||
22 |
|||
23 |
5 |
void test_kkt_dimension(ActionModelTypes::Type action_type, size_t T) { |
|
24 |
// Create the kkt solver |
||
25 |
✓✗ | 10 |
SolverFactory factory; |
26 |
boost::shared_ptr<crocoddyl::SolverKKT> kkt = |
||
27 |
boost::static_pointer_cast<crocoddyl::SolverKKT>( |
||
28 |
✓✗ | 10 |
factory.create(SolverTypes::SolverKKT, action_type, T)); |
29 |
|||
30 |
// define some aliases |
||
31 |
✓✗ | 5 |
const std::size_t ndx = kkt->get_ndx(); |
32 |
✓✗ | 5 |
const std::size_t nu = kkt->get_nu(); |
33 |
|||
34 |
// Test the different matrix sizes |
||
35 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
5 |
BOOST_CHECK_EQUAL(kkt->get_kkt().rows(), 2 * ndx + nu); |
36 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
5 |
BOOST_CHECK_EQUAL(kkt->get_kkt().cols(), 2 * ndx + nu); |
37 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
5 |
BOOST_CHECK_EQUAL(kkt->get_kktref().size(), 2 * ndx + nu); |
38 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
5 |
BOOST_CHECK_EQUAL(kkt->get_primaldual().size(), 2 * ndx + nu); |
39 |
✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
5 |
BOOST_CHECK_EQUAL(kkt->get_us().size(), T); |
40 |
✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
5 |
BOOST_CHECK_EQUAL(kkt->get_xs().size(), T + 1); |
41 |
5 |
} |
|
42 |
|||
43 |
//____________________________________________________________________________// |
||
44 |
|||
45 |
5 |
void test_kkt_search_direction(ActionModelTypes::Type action_type, size_t T) { |
|
46 |
// Create the kkt solver |
||
47 |
✓✗ | 10 |
SolverFactory factory; |
48 |
boost::shared_ptr<crocoddyl::SolverKKT> kkt = |
||
49 |
boost::static_pointer_cast<crocoddyl::SolverKKT>( |
||
50 |
✓✗ | 10 |
factory.create(SolverTypes::SolverKKT, action_type, T)); |
51 |
|||
52 |
// Generate the different state along the trajectory |
||
53 |
const boost::shared_ptr<crocoddyl::ShootingProblem>& problem = |
||
54 |
✓✗ | 5 |
kkt->get_problem(); |
55 |
const boost::shared_ptr<crocoddyl::StateAbstract>& state = |
||
56 |
5 |
problem->get_runningModels()[0]->get_state(); |
|
57 |
10 |
std::vector<Eigen::VectorXd> xs; |
|
58 |
10 |
std::vector<Eigen::VectorXd> us; |
|
59 |
✓✓ | 55 |
for (std::size_t i = 0; i < T; ++i) { |
60 |
const boost::shared_ptr<crocoddyl::ActionModelAbstract>& model = |
||
61 |
50 |
problem->get_runningModels()[i]; |
|
62 |
✓✗✓✗ |
50 |
xs.push_back(state->rand()); |
63 |
✓✗✓✗ ✓✗ |
50 |
us.push_back(Eigen::VectorXd::Random(model->get_nu())); |
64 |
} |
||
65 |
✓✗✓✗ |
5 |
xs.push_back(state->rand()); |
66 |
|||
67 |
// Compute the search direction |
||
68 |
✓✗ | 5 |
kkt->setCandidate(xs, us); |
69 |
✓✗ | 5 |
kkt->computeDirection(); |
70 |
|||
71 |
// define some aliases |
||
72 |
✓✗ | 5 |
const std::size_t ndx = kkt->get_ndx(); |
73 |
✓✗ | 5 |
const std::size_t nu = kkt->get_nu(); |
74 |
✓✗✓✗ |
10 |
Eigen::MatrixXd kkt_mat = kkt->get_kkt(); |
75 |
✓✗ | 5 |
Eigen::Block<Eigen::MatrixXd> hess = kkt_mat.block(0, 0, ndx + nu, ndx + nu); |
76 |
|||
77 |
// Checking the symmetricity of the Hessian |
||
78 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
5 |
BOOST_CHECK((hess - hess.transpose()).isZero(1e-9)); |
79 |
|||
80 |
// Check initial state |
||
81 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
5 |
BOOST_CHECK((state->diff_dx(state->integrate_x(xs[0], kkt->get_dxs()[0]), |
82 |
kkt->get_problem()->get_x0())) |
||
83 |
.isZero(1e-9)); |
||
84 |
5 |
} |
|
85 |
|||
86 |
//____________________________________________________________________________// |
||
87 |
|||
88 |
15 |
void test_solver_against_kkt_solver(SolverTypes::Type solver_type, |
|
89 |
ActionModelTypes::Type action_type, |
||
90 |
size_t T) { |
||
91 |
// Create the testing and KKT solvers |
||
92 |
✓✗ | 30 |
SolverFactory solver_factory; |
93 |
boost::shared_ptr<crocoddyl::SolverAbstract> solver = |
||
94 |
✓✗ | 30 |
solver_factory.create(solver_type, action_type, T); |
95 |
boost::shared_ptr<crocoddyl::SolverAbstract> kkt = |
||
96 |
✓✗ | 30 |
solver_factory.create(SolverTypes::SolverKKT, action_type, T); |
97 |
|||
98 |
// Get the pointer to the problem so we can create the equivalent kkt solver. |
||
99 |
const boost::shared_ptr<crocoddyl::ShootingProblem>& problem = |
||
100 |
✓✗ | 15 |
solver->get_problem(); |
101 |
|||
102 |
// Generate the different state along the trajectory |
||
103 |
const boost::shared_ptr<crocoddyl::StateAbstract>& state = |
||
104 |
15 |
problem->get_runningModels()[0]->get_state(); |
|
105 |
30 |
std::vector<Eigen::VectorXd> xs; |
|
106 |
30 |
std::vector<Eigen::VectorXd> us; |
|
107 |
✓✓ | 165 |
for (std::size_t i = 0; i < T; ++i) { |
108 |
const boost::shared_ptr<crocoddyl::ActionModelAbstract>& model = |
||
109 |
150 |
problem->get_runningModels()[i]; |
|
110 |
✓✗✓✗ |
150 |
xs.push_back(state->rand()); |
111 |
✓✗✓✗ ✓✗ |
150 |
us.push_back(Eigen::VectorXd::Random(model->get_nu())); |
112 |
} |
||
113 |
✓✗✓✗ |
15 |
xs.push_back(state->rand()); |
114 |
|||
115 |
// Define the callback function |
||
116 |
30 |
std::vector<boost::shared_ptr<crocoddyl::CallbackAbstract> > cbs; |
|
117 |
✓✗✓✗ |
15 |
cbs.push_back(boost::make_shared<crocoddyl::CallbackVerbose>()); |
118 |
✓✗ | 15 |
kkt->setCallbacks(cbs); |
119 |
✓✗ | 15 |
solver->setCallbacks(cbs); |
120 |
|||
121 |
// Print the name of the action model for introspection |
||
122 |
✓✗✓✗ |
15 |
std::cout << ActionModelTypes::all[action_type] << std::endl; |
123 |
|||
124 |
// Solve the problem using the KKT solver |
||
125 |
✓✗ | 15 |
kkt->solve(xs, us, 100); |
126 |
|||
127 |
// Solve the problem using the solver in testing |
||
128 |
✓✗ | 15 |
solver->solve(xs, us, 100); |
129 |
|||
130 |
// check trajectory dimensions |
||
131 |
✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
15 |
BOOST_CHECK_EQUAL(solver->get_us().size(), T); |
132 |
✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
15 |
BOOST_CHECK_EQUAL(solver->get_xs().size(), T + 1); |
133 |
|||
134 |
// initial state |
||
135 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
15 |
BOOST_CHECK((solver->get_xs()[0] - problem->get_x0()).isZero(1e-9)); |
136 |
|||
137 |
// check solutions against each other |
||
138 |
✓✓ | 165 |
for (unsigned int t = 0; t < T; ++t) { |
139 |
const boost::shared_ptr<crocoddyl::ActionModelAbstract>& model = |
||
140 |
✓✗ | 150 |
solver->get_problem()->get_runningModels()[t]; |
141 |
150 |
std::size_t nu = model->get_nu(); |
|
142 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
150 |
BOOST_CHECK( |
143 |
(state->diff_dx(solver->get_xs()[t], kkt->get_xs()[t])).isZero(1e-9)); |
||
144 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
150 |
BOOST_CHECK((solver->get_us()[t].head(nu) - kkt->get_us()[t]).isZero(1e-9)); |
145 |
} |
||
146 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
15 |
BOOST_CHECK( |
147 |
(state->diff_dx(solver->get_xs()[T], kkt->get_xs()[T])).isZero(1e-9)); |
||
148 |
15 |
} |
|
149 |
|||
150 |
//____________________________________________________________________________// |
||
151 |
|||
152 |
5 |
void register_kkt_solver_unit_tests(ActionModelTypes::Type action_type, |
|
153 |
const std::size_t T) { |
||
154 |
✓✗✓✗ |
10 |
boost::test_tools::output_test_stream test_name; |
155 |
✓✗✓✗ |
5 |
test_name << "test_" << action_type; |
156 |
✓✗✓✗ ✓✗✓✗ |
5 |
test_suite* ts = BOOST_TEST_SUITE(test_name.str()); |
157 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
5 |
ts->add(BOOST_TEST_CASE(boost::bind(&test_kkt_dimension, action_type, T))); |
158 |
5 |
ts->add( |
|
159 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
5 |
BOOST_TEST_CASE(boost::bind(&test_kkt_search_direction, action_type, T))); |
160 |
✓✗✓✗ ✓✗ |
5 |
framework::master_test_suite().add(ts); |
161 |
5 |
} |
|
162 |
|||
163 |
15 |
void register_solvers_againt_kkt_unit_tests(SolverTypes::Type solver_type, |
|
164 |
ActionModelTypes::Type action_type, |
||
165 |
const std::size_t T) { |
||
166 |
✓✗✓✗ |
30 |
boost::test_tools::output_test_stream test_name; |
167 |
✓✗✓✗ ✓✗✓✗ |
15 |
test_name << "test_" << solver_type << "_" << action_type; |
168 |
✓✗✓✗ ✓✗✓✗ |
15 |
test_suite* ts = BOOST_TEST_SUITE(test_name.str()); |
169 |
✓✗✓✗ ✓✗✓✗ |
15 |
std::cout << "Running " << test_name.str() << std::endl; |
170 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
15 |
ts->add(BOOST_TEST_CASE(boost::bind(&test_solver_against_kkt_solver, |
171 |
solver_type, action_type, T))); |
||
172 |
✓✗✓✗ ✓✗ |
15 |
framework::master_test_suite().add(ts); |
173 |
15 |
} |
|
174 |
|||
175 |
//____________________________________________________________________________// |
||
176 |
|||
177 |
1 |
bool init_function() { |
|
178 |
1 |
std::size_t T = 10; |
|
179 |
|||
180 |
✓✓ | 6 |
for (size_t i = 0; i < ActionModelTypes::all.size(); ++i) { |
181 |
5 |
register_kkt_solver_unit_tests(ActionModelTypes::all[i], T); |
|
182 |
} |
||
183 |
|||
184 |
// We start from 1 as 0 is the kkt solver |
||
185 |
✓✓ | 6 |
for (size_t s = 1; s < SolverTypes::all.size(); ++s) { |
186 |
✓✓ | 20 |
for (size_t i = 0; i < ActionModelTypes::ActionModelImpulseFwdDynamics_HyQ; |
187 |
++i) { |
||
188 |
15 |
register_solvers_againt_kkt_unit_tests(SolverTypes::all[s], |
|
189 |
15 |
ActionModelTypes::all[i], T); |
|
190 |
} |
||
191 |
} |
||
192 |
1 |
return true; |
|
193 |
} |
||
194 |
|||
195 |
//____________________________________________________________________________// |
||
196 |
|||
197 |
1 |
int main(int argc, char* argv[]) { |
|
198 |
1 |
return ::boost::unit_test::unit_test_main(&init_function, argc, argv); |
|
199 |
} |
Generated by: GCOVR (Version 4.2) |