GCC Code Coverage Report


Directory: ./
File: unittest/test_activations.cpp
Date: 2025-05-13 10:30:51
Exec Total Coverage
Lines: 0 83 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