GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/crocoddyl/core/residual-base.hpp Lines: 11 13 84.6 %
Date: 2024-02-13 11:12:33 Branches: 10 20 50.0 %

Line Branch Exec Source
1
///////////////////////////////////////////////////////////////////////////////
2
// BSD 3-Clause License
3
//
4
// Copyright (C) 2021-2023, University of Edinburgh, Heriot-Watt University
5
// Copyright note valid unless otherwise stated in individual files.
6
// All rights reserved.
7
///////////////////////////////////////////////////////////////////////////////
8
9
#ifndef CROCODDYL_CORE_RESIDUAL_BASE_HPP_
10
#define CROCODDYL_CORE_RESIDUAL_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/cost-base.hpp"
17
#include "crocoddyl/core/data-collector-base.hpp"
18
#include "crocoddyl/core/fwd.hpp"
19
#include "crocoddyl/core/state-base.hpp"
20
21
namespace crocoddyl {
22
23
/**
24
 * @brief Abstract class for residual models
25
 *
26
 * A residual model defines a vector function \f$\mathbf{r}(\mathbf{x},
27
 * \mathbf{u})\mathbb{R}^{nr}\f$ where `nr` describes its dimension in the
28
 * Euclidean space. This function depends on the state point
29
 * \f$\mathbf{x}\in\mathcal{X}\f$, which lies in the state manifold described
30
 * with a `nq`-tuple, its velocity \f$\dot{\mathbf{x}}\in
31
 * T_{\mathbf{x}}\mathcal{X}\f$ that belongs to the tangent space with `nv`
32
 * dimension, and the control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$. The
33
 * residual function can used across cost and constraint models.
34
 *
35
 * The main computations are carring out in `calc` and `calcDiff` routines.
36
 * `calc` computes the residual vector and `calcDiff` computes the Jacobians of
37
 * the residual function. Additionally, it is important to note that
38
 * `calcDiff()` computes the Jacobians using the latest stored values by
39
 * `calc()`. Thus, we need to first run `calc()`.
40
 *
41
 * \sa `StateAbstractTpl`, `calc()`, `calcDiff()`, `createData()`
42
 */
43
template <typename _Scalar>
44
class ResidualModelAbstractTpl {
45
 public:
46
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
47
48
  typedef _Scalar Scalar;
49
  typedef MathBaseTpl<Scalar> MathBase;
50
  typedef ResidualDataAbstractTpl<Scalar> ResidualDataAbstract;
51
  typedef CostDataAbstractTpl<Scalar> CostDataAbstract;
52
  typedef ActivationDataAbstractTpl<Scalar> ActivationDataAbstract;
53
  typedef StateAbstractTpl<Scalar> StateAbstract;
54
  typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract;
55
  typedef typename MathBase::VectorXs VectorXs;
56
  typedef typename MathBase::MatrixXs MatrixXs;
57
  typedef typename MathBase::DiagonalMatrixXs DiagonalMatrixXs;
58
59
  /**
60
   * @brief Initialize the residual model
61
   *
62
   * @param[in] state        State of the system
63
   * @param[in] nr           Dimension of residual vector
64
   * @param[in] nu           Dimension of control vector
65
   * @param[in] q_dependent  Define if the residual function depends on q
66
   * (default true)
67
   * @param[in] v_dependent  Define if the residual function depends on v
68
   * (default true)
69
   * @param[in] u_dependent  Define if the residual function depends on u
70
   * (default true)
71
   */
72
  ResidualModelAbstractTpl(boost::shared_ptr<StateAbstract> state,
73
                           const std::size_t nr, const std::size_t nu,
74
                           const bool q_dependent = true,
75
                           const bool v_dependent = true,
76
                           const bool u_dependent = true);
77
78
  /**
79
   * @copybrief ResidualModelAbstractTpl()
80
   *
81
   * The default `nu` value is obtained from `StateAbstractTpl::get_nv()`.
82
   *
83
   * @param[in] state        State of the system
84
   * @param[in] nr           Dimension of residual vector
85
   * @param[in] q_dependent  Define if the residual function depends on q
86
   * (default true)
87
   * @param[in] v_dependent  Define if the residual function depends on v
88
   * (default true)
89
   * @param[in] u_dependent  Define if the residual function depends on u
90
   * (default true)
91
   */
92
  ResidualModelAbstractTpl(boost::shared_ptr<StateAbstract> state,
93
                           const std::size_t nr, const bool q_dependent = true,
94
                           const bool v_dependent = true,
95
                           const bool u_dependent = true);
96
  virtual ~ResidualModelAbstractTpl();
97
98
  /**
99
   * @brief Compute the residual vector
100
   *
101
   * @param[in] data  Residual data
102
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
103
   * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
104
   */
105
  virtual void calc(const boost::shared_ptr<ResidualDataAbstract>& data,
106
                    const Eigen::Ref<const VectorXs>& x,
107
                    const Eigen::Ref<const VectorXs>& u);
108
109
  /**
110
   * @brief Compute the residual vector for nodes that depends only on the state
111
   *
112
   * It updates the residual vector based on the state only. This function is
113
   * used in the terminal nodes of an optimal control problem.
114
   *
115
   * @param[in] data  Residual data
116
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
117
   */
118
  virtual void calc(const boost::shared_ptr<ResidualDataAbstract>& data,
119
                    const Eigen::Ref<const VectorXs>& x);
120
121
  /**
122
   * @brief Compute the Jacobian of the residual vector
123
   *
124
   * It computes the Jacobian the residual function. It assumes that `calc()`
125
   * has been run first.
126
   *
127
   * @param[in] data  Residual data
128
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
129
   * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
130
   */
131
  virtual void calcDiff(const boost::shared_ptr<ResidualDataAbstract>& data,
132
                        const Eigen::Ref<const VectorXs>& x,
133
                        const Eigen::Ref<const VectorXs>& u);
134
135
  /**
136
   * @brief Compute the Jacobian of the residual functions with respect to the
137
   * state only
138
   *
139
   * It updates the Jacobian of the residual function based on the state only.
140
   * This function is used in the terminal nodes of an optimal control problem.
141
   *
142
   * @param[in] data  Residual data
143
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
144
   */
145
  virtual void calcDiff(const boost::shared_ptr<ResidualDataAbstract>& data,
146
                        const Eigen::Ref<const VectorXs>& x);
147
148
  /**
149
   * @brief Create the residual data
150
   *
151
   * The default data contains objects to store the values of the residual
152
   * vector and their Jacobians. However, it is possible to specialize this
153
   * function if we need to create additional data, for instance, to avoid
154
   * dynamic memory allocation.
155
   *
156
   * @param data  Data collector
157
   * @return the residual data
158
   */
159
  virtual boost::shared_ptr<ResidualDataAbstract> createData(
160
      DataCollectorAbstract* const data);
161
162
  /**
163
   * @brief Compute the derivative of the cost function
164
   *
165
   * This function assumes that the derivatives of the activation and residual
166
   * are computed via calcDiff functions.
167
   *
168
   * @param cdata     Cost data
169
   * @param rdata     Residual data
170
   * @param adata     Activation data
171
   * @param update_u  Update the derivative of the cost function w.r.t. to the
172
   * control if True.
173
   */
174
  virtual void calcCostDiff(
175
      const boost::shared_ptr<CostDataAbstract>& cdata,
176
      const boost::shared_ptr<ResidualDataAbstract>& rdata,
177
      const boost::shared_ptr<ActivationDataAbstract>& adata,
178
      const bool update_u = true);
179
180
  /**
181
   * @brief Return the state
182
   */
183
  const boost::shared_ptr<StateAbstract>& get_state() const;
184
185
  /**
186
   * @brief Return the dimension of the residual vector
187
   */
188
  std::size_t get_nr() const;
189
190
  /**
191
   * @brief Return the dimension of the control input
192
   */
193
  std::size_t get_nu() const;
194
195
  /**
196
   * @brief Return true if the residual function depends on q
197
   */
198
  bool get_q_dependent() const;
199
200
  /**
201
   * @brief Return true if the residual function depends on v
202
   */
203
  bool get_v_dependent() const;
204
205
  /**
206
   * @brief Return true if the residual function depends on u
207
   */
208
  bool get_u_dependent() const;
209
210
  /**
211
   * @brief Print information on the residual model
212
   */
213
  template <class Scalar>
214
  friend std::ostream& operator<<(
215
      std::ostream& os, const ResidualModelAbstractTpl<Scalar>& model);
216
217
  /**
218
   * @brief Print relevant information of the residual model
219
   *
220
   * @param[out] os  Output stream object
221
   */
222
  virtual void print(std::ostream& os) const;
223
224
 protected:
225
  boost::shared_ptr<StateAbstract> state_;  //!< State description
226
  std::size_t nr_;                          //!< Residual vector dimension
227
  std::size_t nu_;                          //!< Control dimension
228
  VectorXs unone_;                          //!< No control vector
229
  bool q_dependent_;  //!< Label that indicates if the residual function depends
230
                      //!< on q
231
  bool v_dependent_;  //!< Label that indicates if the residual function depends
232
                      //!< on v
233
  bool u_dependent_;  //!< Label that indicates if the residual function depends
234
                      //!< on u
235
};
236
237
template <typename _Scalar>
238
struct ResidualDataAbstractTpl {
239
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
240
241
  typedef _Scalar Scalar;
242
  typedef MathBaseTpl<Scalar> MathBase;
243
  typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract;
244
  typedef typename MathBase::VectorXs VectorXs;
245
  typedef typename MathBase::MatrixXs MatrixXs;
246
247
  template <template <typename Scalar> class Model>
248
1453699
  ResidualDataAbstractTpl(Model<Scalar>* const model,
249
                          DataCollectorAbstract* const data)
250
      : shared(data),
251
        r(model->get_nr()),
252
1453699
        Rx(model->get_nr(), model->get_state()->get_ndx()),
253
        Ru(model->get_nr(), model->get_nu()),
254
1453699
        Arr_Rx(model->get_nr(), model->get_state()->get_ndx()),
255


1453699
        Arr_Ru(model->get_nr(), model->get_nu()) {
256
1453699
    r.setZero();
257
1453699
    Rx.setZero();
258
1453699
    Ru.setZero();
259
1453699
    Arr_Rx.setZero();
260
1453699
    Arr_Ru.setZero();
261
1453699
  }
262
784721
  virtual ~ResidualDataAbstractTpl() {}
263
264
  DataCollectorAbstract* shared;  //!< Shared data allocated by the action model
265
  VectorXs r;                     //!< Residual vector
266
  MatrixXs Rx;  //!< Jacobian of the residual vector with respect the state
267
  MatrixXs Ru;  //!< Jacobian of the residual vector with respect the control
268
  MatrixXs Arr_Rx;
269
  MatrixXs Arr_Ru;
270
};
271
272
}  // namespace crocoddyl
273
274
/* --- Details -------------------------------------------------------------- */
275
/* --- Details -------------------------------------------------------------- */
276
/* --- Details -------------------------------------------------------------- */
277
#include "crocoddyl/core/residual-base.hxx"
278
279
#endif  // CROCODDYL_CORE_RESIDUAL_BASE_HPP_