GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/core/cost-base.hpp
Date: 2025-01-30 11:01:55
Exec Total Coverage
Lines: 17 23 73.9%
Branches: 11 22 50.0%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2021, LAAS-CNRS, University of Edinburgh
5 // Copyright note valid unless otherwise stated in individual files.
6 // All rights reserved.
7 ///////////////////////////////////////////////////////////////////////////////
8
9 #ifndef CROCODDYL_CORE_COST_BASE_HPP_
10 #define CROCODDYL_CORE_COST_BASE_HPP_
11
12 #include <boost/make_shared.hpp>
13 #include <memory>
14
15 #include "crocoddyl/core/activation-base.hpp"
16 #include "crocoddyl/core/activations/quadratic.hpp"
17 #include "crocoddyl/core/data-collector-base.hpp"
18 #include "crocoddyl/core/fwd.hpp"
19 #include "crocoddyl/core/residual-base.hpp"
20 #include "crocoddyl/core/state-base.hpp"
21 #include "crocoddyl/core/utils/deprecate.hpp"
22
23 namespace crocoddyl {
24
25 /**
26 * @brief Abstract class for cost models
27 *
28 * A cost model is defined by the scalar activation function \f$a(\cdot)\f$ and
29 * by the residual function \f$\mathbf{r}(\cdot)\f$ as follows: \f[
30 * \ell(\mathbf{x},\mathbf{u}) = a(\mathbf{r}(\mathbf{x}, \mathbf{u})), \f]
31 * where the residual function depends on the state point
32 * \f$\mathbf{x}\in\mathcal{X}\f$, which lies in the state manifold described
33 * with a `nx`-tuple, its velocity \f$\dot{\mathbf{x}}\in
34 * T_{\mathbf{x}}\mathcal{X}\f$ that belongs to the tangent space with `ndx`
35 * dimension, and the control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$. The
36 * residual vector is defined by \f$\mathbf{r}\in\mathbb{R}^{nr}\f$ where `nr`
37 * describes its dimension in the Euclidean space. On the other hand, the
38 * activation function builds a cost value based on the definition of the
39 * residual vector. The residual vector has to be specialized in a derived
40 * classes.
41 *
42 * The main computations are carring out in `calc()` and `calcDiff()` routines.
43 * `calc()` computes the cost (and its residual) and `calcDiff()` computes the
44 * derivatives of the cost function (and its residual). Concretely speaking,
45 * `calcDiff()` builds a linear-quadratic approximation of the cost function
46 * with the form: \f$\mathbf{l_x}\in\mathbb{R}^{ndx}\f$,
47 * \f$\mathbf{l_u}\in\mathbb{R}^{nu}\f$,
48 * \f$\mathbf{l_{xx}}\in\mathbb{R}^{ndx\times ndx}\f$,
49 * \f$\mathbf{l_{xu}}\in\mathbb{R}^{ndx\times nu}\f$,
50 * \f$\mathbf{l_{uu}}\in\mathbb{R}^{nu\times nu}\f$ are the Jacobians and
51 * Hessians, respectively. Additionally, it is important to note that
52 * `calcDiff()` computes the derivatives using the latest stored values by
53 * `calc()`. Thus, we need to first run `calc()`.
54 *
55 * \sa `ActivationModelAbstractTpl`, `ResidualModelAbstractTpl` `calc()`,
56 * `calcDiff()`, `createData()`
57 */
58 template <typename _Scalar>
59 class CostModelAbstractTpl {
60 public:
61 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
62
63 typedef _Scalar Scalar;
64 typedef MathBaseTpl<Scalar> MathBase;
65 typedef CostDataAbstractTpl<Scalar> CostDataAbstract;
66 typedef StateAbstractTpl<Scalar> StateAbstract;
67 typedef ActivationModelAbstractTpl<Scalar> ActivationModelAbstract;
68 typedef ResidualModelAbstractTpl<Scalar> ResidualModelAbstract;
69 typedef ActivationModelQuadTpl<Scalar> ActivationModelQuad;
70 typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract;
71 typedef typename MathBase::VectorXs VectorXs;
72 typedef typename MathBase::MatrixXs MatrixXs;
73
74 /**
75 * @brief Initialize the cost model
76 *
77 * @param[in] state State of the dynamical system
78 * @param[in] activation Activation model
79 * @param[in] residual Residual model
80 */
81 CostModelAbstractTpl(std::shared_ptr<StateAbstract> state,
82 std::shared_ptr<ActivationModelAbstract> activation,
83 std::shared_ptr<ResidualModelAbstract> residual);
84
85 /**
86 * @brief Initialize the cost model
87 *
88 * @param[in] state State of the dynamical system
89 * @param[in] activation Activation model
90 * @param[in] nu Dimension of control vector
91 */
92 CostModelAbstractTpl(std::shared_ptr<StateAbstract> state,
93 std::shared_ptr<ActivationModelAbstract> activation,
94 const std::size_t nu);
95
96 /**
97 * @copybrief CostModelAbstractTpl()
98 *
99 * The default `nu` value is obtained from `StateAbstractTpl::get_nv()`.
100 *
101 * @param[in] state State of the dynamical system
102 * @param[in] activation Activation model
103 */
104 CostModelAbstractTpl(std::shared_ptr<StateAbstract> state,
105 std::shared_ptr<ActivationModelAbstract> activation);
106
107 /**
108 * @copybrief CostModelAbstractTpl()
109 *
110 * We use `ActivationModelQuadTpl` as a default activation model (i.e.,
111 * \f$a=\frac{1}{2}\|\mathbf{r}\|^2\f$)
112 *
113 * @param[in] state State of the dynamical system
114 * @param[in] residual Residual model
115 */
116 CostModelAbstractTpl(std::shared_ptr<StateAbstract> state,
117 std::shared_ptr<ResidualModelAbstract> residual);
118
119 /**
120 * @copybrief CostModelAbstractTpl()
121 *
122 * We use `ActivationModelQuadTpl` as a default activation model (i.e.,
123 * \f$a=\frac{1}{2}\|\mathbf{r}\|^2\f$)
124 *
125 * @param[in] state State of the system
126 * @param[in] nr Dimension of residual vector
127 * @param[in] nu Dimension of control vector
128 */
129 CostModelAbstractTpl(std::shared_ptr<StateAbstract> state,
130 const std::size_t nr, const std::size_t nu);
131
132 /**
133 * @copybrief CostModelAbstractTpl()
134 *
135 * We use `ActivationModelQuadTpl` as a default activation model (i.e.,
136 * \f$a=\frac{1}{2}\|\mathbf{r}\|^2\f$). Furthermore, the default `nu` value
137 * is obtained from `StateAbstractTpl::get_nv()`.
138 *
139 * @param[in] state State of the dynamical system
140 * @param[in] nr Dimension of residual vector
141 * @param[in] nu Dimension of control vector
142 */
143 CostModelAbstractTpl(std::shared_ptr<StateAbstract> state,
144 const std::size_t nr);
145 virtual ~CostModelAbstractTpl();
146
147 /**
148 * @brief Compute the cost value and its residual vector
149 *
150 * @param[in] data Cost data
151 * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
152 * @param[in] u Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
153 */
154 virtual void calc(const std::shared_ptr<CostDataAbstract>& data,
155 const Eigen::Ref<const VectorXs>& x,
156 const Eigen::Ref<const VectorXs>& u) = 0;
157
158 /**
159 * @brief Compute the total cost value for nodes that depends only on the
160 * state
161 *
162 * It updates the total cost based on the state only. This function is used in
163 * the terminal nodes of an optimal control problem.
164 *
165 * @param[in] data Cost data
166 * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
167 */
168 virtual void calc(const std::shared_ptr<CostDataAbstract>& data,
169 const Eigen::Ref<const VectorXs>& x);
170
171 /**
172 * @brief Compute the Jacobian and Hessian of cost and its residual vector
173 *
174 * It computes the Jacobian and Hessian of the cost function. It assumes that
175 * `calc()` has been run first.
176 *
177 * @param[in] data Cost data
178 * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
179 * @param[in] u Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
180 */
181 virtual void calcDiff(const std::shared_ptr<CostDataAbstract>& data,
182 const Eigen::Ref<const VectorXs>& x,
183 const Eigen::Ref<const VectorXs>& u) = 0;
184
185 /**
186 * @brief Compute the Jacobian and Hessian of the cost functions with respect
187 * to the state only
188 *
189 * It updates the Jacobian and Hessian of the cost function based on the state
190 * only. This function is used in the terminal nodes of an optimal control
191 * problem.
192 *
193 * @param[in] data Cost data
194 * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
195 */
196 virtual void calcDiff(const std::shared_ptr<CostDataAbstract>& data,
197 const Eigen::Ref<const VectorXs>& x);
198
199 /**
200 * @brief Create the cost data
201 *
202 * The default data contains objects to store the values of the cost, residual
203 * vector and their derivatives (first and second order derivatives). However,
204 * it is possible to specialize this function if we need to create additional
205 * data, for instance, to avoid dynamic memory allocation.
206 *
207 * @param data Data collector
208 * @return the cost data
209 */
210 virtual std::shared_ptr<CostDataAbstract> createData(
211 DataCollectorAbstract* const data);
212
213 /**
214 * @brief Return the state
215 */
216 const std::shared_ptr<StateAbstract>& get_state() const;
217
218 /**
219 * @brief Return the activation model
220 */
221 const std::shared_ptr<ActivationModelAbstract>& get_activation() const;
222
223 /**
224 * @brief Return the residual model
225 */
226 const std::shared_ptr<ResidualModelAbstract>& get_residual() const;
227
228 /**
229 * @brief Return the dimension of the control input
230 */
231 std::size_t get_nu() const;
232
233 /**
234 * @brief Print information on the cost model
235 */
236 template <class Scalar>
237 friend std::ostream& operator<<(std::ostream& os,
238 const CostModelAbstractTpl<Scalar>& model);
239
240 /**
241 * @brief Modify the cost reference
242 */
243 template <class ReferenceType>
244 void set_reference(ReferenceType ref);
245
246 /**
247 * @brief Return the cost reference
248 */
249 template <class ReferenceType>
250 ReferenceType get_reference();
251
252 /**
253 * @brief Print relevant information of the cost model
254 *
255 * @param[out] os Output stream object
256 */
257 virtual void print(std::ostream& os) const;
258
259 protected:
260 /**
261 * @copybrief set_reference()
262 */
263 virtual void set_referenceImpl(const std::type_info&, const void*);
264
265 /**
266 * @copybrief get_reference()
267 */
268 virtual void get_referenceImpl(const std::type_info&, void*);
269
270 std::shared_ptr<StateAbstract> state_; //!< State description
271 std::shared_ptr<ActivationModelAbstract> activation_; //!< Activation model
272 std::shared_ptr<ResidualModelAbstract> residual_; //!< Residual model
273 std::size_t nu_; //!< Control dimension
274 VectorXs unone_; //!< No control vector
275 };
276
277 template <typename _Scalar>
278 struct CostDataAbstractTpl {
279 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
280
281 typedef _Scalar Scalar;
282 typedef MathBaseTpl<Scalar> MathBase;
283 typedef ActivationDataAbstractTpl<Scalar> ActivationDataAbstract;
284 typedef ResidualDataAbstractTpl<Scalar> ResidualDataAbstract;
285 typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract;
286 typedef typename MathBase::VectorXs VectorXs;
287 typedef typename MathBase::MatrixXs MatrixXs;
288
289 template <template <typename Scalar> class Model>
290 954731 CostDataAbstractTpl(Model<Scalar>* const model,
291 DataCollectorAbstract* const data)
292 954731 : shared(data),
293 954731 activation(model->get_activation()->createData()),
294
1/2
✓ Branch 3 taken 477383 times.
✗ Branch 4 not taken.
954731 residual(model->get_residual()->createData(data)),
295 954731 cost(Scalar(0.)),
296
1/2
✓ Branch 4 taken 477383 times.
✗ Branch 5 not taken.
954731 Lx(model->get_state()->get_ndx()),
297
1/2
✓ Branch 2 taken 477383 times.
✗ Branch 3 not taken.
954731 Lu(model->get_nu()),
298
1/2
✓ Branch 7 taken 477383 times.
✗ Branch 8 not taken.
954731 Lxx(model->get_state()->get_ndx(), model->get_state()->get_ndx()),
299
1/2
✓ Branch 5 taken 477383 times.
✗ Branch 6 not taken.
954731 Lxu(model->get_state()->get_ndx(), model->get_nu()),
300
1/2
✓ Branch 4 taken 477383 times.
✗ Branch 5 not taken.
1909462 Luu(model->get_nu(), model->get_nu()) {
301
1/2
✓ Branch 1 taken 477383 times.
✗ Branch 2 not taken.
954731 Lx.setZero();
302
1/2
✓ Branch 1 taken 477383 times.
✗ Branch 2 not taken.
954731 Lu.setZero();
303
1/2
✓ Branch 1 taken 477383 times.
✗ Branch 2 not taken.
954731 Lxx.setZero();
304
1/2
✓ Branch 1 taken 477383 times.
✗ Branch 2 not taken.
954731 Lxu.setZero();
305
1/2
✓ Branch 1 taken 477383 times.
✗ Branch 2 not taken.
954731 Luu.setZero();
306 954731 }
307 479889 virtual ~CostDataAbstractTpl() {}
308
309 DEPRECATED(
310 "Use residual.r", const VectorXs& get_r() const { return residual->r; };)
311 DEPRECATED(
312 "Use residual.Rx",
313 const MatrixXs& get_Rx() const { return residual->Rx; };)
314 DEPRECATED(
315 "Use residual.Ru",
316 const MatrixXs& get_Ru() const { return residual->Ru; };)
317 DEPRECATED(
318 "Use residual.r", void set_r(const VectorXs& r) { residual->r = r; };)
319 DEPRECATED(
320 "Use residual.Rx",
321 void set_Rx(const MatrixXs& Rx) { residual->Rx = Rx; };)
322 DEPRECATED(
323 "Use residual.Ru",
324 void set_Ru(const MatrixXs& Ru) { residual->Ru = Ru; };)
325
326 DataCollectorAbstract* shared;
327 std::shared_ptr<ActivationDataAbstract> activation;
328 std::shared_ptr<ResidualDataAbstract> residual;
329 Scalar cost;
330 VectorXs Lx;
331 VectorXs Lu;
332 MatrixXs Lxx;
333 MatrixXs Lxu;
334 MatrixXs Luu;
335 };
336
337 } // namespace crocoddyl
338
339 /* --- Details -------------------------------------------------------------- */
340 /* --- Details -------------------------------------------------------------- */
341 /* --- Details -------------------------------------------------------------- */
342 #include "crocoddyl/core/cost-base.hxx"
343
344 #endif // CROCODDYL_CORE_COST_BASE_HPP_
345