GCC Code Coverage Report


Directory: ./
File: unittest/test_activations.cpp
Date: 2025-06-03 08:14:12
Exec Total Coverage
Lines: 0 89 0.0%
Functions: 0 8 0.0%
Branches: 0 354 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 "crocoddyl/core/activations/quadratic-barrier.hpp"
15 #include "factory/activation.hpp"
16 #include "unittest_common.hpp"
17
18 using namespace boost::unit_test;
19 using namespace crocoddyl::unittest;
20
21 //----------------------------------------------------------------------------//
22
23 ✗ void test_construct_data(ActivationModelTypes::Type activation_type) {
24 // create the model
25 ✗ ActivationModelFactory factory;
26 const std::shared_ptr<crocoddyl::ActivationModelAbstract>& model =
27 ✗ factory.create(activation_type);
28
29 // Run the print function
30 ✗ std::ostringstream tmp;
31 ✗ tmp << *model;
32
33 // create the corresponding data object
34 const std::shared_ptr<crocoddyl::ActivationDataAbstract>& data =
35 ✗ model->createData();
36 const std::shared_ptr<crocoddyl::ActivationDataAbstractTpl<float>>&
37 ✗ casted_data = model->cast<float>()->createData();
38 ✗ }
39
40 ✗ void test_calc_returns_a_value(ActivationModelTypes::Type activation_type) {
41 // create the model
42 ✗ ActivationModelFactory factory;
43 const std::shared_ptr<crocoddyl::ActivationModelAbstract>& model =
44 ✗ factory.create(activation_type);
45
46 // create the corresponding data object
47 const std::shared_ptr<crocoddyl::ActivationDataAbstract>& data =
48 ✗ model->createData();
49
50 // Generating random input vector
51 ✗ const Eigen::VectorXd r = Eigen::VectorXd::Random(model->get_nr());
52 ✗ data->a_value = nan("");
53
54 // Getting the state dimension from calc() call
55 ✗ model->calc(data, r);
56
57 // Checking that calc returns a value
58 ✗ BOOST_CHECK(!std::isnan(data->a_value));
59
60 // Checking that casted computation is the same
61 const std::shared_ptr<crocoddyl::ActivationModelAbstractTpl<float>>&
62 ✗ casted_model = model->cast<float>();
63 const std::shared_ptr<crocoddyl::ActivationDataAbstractTpl<float>>&
64 ✗ casted_data = casted_model->createData();
65 ✗ const Eigen::VectorXf r_f = r.cast<float>();
66 ✗ casted_data->a_value = float(nan(""));
67 ✗ casted_model->calc(casted_data, r_f);
68 ✗ BOOST_CHECK(!std::isnan(casted_data->a_value));
69 ✗ BOOST_CHECK(std::abs(data->a_value - casted_data->a_value) < 1e-6);
70 ✗ }
71
72 ✗ void test_partial_derivatives_against_numdiff(
73 ActivationModelTypes::Type activation_type) {
74 // create the model
75 ✗ ActivationModelFactory factory;
76 const std::shared_ptr<crocoddyl::ActivationModelAbstract>& model =
77 ✗ factory.create(activation_type);
78
79 // create the corresponding data object and set the cost to nan
80 const std::shared_ptr<crocoddyl::ActivationDataAbstract>& data =
81 ✗ model->createData();
82
83 ✗ crocoddyl::ActivationModelNumDiff model_num_diff(model);
84 std::shared_ptr<crocoddyl::ActivationDataAbstract> data_num_diff =
85 ✗ model_num_diff.createData();
86
87 // Generating random values for the state and control
88 ✗ const Eigen::VectorXd r = Eigen::VectorXd::Random(model->get_nr());
89
90 // Computing the activation derivatives
91 ✗ model->calc(data, r);
92 ✗ model->calcDiff(data, r);
93 ✗ model_num_diff.calc(data_num_diff, r);
94 ✗ model_num_diff.calcDiff(data_num_diff, r);
95
96 // Tolerance defined as in
97 // http://www.it.uom.gr/teaching/linearalgebra/NumericalRecipiesInC/c5-7.pdf
98 ✗ double tol = std::pow(model_num_diff.get_disturbance(), 1. / 3.);
99 ✗ BOOST_CHECK(std::abs(data->a_value - data_num_diff->a_value) < tol);
100 ✗ BOOST_CHECK((data->Ar - data_num_diff->Ar).isZero(tol));
101
102 // numerical differentiation of the Hessian is not good enough to be tested.
103 // BOOST_CHECK((data->Arr - data_num_diff->Arr).isMuchSmallerThan(1.0, tol));
104
105 // Checking that casted computation is the same
106 const std::shared_ptr<crocoddyl::ActivationModelAbstractTpl<float>>&
107 ✗ casted_model = model->cast<float>();
108 const std::shared_ptr<crocoddyl::ActivationDataAbstractTpl<float>>&
109 ✗ casted_data = casted_model->createData();
110 ✗ const Eigen::VectorXf r_f = r.cast<float>();
111 ✗ casted_model->calc(casted_data, r_f);
112 ✗ casted_model->calcDiff(casted_data, r_f);
113 float tol_f =
114 ✗ std::pow(model_num_diff.cast<float>().get_disturbance(), float(1. / 3.));
115 ✗ BOOST_CHECK(std::abs(data->a_value - casted_data->a_value) < tol_f);
116 ✗ BOOST_CHECK((data->Ar.cast<float>() - casted_data->Ar).isZero(tol_f));
117 ✗ }
118
119 ✗ void test_activation_bounds_with_infinity() {
120 ✗ Eigen::VectorXd lb(1);
121 ✗ Eigen::VectorXd ub(1);
122 double beta;
123 ✗ beta = 0.1;
124 ✗ lb[0] = 0;
125 ✗ ub[0] = std::numeric_limits<double>::infinity();
126
127 Eigen::VectorXd m =
128 ✗ 0.5 * (lb + Eigen::VectorXd::Constant(
129 ✗ lb.size(), std::numeric_limits<double>::max()));
130 Eigen::VectorXd d =
131 ✗ 0.5 * (Eigen::VectorXd::Constant(lb.size(),
132 ✗ std::numeric_limits<double>::max()) -
133 ✗ lb);
134 ✗ crocoddyl::ActivationBounds bounds(lb, ub, beta);
135 ✗ BOOST_CHECK(bounds.lb != m - beta * d);
136
137 // Checking that casted computation is the same
138 ✗ crocoddyl::ActivationBoundsTpl<float> casted_bounds = bounds.cast<float>();
139 ✗ BOOST_CHECK(bounds.lb.cast<float>() == casted_bounds.lb);
140 ✗ }
141
142 //----------------------------------------------------------------------------//
143
144 ✗ void register_unit_tests(ActivationModelTypes::Type activation_type) {
145 ✗ boost::test_tools::output_test_stream test_name;
146 ✗ test_name << "test_" << activation_type;
147 ✗ std::cout << "Running " << test_name.str() << std::endl;
148 ✗ test_suite* ts = BOOST_TEST_SUITE(test_name.str());
149 ✗ ts->add(BOOST_TEST_CASE(boost::bind(&test_construct_data, activation_type)));
150 ✗ ts->add(BOOST_TEST_CASE(
151 boost::bind(&test_calc_returns_a_value, activation_type)));
152 ✗ ts->add(BOOST_TEST_CASE(
153 boost::bind(&test_partial_derivatives_against_numdiff, activation_type)));
154 ✗ framework::master_test_suite().add(ts);
155 ✗ }
156
157 ✗ bool register_bounds_unit_test() {
158 ✗ boost::test_tools::output_test_stream test_name;
159 test_name << "test_"
160 ✗ << "ActivationBoundsInfinity";
161 ✗ std::cout << "Running " << test_name.str() << std::endl;
162 ✗ test_suite* ts = BOOST_TEST_SUITE(test_name.str());
163 ✗ ts->add(BOOST_TEST_CASE(boost::bind(&test_activation_bounds_with_infinity)));
164 ✗ framework::master_test_suite().add(ts);
165 ✗ return true;
166 ✗ }
167
168 ✗ bool init_function() {
169 ✗ for (size_t i = 0; i < ActivationModelTypes::all.size(); ++i) {
170 ✗ register_unit_tests(ActivationModelTypes::all[i]);
171 }
172 ✗ register_bounds_unit_test();
173 ✗ return true;
174 }
175
176 ✗ int main(int argc, char** argv) {
177 ✗ return ::boost::unit_test::unit_test_main(&init_function, argc, argv);
178 }
179