GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/crocoddyl/core/cost-base.hpp Lines: 14 22 63.6 %
Date: 2024-02-13 11:12:33 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 <boost/shared_ptr.hpp>
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(boost::shared_ptr<StateAbstract> state,
82
                       boost::shared_ptr<ActivationModelAbstract> activation,
83
                       boost::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(boost::shared_ptr<StateAbstract> state,
93
                       boost::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(boost::shared_ptr<StateAbstract> state,
105
                       boost::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(boost::shared_ptr<StateAbstract> state,
117
                       boost::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(boost::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(boost::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 boost::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 boost::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 boost::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 boost::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 boost::shared_ptr<CostDataAbstract> createData(
211
      DataCollectorAbstract* const data);
212
213
  /**
214
   * @brief Return the state
215
   */
216
  const boost::shared_ptr<StateAbstract>& get_state() const;
217
218
  /**
219
   * @brief Return the activation model
220
   */
221
  const boost::shared_ptr<ActivationModelAbstract>& get_activation() const;
222
223
  /**
224
   * @brief Return the residual model
225
   */
226
  const boost::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
  boost::shared_ptr<StateAbstract> state_;  //!< State description
271
  boost::shared_ptr<ActivationModelAbstract> activation_;  //!< Activation model
272
  boost::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
953879
  CostDataAbstractTpl(Model<Scalar>* const model,
291
                      DataCollectorAbstract* const data)
292
      : shared(data),
293
953879
        activation(model->get_activation()->createData()),
294
953879
        residual(model->get_residual()->createData(data)),
295
        cost(Scalar(0.)),
296
953879
        Lx(model->get_state()->get_ndx()),
297
        Lu(model->get_nu()),
298
1907758
        Lxx(model->get_state()->get_ndx(), model->get_state()->get_ndx()),
299
953879
        Lxu(model->get_state()->get_ndx(), model->get_nu()),
300



2861637
        Luu(model->get_nu(), model->get_nu()) {
301
953879
    Lx.setZero();
302
953879
    Lu.setZero();
303
953879
    Lxx.setZero();
304
953879
    Lxu.setZero();
305
953879
    Luu.setZero();
306
953879
  }
307
479037
  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
  boost::shared_ptr<ActivationDataAbstract> activation;
328
  boost::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_