GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/crocoddyl/core/action-base.hpp Lines: 27 29 93.1 %
Date: 2024-02-13 11:12:33 Branches: 36 72 50.0 %

Line Branch Exec Source
1
///////////////////////////////////////////////////////////////////////////////
2
// BSD 3-Clause License
3
//
4
// Copyright (C) 2019-2023, LAAS-CNRS, University of Edinburgh,
5
//                          University of Oxford, Heriot-Watt University
6
// Copyright note valid unless otherwise stated in individual files.
7
// All rights reserved.
8
///////////////////////////////////////////////////////////////////////////////
9
10
#ifndef CROCODDYL_CORE_ACTION_BASE_HPP_
11
#define CROCODDYL_CORE_ACTION_BASE_HPP_
12
13
#include <boost/make_shared.hpp>
14
#include <boost/shared_ptr.hpp>
15
#include <stdexcept>
16
17
#include "crocoddyl/core/fwd.hpp"
18
#include "crocoddyl/core/state-base.hpp"
19
#include "crocoddyl/core/utils/math.hpp"
20
21
namespace crocoddyl {
22
23
/**
24
 * @brief Abstract class for action model
25
 *
26
 * An action model combines dynamics, cost functions and constraints. Each node,
27
 * in our optimal control problem, is described through an action model. Every
28
 * time that we want describe a problem, we need to provide ways of computing
29
 * the dynamics, cost functions, constraints and their derivatives. All these is
30
 * described inside the action model.
31
 *
32
 * Concretely speaking, the action model describes a time-discrete action model
33
 * with a first-order ODE along a cost function, i.e.
34
 *  - the state \f$\mathbf{z}\in\mathcal{Z}\f$ lies in a manifold described with
35
 * a `nx`-tuple,
36
 *  - the state rate \f$\mathbf{\dot{x}}\in T_{\mathbf{q}}\mathcal{Q}\f$ is the
37
 * tangent vector to the state manifold with `ndx` dimension,
38
 *  - the control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$ is an Euclidean
39
 * vector
40
 *  - \f$\mathbf{r}(\cdot)\f$ and \f$a(\cdot)\f$ are the residual and activation
41
 * functions (see `ResidualModelAbstractTpl` and `ActivationModelAbstractTpl`,
42
 * respetively),
43
 *  - \f$\mathbf{g}(\cdot)\in\mathbb{R}^{ng}\f$ and
44
 * \f$\mathbf{h}(\cdot)\in\mathbb{R}^{nh}\f$ are the inequality and equality
45
 * vector functions, respectively.
46
 *
47
 * The computation of these equations are carried out out inside `calc()`
48
 * function. In short, this function computes the system acceleration, cost and
49
 * constraints values (also called constraints violations). This procedure is
50
 * equivalent to running a forward pass of the action model.
51
 *
52
 * However, during numerical optimization, we also need to run backward passes
53
 * of the action model. These calculations are performed by `calcDiff()`. In
54
 * short, this method builds a linear-quadratic approximation of the action
55
 * model, i.e.: \f[ \begin{aligned}
56
 * &\delta\mathbf{x}_{k+1} =
57
 * \mathbf{f_x}\delta\mathbf{x}_k+\mathbf{f_u}\delta\mathbf{u}_k,
58
 * &\textrm{(dynamics)}\\
59
 * &\ell(\delta\mathbf{x}_k,\delta\mathbf{u}_k) = \begin{bmatrix}1
60
 * \\ \delta\mathbf{x}_k \\ \delta\mathbf{u}_k\end{bmatrix}^T \begin{bmatrix}0 &
61
 * \mathbf{\ell_x}^T & \mathbf{\ell_u}^T \\ \mathbf{\ell_x} & \mathbf{\ell_{xx}}
62
 * &
63
 * \mathbf{\ell_{ux}}^T \\
64
 * \mathbf{\ell_u} & \mathbf{\ell_{ux}} & \mathbf{\ell_{uu}}\end{bmatrix}
65
 * \begin{bmatrix}1 \\ \delta\mathbf{x}_k \\
66
 * \delta\mathbf{u}_k\end{bmatrix}, &\textrm{(cost)}\\
67
 * &\mathbf{g}(\delta\mathbf{x}_k,\delta\mathbf{u}_k)<\mathbf{0},
68
 * &\textrm{(inequality constraint)}\\
69
 * &\mathbf{h}(\delta\mathbf{x}_k,\delta\mathbf{u}_k)=\mathbf{0},
70
 * &\textrm{(equality constraint)} \end{aligned} \f] where
71
 *  - \f$\mathbf{f_x}\in\mathbb{R}^{ndx\times ndx}\f$ and
72
 * \f$\mathbf{f_u}\in\mathbb{R}^{ndx\times nu}\f$ are the Jacobians of the
73
 * dynamics,
74
 *  - \f$\mathbf{\ell_x}\in\mathbb{R}^{ndx}\f$ and
75
 * \f$\mathbf{\ell_u}\in\mathbb{R}^{nu}\f$ are the Jacobians of the cost
76
 * function,
77
 *  - \f$\mathbf{\ell_{xx}}\in\mathbb{R}^{ndx\times ndx}\f$,
78
 * \f$\mathbf{\ell_{xu}}\in\mathbb{R}^{ndx\times nu}\f$ and
79
 * \f$\mathbf{\ell_{uu}}\in\mathbb{R}^{nu\times nu}\f$ are the Hessians of the
80
 * cost function,
81
 *  - \f$\mathbf{g_x}\in\mathbb{R}^{ng\times ndx}\f$ and
82
 * \f$\mathbf{g_u}\in\mathbb{R}^{ng\times nu}\f$ are the Jacobians of the
83
 * inequality constraints, and
84
 *  - \f$\mathbf{h_x}\in\mathbb{R}^{nh\times ndx}\f$ and
85
 * \f$\mathbf{h_u}\in\mathbb{R}^{nh\times nu}\f$ are the Jacobians of the
86
 * equality constraints.
87
 *
88
 * Additionally, it is important to note that `calcDiff()` computes the
89
 * derivatives using the latest stored values by `calc()`. Thus, we need to
90
 * first run `calc()`.
91
 *
92
 * \sa `calc()`, `calcDiff()`, `createData()`
93
 */
94
template <typename _Scalar>
95
class ActionModelAbstractTpl {
96
 public:
97
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
98
99
  typedef _Scalar Scalar;
100
  typedef MathBaseTpl<Scalar> MathBase;
101
  typedef ActionDataAbstractTpl<Scalar> ActionDataAbstract;
102
  typedef StateAbstractTpl<Scalar> StateAbstract;
103
  typedef typename MathBase::VectorXs VectorXs;
104
105
  /**
106
   * @brief Initialize the action model
107
   *
108
   * @param[in] state  State description
109
   * @param[in] nu     Dimension of control vector
110
   * @param[in] nr     Dimension of cost-residual vector
111
   * @param[in] ng     Number of inequality constraints
112
   * @param[in] nh     Number of equality constraints
113
   */
114
  ActionModelAbstractTpl(boost::shared_ptr<StateAbstract> state,
115
                         const std::size_t nu, const std::size_t nr = 0,
116
                         const std::size_t ng = 0, const std::size_t nh = 0);
117
  virtual ~ActionModelAbstractTpl();
118
119
  /**
120
   * @brief Compute the next state and cost value
121
   *
122
   * @param[in] data  Action data
123
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
124
   * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
125
   */
126
  virtual void calc(const boost::shared_ptr<ActionDataAbstract>& data,
127
                    const Eigen::Ref<const VectorXs>& x,
128
                    const Eigen::Ref<const VectorXs>& u) = 0;
129
130
  /**
131
   * @brief Compute the total cost value for nodes that depends only on the
132
   * state
133
   *
134
   * It updates the total cost and the next state is not computed as it is not
135
   * expected to change. This function is used in the terminal nodes of an
136
   * optimal control problem.
137
   *
138
   * @param[in] data  Action data
139
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
140
   */
141
  virtual void calc(const boost::shared_ptr<ActionDataAbstract>& data,
142
                    const Eigen::Ref<const VectorXs>& x);
143
144
  /**
145
   * @brief Compute the derivatives of the dynamics and cost functions
146
   *
147
   * It computes the partial derivatives of the dynamical system and the cost
148
   * function. It assumes that `calc()` has been run first. This function builds
149
   * a linear-quadratic approximation of the action model (i.e. dynamical system
150
   * and cost function).
151
   *
152
   * @param[in] data  Action data
153
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
154
   * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
155
   */
156
  virtual void calcDiff(const boost::shared_ptr<ActionDataAbstract>& data,
157
                        const Eigen::Ref<const VectorXs>& x,
158
                        const Eigen::Ref<const VectorXs>& u) = 0;
159
160
  /**
161
   * @brief Compute the derivatives of the cost functions with respect to the
162
   * state only
163
   *
164
   * It updates the derivatives of the cost function with respect to the state
165
   * only. This function is used in the terminal nodes of an optimal control
166
   * problem.
167
   *
168
   * @param[in] data  Action data
169
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
170
   */
171
  virtual void calcDiff(const boost::shared_ptr<ActionDataAbstract>& data,
172
                        const Eigen::Ref<const VectorXs>& x);
173
174
  /**
175
   * @brief Create the action data
176
   *
177
   * @return the action data
178
   */
179
  virtual boost::shared_ptr<ActionDataAbstract> createData();
180
181
  /**
182
   * @brief Checks that a specific data belongs to this model
183
   */
184
  virtual bool checkData(const boost::shared_ptr<ActionDataAbstract>& data);
185
186
  /**
187
   * @brief Computes the quasic static commands
188
   *
189
   * The quasic static commands are the ones produced for a the reference
190
   * posture as an equilibrium point, i.e. for
191
   * \f$\mathbf{f^q_x}\delta\mathbf{q}+\mathbf{f_u}\delta\mathbf{u}=\mathbf{0}\f$
192
   *
193
   * @param[in] data    Action data
194
   * @param[out] u      Quasic static commands
195
   * @param[in] x       State point (velocity has to be zero)
196
   * @param[in] maxiter Maximum allowed number of iterations
197
   * @param[in] tol     Tolerance
198
   */
199
  virtual void quasiStatic(const boost::shared_ptr<ActionDataAbstract>& data,
200
                           Eigen::Ref<VectorXs> u,
201
                           const Eigen::Ref<const VectorXs>& x,
202
                           const std::size_t maxiter = 100,
203
                           const Scalar tol = Scalar(1e-9));
204
205
  /**
206
   * @copybrief quasicStatic()
207
   *
208
   * @copydetails quasicStatic()
209
   *
210
   * @param[in] data    Action data
211
   * @param[in] x       State point (velocity has to be zero)
212
   * @param[in] maxiter Maximum allowed number of iterations
213
   * @param[in] tol     Tolerance
214
   * @return Quasic static commands
215
   */
216
  VectorXs quasiStatic_x(const boost::shared_ptr<ActionDataAbstract>& data,
217
                         const VectorXs& x, const std::size_t maxiter = 100,
218
                         const Scalar tol = Scalar(1e-9));
219
220
  /**
221
   * @brief Return the dimension of the control input
222
   */
223
  std::size_t get_nu() const;
224
225
  /**
226
   * @brief Return the dimension of the cost-residual vector
227
   */
228
  std::size_t get_nr() const;
229
230
  /**
231
   * @brief Return the number of inequality constraints
232
   */
233
  virtual std::size_t get_ng() const;
234
235
  /**
236
   * @brief Return the number of equality constraints
237
   */
238
  virtual std::size_t get_nh() const;
239
240
  /**
241
   * @brief Return the state
242
   */
243
  const boost::shared_ptr<StateAbstract>& get_state() const;
244
245
  /**
246
   * @brief Return the lower bound of the inequality constraints
247
   */
248
  virtual const VectorXs& get_g_lb() const;
249
250
  /**
251
   * @brief Return the upper bound of the inequality constraints
252
   */
253
  virtual const VectorXs& get_g_ub() const;
254
255
  /**
256
   * @brief Return the control lower bound
257
   */
258
  const VectorXs& get_u_lb() const;
259
260
  /**
261
   * @brief Return the control upper bound
262
   */
263
  const VectorXs& get_u_ub() const;
264
265
  /**
266
   * @brief Indicates if there are defined control limits
267
   */
268
  bool get_has_control_limits() const;
269
270
  /**
271
   * @brief Modify the lower bound of the inequality constraints
272
   */
273
  void set_g_lb(const VectorXs& g_lb);
274
275
  /**
276
   * @brief Modify the upper bound of the inequality constraints
277
   */
278
  void set_g_ub(const VectorXs& g_ub);
279
280
  /**
281
   * @brief Modify the control lower bounds
282
   */
283
  void set_u_lb(const VectorXs& u_lb);
284
285
  /**
286
   * @brief Modify the control upper bounds
287
   */
288
  void set_u_ub(const VectorXs& u_ub);
289
290
  /**
291
   * @brief Print information on the action model
292
   */
293
  template <class Scalar>
294
  friend std::ostream& operator<<(std::ostream& os,
295
                                  const ActionModelAbstractTpl<Scalar>& model);
296
297
  /**
298
   * @brief Print relevant information of the action model
299
   *
300
   * @param[out] os  Output stream object
301
   */
302
  virtual void print(std::ostream& os) const;
303
304
 protected:
305
  std::size_t nu_;  //!< Control dimension
306
  std::size_t nr_;  //!< Dimension of the cost residual
307
  std::size_t ng_;  //!< Number of inequality constraints
308
  std::size_t nh_;  //!< Number of equality constraints
309
  boost::shared_ptr<StateAbstract> state_;  //!< Model of the state
310
  VectorXs unone_;                          //!< Neutral state
311
  VectorXs g_lb_;            //!< Lower bound of the inequality constraints
312
  VectorXs g_ub_;            //!< Lower bound of the inequality constraints
313
  VectorXs u_lb_;            //!< Lower control limits
314
  VectorXs u_ub_;            //!< Upper control limits
315
  bool has_control_limits_;  //!< Indicates whether any of the control limits is
316
                             //!< finite
317
318
  /**
319
   * @brief Update the status of the control limits (i.e. if there are defined
320
   * limits)
321
   */
322
  void update_has_control_limits();
323
324
  template <class Scalar>
325
  friend class ConstraintModelManagerTpl;
326
};
327
328
template <typename _Scalar>
329
struct ActionDataAbstractTpl {
330
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
331
332
  typedef _Scalar Scalar;
333
  typedef MathBaseTpl<Scalar> MathBase;
334
  typedef typename MathBase::VectorXs VectorXs;
335
  typedef typename MathBase::MatrixXs MatrixXs;
336
337
  template <template <typename Scalar> class Model>
338
86871
  explicit ActionDataAbstractTpl(Model<Scalar>* const model)
339
      : cost(Scalar(0.)),
340
86871
        xnext(model->get_state()->get_nx()),
341
173742
        Fx(model->get_state()->get_ndx(), model->get_state()->get_ndx()),
342
86871
        Fu(model->get_state()->get_ndx(), model->get_nu()),
343
        r(model->get_nr()),
344
86871
        Lx(model->get_state()->get_ndx()),
345
        Lu(model->get_nu()),
346
173742
        Lxx(model->get_state()->get_ndx(), model->get_state()->get_ndx()),
347
86871
        Lxu(model->get_state()->get_ndx(), model->get_nu()),
348
        Luu(model->get_nu(), model->get_nu()),
349
        g(model->get_ng()),
350
86871
        Gx(model->get_ng(), model->get_state()->get_ndx()),
351
        Gu(model->get_ng(), model->get_nu()),
352
        h(model->get_nh()),
353
86871
        Hx(model->get_nh(), model->get_state()->get_ndx()),
354










86871
        Hu(model->get_nh(), model->get_nu()) {
355
86871
    xnext.setZero();
356
86871
    Fx.setZero();
357
86871
    Fu.setZero();
358
86871
    r.setZero();
359
86871
    Lx.setZero();
360
86871
    Lu.setZero();
361
86871
    Lxx.setZero();
362
86871
    Lxu.setZero();
363
86871
    Luu.setZero();
364
86871
    g.setZero();
365
86871
    Gx.setZero();
366
86871
    Gu.setZero();
367
86871
    h.setZero();
368
86871
    Hx.setZero();
369
86871
    Hu.setZero();
370
86871
  }
371
45161
  virtual ~ActionDataAbstractTpl() {}
372
373
  Scalar cost;     //!< cost value
374
  VectorXs xnext;  //!< evolution state
375
  MatrixXs Fx;  //!< Jacobian of the dynamics w.r.t. the state \f$\mathbf{x}\f$
376
  MatrixXs
377
      Fu;      //!< Jacobian of the dynamics w.r.t. the control \f$\mathbf{u}\f$
378
  VectorXs r;  //!< Cost residual
379
  VectorXs Lx;   //!< Jacobian of the cost w.r.t. the state \f$\mathbf{x}\f$
380
  VectorXs Lu;   //!< Jacobian of the cost w.r.t. the control \f$\mathbf{u}\f$
381
  MatrixXs Lxx;  //!< Hessian of the cost w.r.t. the state \f$\mathbf{x}\f$
382
  MatrixXs Lxu;  //!< Hessian of the cost w.r.t. the state \f$\mathbf{x}\f$ and
383
                 //!< control \f$\mathbf{u}\f$
384
  MatrixXs Luu;  //!< Hessian of the cost w.r.t. the control \f$\mathbf{u}\f$
385
  VectorXs g;    //!< Inequality constraint values
386
  MatrixXs Gx;   //!< Jacobian of the inequality constraint w.r.t. the state
387
                 //!< \f$\mathbf{x}\f$
388
  MatrixXs Gu;   //!< Jacobian of the inequality constraint w.r.t. the control
389
                 //!< \f$\mathbf{u}\f$
390
  VectorXs h;    //!< Equality constraint values
391
  MatrixXs Hx;   //!< Jacobian of the equality constraint w.r.t. the state
392
                 //!< \f$\mathbf{x}\f$
393
  MatrixXs Hu;   //!< Jacobian of the equality constraint w.r.t. the control
394
                 //!< \f$\mathbf{u}\f$
395
};
396
397
}  // namespace crocoddyl
398
399
/* --- Details -------------------------------------------------------------- */
400
/* --- Details -------------------------------------------------------------- */
401
/* --- Details -------------------------------------------------------------- */
402
#include "crocoddyl/core/action-base.hxx"
403
404
#endif  // CROCODDYL_CORE_ACTION_BASE_HPP_