GCC Code Coverage Report


Directory: ./
File: unittest/test_states.cpp
Date: 2025-06-03 08:14:12
Exec Total Coverage
Lines: 0 225 0.0%
Functions: 0 15 0.0%
Branches: 0 1428 0.0%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2025, LAAS-CNRS, New York University,
5 // Max Planck Gesellschaft, University of Edinburgh
6 // INRIA, Heriot-Watt University
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 "factory/state.hpp"
15 #include "unittest_common.hpp"
16
17 using namespace boost::unit_test;
18 using namespace crocoddyl::unittest;
19
20 //----------------------------------------------------------------------------//
21
22 ✗ void test_state_dimension(StateModelTypes::Type state_type) {
23 ✗ StateModelFactory factory;
24 const std::shared_ptr<crocoddyl::StateAbstract>& state =
25 ✗ factory.create(state_type);
26
27 // Checking the dimension of zero and random states
28 ✗ BOOST_CHECK(static_cast<std::size_t>(state->zero().size()) ==
29 state->get_nx());
30 ✗ BOOST_CHECK(static_cast<std::size_t>(state->rand().size()) ==
31 state->get_nx());
32 ✗ BOOST_CHECK(state->get_nx() == (state->get_nq() + state->get_nv()));
33 ✗ BOOST_CHECK(state->get_ndx() == (2 * state->get_nv()));
34 ✗ BOOST_CHECK(static_cast<std::size_t>(state->get_lb().size()) ==
35 state->get_nx());
36 ✗ BOOST_CHECK(static_cast<std::size_t>(state->get_ub().size()) ==
37 state->get_nx());
38
39 // Checking that casted computation is the same
40 #ifdef NDEBUG // Run only in release mode
41 const std::shared_ptr<crocoddyl::StateAbstractTpl<float>>& casted_state =
42 state->cast<float>();
43 BOOST_CHECK(static_cast<std::size_t>(casted_state->zero().size()) ==
44 casted_state->get_nx());
45 BOOST_CHECK(static_cast<std::size_t>(casted_state->rand().size()) ==
46 casted_state->get_nx());
47 BOOST_CHECK(casted_state->get_nx() ==
48 (casted_state->get_nq() + casted_state->get_nv()));
49 BOOST_CHECK(casted_state->get_ndx() == (2 * casted_state->get_nv()));
50 BOOST_CHECK(static_cast<std::size_t>(casted_state->get_lb().size()) ==
51 casted_state->get_nx());
52 BOOST_CHECK(static_cast<std::size_t>(casted_state->get_ub().size()) ==
53 casted_state->get_nx());
54 #endif
55 ✗ }
56
57 ✗ void test_integrate_against_difference(StateModelTypes::Type state_type) {
58 ✗ StateModelFactory factory;
59 const std::shared_ptr<crocoddyl::StateAbstract>& state =
60 ✗ factory.create(state_type);
61
62 // Generating random states
63 ✗ const Eigen::VectorXd x1 = state->rand();
64 ✗ const Eigen::VectorXd x2 = state->rand();
65
66 // Computing x2 by integrating its difference
67 ✗ Eigen::VectorXd dx(state->get_ndx());
68 ✗ Eigen::VectorXd x2i(state->get_nx());
69 ✗ Eigen::VectorXd dxi(state->get_ndx());
70 ✗ state->diff(x1, x2, dx);
71 ✗ state->integrate(x1, dx, x2i);
72 ✗ state->diff(x2i, x2, dxi);
73
74 // Checking that both states agree
75 ✗ BOOST_CHECK(dxi.isZero(1e-9));
76
77 // Checking that casted computation is the same
78 #ifdef NDEBUG // Run only in release mode
79 const std::shared_ptr<crocoddyl::StateAbstractTpl<float>>& casted_state =
80 state->cast<float>();
81 const Eigen::VectorXf x1_f = casted_state->rand();
82 const Eigen::VectorXf x2_f = casted_state->rand();
83 Eigen::VectorXf dx_f(casted_state->get_ndx());
84 Eigen::VectorXf x2i_f(casted_state->get_nx());
85 Eigen::VectorXf dxi_f(casted_state->get_ndx());
86 casted_state->diff(x1_f, x2_f, dx_f);
87 casted_state->integrate(x1_f, dx_f, x2i_f);
88 casted_state->diff(x2i_f, x2_f, dxi_f);
89 BOOST_CHECK(dxi_f.isZero(1e-6f));
90 #endif
91 ✗ }
92
93 ✗ void test_difference_against_integrate(StateModelTypes::Type state_type) {
94 ✗ StateModelFactory factory;
95 const std::shared_ptr<crocoddyl::StateAbstract>& state =
96 ✗ factory.create(state_type);
97
98 // Generating random states
99 ✗ const Eigen::VectorXd x = state->rand();
100 ✗ const Eigen::VectorXd dx = Eigen::VectorXd::Random(state->get_ndx());
101
102 // Computing dx by differentiation of its integrate
103 ✗ Eigen::VectorXd xidx(state->get_nx());
104 ✗ Eigen::VectorXd dxd(state->get_ndx());
105 ✗ state->integrate(x, dx, xidx);
106 ✗ state->diff(x, xidx, dxd);
107
108 // Checking that both states agree
109 ✗ BOOST_CHECK((dxd - dx).isZero(1e-9));
110
111 // Checking that casted computation is the same
112 #ifdef NDEBUG // Run only in release mode
113 const std::shared_ptr<crocoddyl::StateAbstractTpl<float>>& casted_state =
114 state->cast<float>();
115 const Eigen::VectorXf x_f = casted_state->rand();
116 const Eigen::VectorXf dx_f = Eigen::VectorXf::Random(casted_state->get_ndx());
117 Eigen::VectorXf xidx_f(casted_state->get_nx());
118 Eigen::VectorXf dxd_f(casted_state->get_ndx());
119 casted_state->integrate(x_f, dx_f, xidx_f);
120 casted_state->diff(x_f, xidx_f, dxd_f);
121 BOOST_CHECK((dxd_f - dx_f).isZero(1e-6f));
122 #endif
123 ✗ }
124
125 ✗ void test_Jdiff_firstsecond(StateModelTypes::Type state_type) {
126 ✗ StateModelFactory factory;
127 const std::shared_ptr<crocoddyl::StateAbstract>& state =
128 ✗ factory.create(state_type);
129
130 // Generating random values for the initial and terminal states
131 ✗ const Eigen::VectorXd x1 = state->rand();
132 ✗ const Eigen::VectorXd x2 = state->rand();
133
134 // Computing the partial derivatives of the difference function separately
135 Eigen::MatrixXd Jdiff_tmp(
136 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
137 Eigen::MatrixXd Jdiff_first(
138 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
139 Eigen::MatrixXd Jdiff_second(
140 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
141 ✗ state->Jdiff(x1, x2, Jdiff_first, Jdiff_tmp, crocoddyl::first);
142 ✗ state->Jdiff(x1, x2, Jdiff_tmp, Jdiff_second, crocoddyl::second);
143
144 // Computing the partial derivatives of the difference function separately
145 Eigen::MatrixXd Jdiff_both_first(
146 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
147 Eigen::MatrixXd Jdiff_both_second(
148 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
149 ✗ state->Jdiff(x1, x2, Jdiff_both_first, Jdiff_both_second);
150
151 ✗ BOOST_CHECK((Jdiff_first - Jdiff_both_first).isZero(1e-9));
152 ✗ BOOST_CHECK((Jdiff_second - Jdiff_both_second).isZero(1e-9));
153
154 // Checking that casted computation is the same
155 #ifdef NDEBUG // Run only in release mode
156 const std::shared_ptr<crocoddyl::StateAbstractTpl<float>>& casted_state =
157 state->cast<float>();
158 const Eigen::VectorXf x1_f = casted_state->rand();
159 const Eigen::VectorXf x2_f = casted_state->rand();
160 Eigen::MatrixXf Jdiff_tmp_f(
161 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
162 Eigen::MatrixXf Jdiff_first_f(
163 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
164 Eigen::MatrixXf Jdiff_second_f(
165 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
166 Eigen::MatrixXf Jdiff_both_first_f(
167 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
168 Eigen::MatrixXf Jdiff_both_second_f(
169 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
170 casted_state->Jdiff(x1_f, x2_f, Jdiff_first_f, Jdiff_tmp_f, crocoddyl::first);
171 casted_state->Jdiff(x1_f, x2_f, Jdiff_tmp_f, Jdiff_second_f,
172 crocoddyl::second);
173 casted_state->Jdiff(x1_f, x2_f, Jdiff_both_first_f, Jdiff_both_second_f);
174 BOOST_CHECK((Jdiff_first_f - Jdiff_both_first_f).isZero(1e-9f));
175 BOOST_CHECK((Jdiff_second_f - Jdiff_both_second_f).isZero(1e-9f));
176 #endif
177 ✗ }
178
179 ✗ void test_Jint_firstsecond(StateModelTypes::Type state_type) {
180 ✗ StateModelFactory factory;
181 const std::shared_ptr<crocoddyl::StateAbstract>& state =
182 ✗ factory.create(state_type);
183
184 // Generating random values for the initial and terminal states
185 ✗ const Eigen::VectorXd x = state->rand();
186 ✗ const Eigen::VectorXd dx = Eigen::VectorXd::Random(state->get_ndx());
187
188 // Computing the partial derivatives of the difference function separately
189 Eigen::MatrixXd Jint_tmp(
190 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
191 Eigen::MatrixXd Jint_first(
192 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
193 Eigen::MatrixXd Jint_second(
194 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
195 ✗ state->Jintegrate(x, dx, Jint_first, Jint_tmp, crocoddyl::first);
196 ✗ state->Jintegrate(x, dx, Jint_tmp, Jint_second, crocoddyl::second);
197
198 // Computing the partial derivatives of the integrate function separately
199 Eigen::MatrixXd Jint_both_first(
200 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
201 Eigen::MatrixXd Jint_both_second(
202 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
203 ✗ state->Jintegrate(x, dx, Jint_both_first, Jint_both_second);
204
205 ✗ BOOST_CHECK((Jint_first - Jint_both_first).isZero(1e-9));
206 ✗ BOOST_CHECK((Jint_second - Jint_both_second).isZero(1e-9));
207
208 // Checking that casted computation is the same
209 #ifdef NDEBUG // Run only in release mode
210 const std::shared_ptr<crocoddyl::StateAbstractTpl<float>>& casted_state =
211 state->cast<float>();
212 const Eigen::VectorXf x_f = casted_state->rand();
213 const Eigen::VectorXf dx_f = Eigen::VectorXf::Random(casted_state->get_ndx());
214 Eigen::MatrixXf Jint_tmp_f(
215 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
216 Eigen::MatrixXf Jint_first_f(
217 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
218 Eigen::MatrixXf Jint_second_f(
219 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
220 Eigen::MatrixXf Jint_both_first_f(
221 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
222 Eigen::MatrixXf Jint_both_second_f(
223 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
224 casted_state->Jintegrate(x_f, dx_f, Jint_first_f, Jint_tmp_f,
225 crocoddyl::first);
226 casted_state->Jintegrate(x_f, dx_f, Jint_tmp_f, Jint_second_f,
227 crocoddyl::second);
228 casted_state->Jintegrate(x_f, dx_f, Jint_both_first_f, Jint_both_second_f);
229 BOOST_CHECK((Jint_first_f - Jint_both_first_f).isZero(1e-9f));
230 BOOST_CHECK((Jint_second_f - Jint_both_second_f).isZero(1e-9f));
231 #endif
232 ✗ }
233
234 ✗ void test_Jdiff_num_diff_firstsecond(StateModelTypes::Type state_type) {
235 ✗ StateModelFactory factory;
236 const std::shared_ptr<crocoddyl::StateAbstract>& state =
237 ✗ factory.create(state_type);
238 // Generating random values for the initial and terminal states
239 ✗ const Eigen::VectorXd x1 = state->rand();
240 ✗ const Eigen::VectorXd x2 = state->rand();
241
242 // Get the num diff state
243 ✗ crocoddyl::StateNumDiff state_num_diff(state);
244
245 // Computing the partial derivatives of the difference function separately
246 Eigen::MatrixXd Jdiff_num_diff_tmp(
247 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
248 Eigen::MatrixXd Jdiff_num_diff_first(
249 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
250 Eigen::MatrixXd Jdiff_num_diff_second(
251 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
252 ✗ state_num_diff.Jdiff(x1, x2, Jdiff_num_diff_first, Jdiff_num_diff_tmp,
253 crocoddyl::first);
254 ✗ state_num_diff.Jdiff(x1, x2, Jdiff_num_diff_tmp, Jdiff_num_diff_second,
255 crocoddyl::second);
256
257 // Computing the partial derivatives of the difference function separately
258 Eigen::MatrixXd Jdiff_num_diff_both_first(
259 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
260 Eigen::MatrixXd Jdiff_num_diff_both_second(
261 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
262 ✗ state_num_diff.Jdiff(x1, x2, Jdiff_num_diff_both_first,
263 Jdiff_num_diff_both_second);
264
265 ✗ BOOST_CHECK((Jdiff_num_diff_first - Jdiff_num_diff_both_first).isZero(1e-9));
266 ✗ BOOST_CHECK(
267 (Jdiff_num_diff_second - Jdiff_num_diff_both_second).isZero(1e-9));
268 ✗ }
269
270 ✗ void test_Jint_num_diff_firstsecond(StateModelTypes::Type state_type) {
271 ✗ StateModelFactory factory;
272 const std::shared_ptr<crocoddyl::StateAbstract>& state =
273 ✗ factory.create(state_type);
274 // Generating random values for the initial and terminal states
275 ✗ const Eigen::VectorXd x = state->rand();
276 ✗ const Eigen::VectorXd dx = Eigen::VectorXd::Random(state->get_ndx());
277
278 // Get the num diff state
279 ✗ crocoddyl::StateNumDiff state_num_diff(state);
280
281 // Computing the partial derivatives of the difference function separately
282 Eigen::MatrixXd Jint_num_diff_tmp(
283 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
284 Eigen::MatrixXd Jint_num_diff_first(
285 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
286 Eigen::MatrixXd Jint_num_diff_second(
287 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
288 ✗ state_num_diff.Jintegrate(x, dx, Jint_num_diff_first, Jint_num_diff_tmp,
289 crocoddyl::first);
290 ✗ state_num_diff.Jintegrate(x, dx, Jint_num_diff_tmp, Jint_num_diff_second,
291 crocoddyl::second);
292
293 // Computing the partial derivatives of the given function separately
294 Eigen::MatrixXd Jint_num_diff_both_first(
295 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
296 Eigen::MatrixXd Jint_num_diff_both_second(
297 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
298 ✗ state_num_diff.Jintegrate(x, dx, Jint_num_diff_both_first,
299 Jint_num_diff_both_second);
300
301 ✗ BOOST_CHECK((Jint_num_diff_first - Jint_num_diff_both_first).isZero(1e-9));
302 ✗ BOOST_CHECK((Jint_num_diff_second - Jint_num_diff_both_second).isZero(1e-9));
303 ✗ }
304
305 ✗ void test_Jdiff_against_numdiff(StateModelTypes::Type state_type) {
306 ✗ StateModelFactory factory;
307 const std::shared_ptr<crocoddyl::StateAbstract>& state =
308 ✗ factory.create(state_type);
309 // Generating random values for the initial and terminal states
310 ✗ const Eigen::VectorXd x1 = state->rand();
311 ✗ const Eigen::VectorXd x2 = state->rand();
312
313 // Computing the partial derivatives of the difference function analytically
314 Eigen::MatrixXd Jdiff_1(
315 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
316 Eigen::MatrixXd Jdiff_2(
317 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
318 ✗ state->Jdiff(x1, x2, Jdiff_1, Jdiff_2, crocoddyl::first);
319 ✗ state->Jdiff(x1, x2, Jdiff_1, Jdiff_2, crocoddyl::second);
320
321 // Computing the partial derivatives of the difference function numerically
322 ✗ crocoddyl::StateNumDiff state_num_diff(state);
323 Eigen::MatrixXd Jdiff_num_1(
324 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
325 Eigen::MatrixXd Jdiff_num_2(
326 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
327 ✗ state_num_diff.Jdiff(x1, x2, Jdiff_num_1, Jdiff_num_2);
328
329 // Checking the partial derivatives against numerical differentiation
330 // Tolerance defined as in
331 // http://www.it.uom.gr/teaching/linearalgebra/NumericalRecipiesInC/c5-7.pdf
332 ✗ double tol = std::pow(std::sqrt(2.0 * std::numeric_limits<double>::epsilon()),
333 1. / 3.);
334 ✗ BOOST_CHECK((Jdiff_1 - Jdiff_num_1).isZero(tol));
335 ✗ BOOST_CHECK((Jdiff_2 - Jdiff_num_2).isZero(tol));
336 ✗ }
337
338 ✗ void test_Jintegrate_against_numdiff(StateModelTypes::Type state_type) {
339 ✗ StateModelFactory factory;
340 const std::shared_ptr<crocoddyl::StateAbstract>& state =
341 ✗ factory.create(state_type);
342
343 // Generating random values for the initial state and its rate of change
344 ✗ const Eigen::VectorXd x = state->rand();
345 ✗ const Eigen::VectorXd dx = Eigen::VectorXd::Random(state->get_ndx());
346
347 // Computing the partial derivatives of the difference function analytically
348 Eigen::MatrixXd Jint_1(
349 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
350 Eigen::MatrixXd Jint_2(
351 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
352 ✗ state->Jintegrate(x, dx, Jint_1, Jint_2);
353
354 // Computing the partial derivatives of the difference function numerically
355 ✗ crocoddyl::StateNumDiff state_num_diff(state);
356 Eigen::MatrixXd Jint_num_1(
357 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
358 Eigen::MatrixXd Jint_num_2(
359 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
360 ✗ state_num_diff.Jintegrate(x, dx, Jint_num_1, Jint_num_2);
361
362 // Checking the partial derivatives against numerical differentiation
363 // Tolerance defined as in
364 // http://www.it.uom.gr/teaching/linearalgebra/NumericalRecipiesInC/c5-7.pdf
365 ✗ double tol = std::pow(std::sqrt(2.0 * std::numeric_limits<double>::epsilon()),
366 1. / 3.);
367 ✗ BOOST_CHECK((Jint_1 - Jint_num_1).isZero(tol));
368 ✗ BOOST_CHECK((Jint_2 - Jint_num_2).isZero(tol));
369
370 // Checking that casted computation is the same
371 #ifdef NDEBUG // Run only in release mode
372 float tol_f = std::sqrt(float(2.0) * std::numeric_limits<float>::epsilon());
373 const std::shared_ptr<crocoddyl::StateAbstractTpl<float>>& casted_state =
374 state->cast<float>();
375 crocoddyl::StateNumDiffTpl<float> casted_state_num_diff =
376 state_num_diff.cast<float>();
377 const Eigen::VectorXf x_f = casted_state->rand();
378 const Eigen::VectorXf dx_f = Eigen::VectorXf::Random(casted_state->get_ndx());
379 Eigen::MatrixXf Jint_1_f(
380 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
381 Eigen::MatrixXf Jint_2_f(
382 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
383 Eigen::MatrixXf Jint_num_1_f(
384 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
385 Eigen::MatrixXf Jint_num_2_f(
386 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
387 casted_state_num_diff.Jintegrate(x_f, dx_f, Jint_num_1_f, Jint_num_2_f);
388 casted_state->Jintegrate(x_f, dx_f, Jint_1_f, Jint_2_f);
389 BOOST_CHECK((Jint_1_f - Jint_num_1_f).isZero(tol_f));
390 BOOST_CHECK((Jint_2_f - Jint_num_2_f).isZero(tol_f));
391 #endif
392 ✗ }
393
394 ✗ void test_JintegrateTransport(StateModelTypes::Type state_type) {
395 ✗ StateModelFactory factory;
396 const std::shared_ptr<crocoddyl::StateAbstract>& state =
397 ✗ factory.create(state_type);
398
399 // Generating random values for the initial state and its rate of change
400 ✗ const Eigen::VectorXd x = state->rand();
401 ✗ const Eigen::VectorXd dx = Eigen::VectorXd::Random(state->get_ndx());
402
403 // Computing the partial derivatives of the difference function analytically
404 Eigen::MatrixXd Jint_1(
405 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
406 Eigen::MatrixXd Jint_2(
407 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
408 ✗ state->Jintegrate(x, dx, Jint_1, Jint_2);
409
410 Eigen::MatrixXd Jref(
411 ✗ Eigen::MatrixXd::Random(state->get_ndx(), 2 * state->get_ndx()));
412 ✗ const Eigen::MatrixXd Jtest(Jref);
413
414 ✗ state->JintegrateTransport(x, dx, Jref, crocoddyl::first);
415 ✗ BOOST_CHECK((Jref - Jint_1 * Jtest).isZero(1e-10));
416
417 ✗ Jref = Jtest;
418 ✗ state->JintegrateTransport(x, dx, Jref, crocoddyl::second);
419 ✗ BOOST_CHECK((Jref - Jint_2 * Jtest).isZero(1e-10));
420
421 // Checking that casted computation is the same
422 #ifdef NDEBUG // Run only in release mode
423 const std::shared_ptr<crocoddyl::StateAbstractTpl<float>>& casted_state =
424 state->cast<float>();
425 const Eigen::VectorXf x_f = casted_state->rand();
426 const Eigen::VectorXf dx_f = Eigen::VectorXf::Random(casted_state->get_ndx());
427 Eigen::MatrixXf Jint_1_f(
428 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
429 Eigen::MatrixXf Jint_2_f(
430 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
431 Eigen::MatrixXf Jref_f(Eigen::MatrixXf::Random(casted_state->get_ndx(),
432 2 * casted_state->get_ndx()));
433 const Eigen::MatrixXf Jtest_f(Jref_f);
434 casted_state->Jintegrate(x_f, dx_f, Jint_1_f, Jint_2_f);
435 Jref_f = Jtest_f;
436 casted_state->JintegrateTransport(x_f, dx_f, Jref_f, crocoddyl::first);
437 BOOST_CHECK((Jref_f - Jint_1_f * Jtest_f).isZero(1e-6f));
438 casted_state->JintegrateTransport(x_f, dx_f, Jref_f, crocoddyl::second);
439 Jref_f = Jtest_f;
440 casted_state->JintegrateTransport(x_f, dx_f, Jref_f, crocoddyl::second);
441 BOOST_CHECK((Jref_f - Jint_2_f * Jtest_f).isZero(1e-6f));
442 #endif
443 ✗ }
444
445 ✗ void test_Jdiff_and_Jintegrate_are_inverses(StateModelTypes::Type state_type) {
446 ✗ StateModelFactory factory;
447 const std::shared_ptr<crocoddyl::StateAbstract>& state =
448 ✗ factory.create(state_type);
449
450 // Generating random states
451 ✗ const Eigen::VectorXd x1 = state->rand();
452 ✗ const Eigen::VectorXd dx = Eigen::VectorXd::Random(state->get_ndx());
453 ✗ Eigen::VectorXd x2(state->get_nx());
454 ✗ state->integrate(x1, dx, x2);
455
456 // Computing the partial derivatives of the integrate and difference function
457 ✗ Eigen::MatrixXd Jx(Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
458 Eigen::MatrixXd Jdx(
459 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
460 ✗ state->Jintegrate(x1, dx, Jx, Jdx);
461 ✗ Eigen::MatrixXd J1(Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
462 ✗ Eigen::MatrixXd J2(Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
463 ✗ state->Jdiff(x1, x2, J1, J2);
464
465 // Checking that Jdiff and Jintegrate are inverses
466 ✗ Eigen::MatrixXd dX_dDX = Jdx;
467 ✗ Eigen::MatrixXd dDX_dX = J2;
468 ✗ BOOST_CHECK((dX_dDX - dDX_dX.inverse()).isZero(1e-9));
469
470 // Checking that casted computation is the same
471 #ifdef NDEBUG // Run only in release mode
472 const std::shared_ptr<crocoddyl::StateAbstractTpl<float>>& casted_state =
473 state->cast<float>();
474 const Eigen::VectorXf x1_f = casted_state->rand();
475 const Eigen::VectorXf dx_f = Eigen::VectorXf::Random(casted_state->get_ndx());
476 Eigen::VectorXf x2_f(casted_state->get_nx());
477
478 Eigen::MatrixXf Jx_f(
479 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
480 Eigen::MatrixXf Jdx_f(
481 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
482 Eigen::MatrixXf J1_f(
483 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
484 Eigen::MatrixXf J2_f(
485 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
486 Eigen::MatrixXf dX_dDX_f = Jdx_f;
487 Eigen::MatrixXf dDX_dX_f = J2_f;
488 casted_state->integrate(x1_f, dx_f, x2_f);
489 casted_state->Jintegrate(x1_f, dx_f, Jx_f, Jdx_f);
490 casted_state->Jdiff(x1_f, x2_f, J1_f, J2_f);
491 dX_dDX_f = Jdx_f;
492 dDX_dX_f = J2_f;
493 BOOST_CHECK((dX_dDX_f - dDX_dX_f.inverse()).isZero(1e-4f));
494 #endif
495 ✗ }
496
497 ✗ void test_velocity_from_Jintegrate_Jdiff(StateModelTypes::Type state_type) {
498 ✗ StateModelFactory factory;
499 const std::shared_ptr<crocoddyl::StateAbstract>& state =
500 ✗ factory.create(state_type);
501
502 // Generating random states
503 ✗ const Eigen::VectorXd x1 = state->rand();
504 ✗ Eigen::VectorXd dx = Eigen::VectorXd::Random(state->get_ndx());
505 ✗ Eigen::VectorXd x2(state->get_nx());
506 ✗ state->integrate(x1, dx, x2);
507 ✗ Eigen::VectorXd eps = Eigen::VectorXd::Random(state->get_ndx());
508 ✗ double h = 1e-8;
509
510 // Computing the partial derivatives of the integrate and difference function
511 ✗ Eigen::MatrixXd Jx(Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
512 Eigen::MatrixXd Jdx(
513 ✗ Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
514 ✗ state->Jintegrate(x1, dx, Jx, Jdx);
515 ✗ Eigen::MatrixXd J1(Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
516 ✗ Eigen::MatrixXd J2(Eigen::MatrixXd::Zero(state->get_ndx(), state->get_ndx()));
517 ✗ state->Jdiff(x1, x2, J1, J2);
518
519 // Checking that computed velocity from Jintegrate
520 ✗ Eigen::MatrixXd dX_dDX = Jdx;
521 ✗ Eigen::VectorXd x2eps(state->get_nx());
522 ✗ state->integrate(x1, dx + eps * h, x2eps);
523 ✗ Eigen::VectorXd x2_eps(state->get_ndx());
524 ✗ state->diff(x2, x2eps, x2_eps);
525 ✗ BOOST_CHECK((dX_dDX * eps - x2_eps / h).isZero(1e-3));
526
527 // Checking the velocity computed from Jdiff
528 ✗ const Eigen::VectorXd x = state->rand();
529 ✗ dx.setZero();
530 ✗ state->diff(x1, x, dx);
531 ✗ Eigen::VectorXd x2i(state->get_nx());
532 ✗ state->integrate(x, eps * h, x2i);
533 ✗ Eigen::VectorXd dxi(state->get_ndx());
534 ✗ state->diff(x1, x2i, dxi);
535 ✗ J1.setZero();
536 ✗ J2.setZero();
537 ✗ state->Jdiff(x1, x, J1, J2);
538 ✗ BOOST_CHECK((J2 * eps - (-dx + dxi) / h).isZero(1e-3));
539
540 // Checking that casted computation is the same
541 #ifdef NDEBUG // Run only in release mode
542 const std::shared_ptr<crocoddyl::StateAbstractTpl<float>>& casted_state =
543 state->cast<float>();
544 float h_f = std::sqrt(float(2.0) * std::numeric_limits<float>::epsilon());
545 Eigen::VectorXf eps_f = Eigen::VectorXf::Random(casted_state->get_ndx());
546 const Eigen::VectorXf x1_f = casted_state->rand();
547 Eigen::VectorXf dx_f = Eigen::VectorXf::Random(casted_state->get_ndx());
548 Eigen::VectorXf x2_f(casted_state->get_nx());
549 Eigen::MatrixXf Jx_f(
550 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
551 Eigen::MatrixXf Jdx_f(
552 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
553 Eigen::MatrixXf J1_f(
554 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
555 Eigen::MatrixXf J2_f(
556 Eigen::MatrixXf::Zero(casted_state->get_ndx(), casted_state->get_ndx()));
557 Eigen::MatrixXf dX_dDX_f = Jdx_f;
558 Eigen::VectorXf x2eps_f(casted_state->get_nx());
559 Eigen::VectorXf x2_eps_f(casted_state->get_ndx());
560 const Eigen::VectorXf x_f = casted_state->rand();
561 Eigen::VectorXf x2i_f(casted_state->get_nx());
562 Eigen::VectorXf dxi_f(casted_state->get_ndx());
563 casted_state->integrate(x1_f, dx_f, x2_f);
564 casted_state->Jintegrate(x1_f, dx_f, Jx_f, Jdx_f);
565 casted_state->Jdiff(x1_f, x2_f, J1_f, J2_f);
566 dX_dDX_f = Jdx_f;
567 casted_state->integrate(x1_f, dx_f + eps_f * h_f, x2eps_f);
568 casted_state->diff(x2_f, x2eps_f, x2_eps_f);
569 BOOST_CHECK((dX_dDX_f * eps_f - x2_eps_f / h_f).isZero(1e-3f));
570 dx_f.setZero();
571 casted_state->diff(x1_f, x_f, dx_f);
572 casted_state->integrate(x_f, eps_f * h_f, x2i_f);
573 casted_state->diff(x1_f, x2i_f, dxi_f);
574 casted_state->Jdiff(x1_f, x_f, J1_f, J2_f);
575 BOOST_CHECK((J2_f * eps_f - (dxi_f - dx_f) / h_f).isZero(1e-2f));
576 #endif
577 ✗ }
578
579 //----------------------------------------------------------------------------//
580
581 ✗ void register_state_unit_tests(StateModelTypes::Type state_type) {
582 ✗ boost::test_tools::output_test_stream test_name;
583 ✗ test_name << "test_" << state_type;
584 ✗ std::cout << "Running " << test_name.str() << std::endl;
585 ✗ test_suite* ts = BOOST_TEST_SUITE(test_name.str());
586 ✗ ts->add(BOOST_TEST_CASE(boost::bind(&test_state_dimension, state_type)));
587 ✗ ts->add(BOOST_TEST_CASE(
588 boost::bind(&test_integrate_against_difference, state_type)));
589 ✗ ts->add(BOOST_TEST_CASE(
590 boost::bind(&test_difference_against_integrate, state_type)));
591 ✗ ts->add(BOOST_TEST_CASE(boost::bind(&test_Jdiff_firstsecond, state_type)));
592 ✗ ts->add(BOOST_TEST_CASE(boost::bind(&test_Jint_firstsecond, state_type)));
593 ✗ ts->add(BOOST_TEST_CASE(
594 boost::bind(&test_Jdiff_num_diff_firstsecond, state_type)));
595 ✗ ts->add(BOOST_TEST_CASE(
596 boost::bind(&test_Jint_num_diff_firstsecond, state_type)));
597 ✗ ts->add(
598 ✗ BOOST_TEST_CASE(boost::bind(&test_Jdiff_against_numdiff, state_type)));
599 ✗ ts->add(BOOST_TEST_CASE(
600 boost::bind(&test_Jintegrate_against_numdiff, state_type)));
601 ✗ ts->add(BOOST_TEST_CASE(boost::bind(&test_JintegrateTransport, state_type)));
602 ✗ ts->add(BOOST_TEST_CASE(
603 boost::bind(&test_Jdiff_and_Jintegrate_are_inverses, state_type)));
604 ✗ ts->add(BOOST_TEST_CASE(
605 boost::bind(&test_velocity_from_Jintegrate_Jdiff, state_type)));
606 ✗ framework::master_test_suite().add(ts);
607 ✗ }
608
609 ✗ bool init_function() {
610 ✗ for (size_t i = 0; i < StateModelTypes::all.size(); ++i) {
611 ✗ register_state_unit_tests(StateModelTypes::all[i]);
612 }
613 ✗ return true;
614 }
615
616 ✗ int main(int argc, char** argv) {
617 ✗ return ::boost::unit_test::unit_test_main(&init_function, argc, argv);
618 }
619