GCC Code Coverage Report


Directory: ./
File: bindings/python/crocoddyl/core/cost-base.cpp
Date: 2025-03-26 19:23:43
Exec Total Coverage
Lines: 53 55 96.4%
Branches: 110 220 50.0%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2025, LAAS-CNRS, University of Edinburgh,
5 // Heriot-Watt University
6 // Copyright note valid unless otherwise stated in individual files.
7 // All rights reserved.
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #include "python/crocoddyl/core/cost-base.hpp"
11
12 #include "python/crocoddyl/utils/deprecate.hpp"
13
14 namespace crocoddyl {
15 namespace python {
16
17 template <typename Model>
18 struct CostModelAbstractVisitor
19 : public bp::def_visitor<CostModelAbstractVisitor<Model>> {
20 typedef typename Model::CostModel CostModel;
21 typedef typename Model::CostData CostData;
22 typedef typename Model::State State;
23 typedef typename Model::ActivationModel ActivationModel;
24 typedef typename Model::ResidualModel ResidualModel;
25 typedef typename Model::VectorXs VectorXs;
26 template <class PyClass>
27 40 void visit(PyClass& cl) const {
28
2/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
40 cl.def(bp::init<std::shared_ptr<State>, std::shared_ptr<ActivationModel>,
29 std::size_t>(
30 bp::args("self", "state", "activation", "nu"),
31 "Initialize the cost model.\n\n"
32 ":param state: state description\n"
33 ":param activation: activation model\n"
34 ":param nu: dimension of control vector (default state.nv)"))
35
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .def(bp::init<std::shared_ptr<State>, std::shared_ptr<ActivationModel>>(
36 bp::args("self", "state", "activation"),
37 "Initialize the cost model.\n\n"
38 ":param state: state description\n"
39 ":param activation: activation model"))
40
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .def(bp::init<std::shared_ptr<State>, std::shared_ptr<ResidualModel>>(
41 bp::args("self", "state", "residual"),
42 "Initialize the cost model.\n\n"
43 ":param state: state description\n"
44 ":param residual: residual model"))
45
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .def(bp::init<std::shared_ptr<State>, std::size_t, std::size_t>(
46 bp::args("self", "state", "nr", "nu"),
47 "Initialize the cost model.\n\n"
48 "We use ActivationModelQuad as a default activation model (i.e., "
49 "a=0.5*||r||^2).\n"
50 ":param state: state description\n"
51 ":param nr: dimension of residual vector\n"
52 ":param nu: dimension of control vector (default state.nv)"))
53
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .def(bp::init<std::shared_ptr<State>, std::size_t>(
54 bp::args("self", "state", "nr"),
55 "Initialize the cost model.\n\n"
56 "We use ActivationModelQuad as a default activation model (i.e., "
57 "a=0.5*||r||^2), and the default nu value is obtained from "
58 "state.nv.\n"
59 ":param state: state description\n"
60 ":param nr: dimension of cost vector"))
61
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .def("calc", pure_virtual(&Model::calc),
62 bp::args("self", "data", "x", "u"),
63 "Compute the cost value and its residuals.\n\n"
64 ":param data: cost data\n"
65 ":param x: state point (dim. state.nx)\n"
66 ":param u: control input (dim. nu)")
67
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
80 .def(
68 "calc",
69 static_cast<void (CostModel::*)(const std::shared_ptr<CostData>&,
70 const Eigen::Ref<const VectorXs>&)>(
71 &CostModel::calc),
72 bp::args("self", "data", "x"),
73 "Compute the total cost value for nodes that depends only on the "
74 "state.\n\n"
75 "It updates the total cost based on the state only. This function "
76 "is used in the terminal nodes of an optimal control problem.\n"
77 ":param data: cost data\n"
78 ":param x: state point (dim. state.nx)")
79
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .def("calcDiff", pure_virtual(&Model::calcDiff),
80 bp::args("self", "data", "x", "u"),
81 "Compute the derivatives of the cost function and its "
82 "residuals.\n\n"
83 "It computes the partial derivatives of the cost function. It "
84 "assumes that calc has been run first.\n"
85 ":param data: cost data\n"
86 ":param x: state point (dim. state.nx)\n"
87 ":param u: control input (dim. nu)")
88
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
80 .def(
89 "calcDiff",
90 static_cast<void (CostModel::*)(const std::shared_ptr<CostData>&,
91 const Eigen::Ref<const VectorXs>&)>(
92 &CostModel::calcDiff),
93 bp::args("self", "data", "x"),
94 "Compute the Jacobian and Hessian of the cost functions with "
95 "respect to the state only.\n\n"
96 "It updates the Jacobian and Hessian of the cost function based on "
97 "the state only. This function is used in the terminal nodes of an "
98 "optimal control problem.\n"
99 ":param data: cost data\n"
100 ":param x: state point (dim. state.nx)")
101
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
80 .def("createData", &Model::createData,
102 bp::with_custodian_and_ward_postcall<0, 2>(),
103 bp::args("self", "data"),
104 "Create the cost data.\n\n"
105 "Each cost model has its own data that needs to be allocated. "
106 "This function returns the allocated data for a predefined cost.\n"
107 ":param data: shared data\n"
108 ":return cost data.")
109
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
40 .def("createData", &Model::default_createData,
110 bp::with_custodian_and_ward_postcall<0, 2>())
111
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
40 .add_property(
112 "state",
113 bp::make_function(&Model::get_state,
114 40 bp::return_value_policy<bp::return_by_value>()),
115 "state description")
116
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
40 .add_property(
117 "activation",
118 bp::make_function(&Model::get_activation,
119 40 bp::return_value_policy<bp::return_by_value>()),
120 "activation model")
121
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
40 .add_property(
122 "residual",
123 bp::make_function(&Model::get_residual,
124 40 bp::return_value_policy<bp::return_by_value>()),
125 "residual model")
126
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
40 .add_property("nu", bp::make_function(&Model::get_nu),
127 "dimension of control vector");
128 40 }
129 };
130
131 template <typename Data>
132 struct CostDataAbstractVisitor
133 : public bp::def_visitor<CostDataAbstractVisitor<Data>> {
134 template <class PyClass>
135 40 void visit(PyClass& cl) const {
136
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
40 cl.add_property(
137 "shared",
138 40 bp::make_getter(&Data::shared, bp::return_internal_reference<>()),
139 "shared data")
140
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
40 .add_property(
141 "activation",
142 bp::make_getter(&Data::activation,
143 40 bp::return_value_policy<bp::return_by_value>()),
144 "activation data")
145
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
40 .add_property(
146 "residual",
147 bp::make_getter(&Data::residual,
148 40 bp::return_value_policy<bp::return_by_value>()),
149 "residual data")
150
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .add_property(
151 "cost",
152 bp::make_getter(&Data::cost,
153 40 bp::return_value_policy<bp::return_by_value>()),
154 bp::make_setter(&Data::cost), "cost value")
155
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .add_property(
156 40 "Lx", bp::make_getter(&Data::Lx, bp::return_internal_reference<>()),
157 bp::make_setter(&Data::Lx), "Jacobian of the cost")
158
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .add_property(
159 40 "Lu", bp::make_getter(&Data::Lu, bp::return_internal_reference<>()),
160 bp::make_setter(&Data::Lu), "Jacobian of the cost")
161
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .add_property(
162 "Lxx",
163 40 bp::make_getter(&Data::Lxx, bp::return_internal_reference<>()),
164 bp::make_setter(&Data::Lxx), "Hessian of the cost")
165
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .add_property(
166 "Lxu",
167 40 bp::make_getter(&Data::Lxu, bp::return_internal_reference<>()),
168 bp::make_setter(&Data::Lxu), "Hessian of the cost")
169
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .add_property(
170 "Luu",
171 40 bp::make_getter(&Data::Luu, bp::return_internal_reference<>()),
172 bp::make_setter(&Data::Luu), "Hessian of the cost")
173
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .add_property(
174 "r",
175 bp::make_function(&Data::get_r,
176
2/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
80 deprecated<bp::return_internal_reference<>>(
177 "Deprecated. Use residual.r.")),
178 bp::make_function(&Data::set_r,
179
2/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
80 deprecated<>("Deprecated. Use residual.r.")),
180 "cost residual")
181
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .add_property(
182 "Rx",
183 bp::make_function(&Data::get_Rx,
184
2/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
80 deprecated<bp::return_internal_reference<>>(
185 "Deprecated. Use residual.Rx.")),
186 bp::make_function(&Data::set_Rx,
187
2/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
80 deprecated<>("Deprecated. Use residual.Rx.")),
188 "Jacobian of the cost residual")
189
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
80 .add_property(
190 "Ru",
191 bp::make_function(&Data::get_Ru,
192
2/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
80 deprecated<bp::return_internal_reference<>>(
193 "Deprecated. Use residual.Ru.")),
194 bp::make_function(&Data::set_Ru,
195
2/4
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
80 deprecated<>("Deprecated. Use residual.Ru.")),
196 "Jacobian of the cost residual");
197 40 }
198 };
199
200 #define CROCODDYL_COST_MODEL_ABSTRACT_PYTHON_BINDINGS(Scalar) \
201 typedef CostModelAbstractTpl<Scalar> Model; \
202 typedef CostModelAbstractTpl_wrap<Scalar> Model_wrap; \
203 typedef StateAbstractTpl<Scalar> State; \
204 typedef Model::ActivationModelAbstract ActivationModel; \
205 typedef Model::ResidualModelAbstract ResidualModel; \
206 bp::register_ptr_to_python<std::shared_ptr<Model>>(); \
207 bp::class_<Model_wrap, boost::noncopyable>( \
208 "CostModelAbstract", \
209 "Abstract multibody cost models.\n\n" \
210 "In Crocoddyl, a cost model is defined by the scalar activation " \
211 "function a(.) and by the residual function r(.) as follows:\n" \
212 " cost = a(r(x, u)),\n" \
213 "where the residual function depends on the state point x, which lies " \
214 "in the state manifold described with a nq-tuple, its velocity xd that " \
215 "belongs to the tangent space with nv dimension, and the control input " \
216 "u. The dimension of the residual vector is defined by nr, which " \
217 "belongs to the Euclidean space. On the other hand, the activation " \
218 "function builds a cost value based on the definition of the residual " \
219 "vector. The residual vector has to be specialized in a derived " \
220 "classes.", \
221 bp::init<std::shared_ptr<State>, std::shared_ptr<ActivationModel>, \
222 std::shared_ptr<ResidualModel>>( \
223 bp::args("self", "state", "activation", "residual"), \
224 "Initialize the cost model.\n\n" \
225 ":param state: state description\n" \
226 ":param activation: activation model\n" \
227 ":param residual: residual model")) \
228 .def(CostModelAbstractVisitor<Model_wrap>()) \
229 .def(PrintableVisitor<Model_wrap>()) \
230 .def(CopyableVisitor<Model_wrap>());
231
232 #define CROCODDYL_COST_DATA_ABSTRACT_PYTHON_BINDINGS(Scalar) \
233 typedef CostDataAbstractTpl<Scalar> Data; \
234 typedef CostModelAbstractTpl<Scalar> Model; \
235 typedef Model::DataCollectorAbstract DataCollector; \
236 bp::register_ptr_to_python<std::shared_ptr<Data>>(); \
237 bp::class_<Data, boost::noncopyable>( \
238 "CostDataAbstract", "Abstract class for cost data.\n\n", \
239 bp::init<Model*, DataCollector*>( \
240 bp::args("self", "model", "data"), \
241 "Create common data shared between cost models.\n\n" \
242 ":param model: cost model\n" \
243 ":param data: shared data")[bp::with_custodian_and_ward< \
244 1, 2, bp::with_custodian_and_ward<1, 3>>()]) \
245 .def(CostDataAbstractVisitor<Data>()) \
246 .def(CopyableVisitor<Data>());
247
248 10 void exposeCostAbstract() {
249 // TODO: Remove once the deprecated update call has been removed in a future
250 // release
251 #pragma GCC diagnostic push
252 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
253
254
15/30
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 10 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 10 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 10 times.
✗ Branch 16 not taken.
✓ Branch 21 taken 10 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 10 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 10 times.
✗ Branch 28 not taken.
✓ Branch 32 taken 10 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 10 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 10 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 10 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 10 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 10 times.
✗ Branch 48 not taken.
✓ Branch 50 taken 10 times.
✗ Branch 51 not taken.
20 CROCODDYL_PYTHON_SCALARS(CROCODDYL_COST_MODEL_ABSTRACT_PYTHON_BINDINGS)
255
15/30
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 10 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 10 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 10 times.
✗ Branch 16 not taken.
✓ Branch 21 taken 10 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 10 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 10 times.
✗ Branch 28 not taken.
✓ Branch 32 taken 10 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 10 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 10 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 10 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 10 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 10 times.
✗ Branch 48 not taken.
✓ Branch 50 taken 10 times.
✗ Branch 51 not taken.
20 CROCODDYL_PYTHON_SCALARS(CROCODDYL_COST_DATA_ABSTRACT_PYTHON_BINDINGS)
256
257 #pragma GCC diagnostic pop
258 10 }
259
260 } // namespace python
261 } // namespace crocoddyl
262