GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/crocoddyl/core/constraint-base.hpp Lines: 13 16 81.2 %
Date: 2024-02-13 11:12:33 Branches: 16 40 40.0 %

Line Branch Exec Source
1
///////////////////////////////////////////////////////////////////////////////
2
// BSD 3-Clause License
3
//
4
// Copyright (C) 2020-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_CONSTRAINT_BASE_HPP_
10
#define CROCODDYL_CORE_CONSTRAINT_BASE_HPP_
11
12
#include <boost/make_shared.hpp>
13
#include <boost/shared_ptr.hpp>
14
15
#include "crocoddyl/core/fwd.hpp"
16
//
17
#include "crocoddyl/core/data-collector-base.hpp"
18
#include "crocoddyl/core/residual-base.hpp"
19
#include "crocoddyl/core/state-base.hpp"
20
21
namespace crocoddyl {
22
23
enum ConstraintType { Inequality = 0, Equality, Both };
24
25
/**
26
 * @brief Abstract class for constraint models
27
 *
28
 * A constraint model defines both: inequality \f$\mathbf{g}(\mathbf{x},
29
 * \mathbf{u})\in\mathbb{R}^{ng}\f$ and equality \f$\mathbf{h}(\mathbf{x},
30
 * \mathbf{u})\in\mathbb{R}^{nh}\f$ constraints. The constraint function depends
31
 * on the state point \f$\mathbf{x}\in\mathcal{X}\f$, which lies in the state
32
 * manifold described with a `nx`-tuple, its velocity \f$\dot{\mathbf{x}}\in
33
 * T_{\mathbf{x}}\mathcal{X}\f$ that belongs to the tangent space with `ndx`
34
 * dimension, and the control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$.
35
 *
36
 * The main computations are carried out in `calc()` and `calcDiff()` routines.
37
 * `calc()` computes the constraint residual and `calcDiff()` computes the
38
 * Jacobians of the constraint function. Concretely speaking, `calcDiff()`
39
 * builds a linear approximation of the constraint function with the form:
40
 * \f$\mathbf{g_x}\in\mathbb{R}^{ng\times ndx}\f$,
41
 * \f$\mathbf{g_u}\in\mathbb{R}^{ng\times nu}\f$,
42
 * \f$\mathbf{h_x}\in\mathbb{R}^{nh\times ndx}\f$
43
 * \f$\mathbf{h_u}\in\mathbb{R}^{nh\times nu}\f$. Additionally, it is important
44
 * to note that `calcDiff()` computes the derivatives using the latest stored
45
 * values by `calc()`. Thus, we need to first run `calc()`.
46
 *
47
 * \sa `calc()`, `calcDiff()`, `createData()`
48
 */
49
template <typename _Scalar>
50
class ConstraintModelAbstractTpl {
51
 public:
52
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
53
54
  typedef _Scalar Scalar;
55
  typedef MathBaseTpl<Scalar> MathBase;
56
  typedef ConstraintDataAbstractTpl<Scalar> ConstraintDataAbstract;
57
  typedef StateAbstractTpl<Scalar> StateAbstract;
58
  typedef ResidualModelAbstractTpl<Scalar> ResidualModelAbstract;
59
  typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract;
60
  typedef typename MathBase::VectorXs VectorXs;
61
62
  /**
63
   * @brief Initialize the constraint model
64
   *
65
   * @param[in] state     State of the multibody system
66
   * @param[in] residual  Residual model
67
   * @param[in] ng        Number of inequality constraints
68
   * @param[in] nh        Number of equality constraints
69
   */
70
  ConstraintModelAbstractTpl(boost::shared_ptr<StateAbstract> state,
71
                             boost::shared_ptr<ResidualModelAbstract> residual,
72
                             const std::size_t ng, const std::size_t nh);
73
74
  /**
75
   * @copybrief Initialize the constraint model
76
   *
77
   * @param[in] state  State of the multibody system
78
   * @param[in] nu     Dimension of control vector
79
   * @param[in] ng     Number of inequality constraints
80
   * @param[in] nh     Number of equality constraints
81
   */
82
  ConstraintModelAbstractTpl(boost::shared_ptr<StateAbstract> state,
83
                             const std::size_t nu, const std::size_t ng,
84
                             const std::size_t nh);
85
86
  /**
87
   * @copybrief ConstraintModelAbstractTpl()
88
   *
89
   * The default `nu` value is obtained from `StateAbstractTpl::get_nv()`.
90
   *
91
   * @param[in] state  State of the multibody system
92
   * @param[in] ng     Number of inequality constraints
93
   * @param[in] nh     Number of equality constraints
94
   */
95
  ConstraintModelAbstractTpl(boost::shared_ptr<StateAbstract> state,
96
                             const std::size_t ng, const std::size_t nh);
97
  virtual ~ConstraintModelAbstractTpl();
98
99
  /**
100
   * @brief Compute the constraint value
101
   *
102
   * @param[in] data  Constraint data
103
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
104
   * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
105
   */
106
  virtual void calc(const boost::shared_ptr<ConstraintDataAbstract>& data,
107
                    const Eigen::Ref<const VectorXs>& x,
108
                    const Eigen::Ref<const VectorXs>& u) = 0;
109
110
  /**
111
   * @brief Compute the constraint value for nodes that depends only on the
112
   * state
113
   *
114
   * It updates the constraint based on the state only. This function is
115
   * commonly used in the terminal nodes of an optimal control problem.
116
   *
117
   * @param[in] data  Constraint data
118
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
119
   */
120
  virtual void calc(const boost::shared_ptr<ConstraintDataAbstract>& data,
121
                    const Eigen::Ref<const VectorXs>& x);
122
123
  /**
124
   * @brief Compute the Jacobian of the constraint
125
   *
126
   * It computes the Jacobian of the constraint function. It assumes that
127
   * `calc()` has been run first.
128
   *
129
   * @param[in] data  Constraint data
130
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
131
   * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
132
   */
133
  virtual void calcDiff(const boost::shared_ptr<ConstraintDataAbstract>& data,
134
                        const Eigen::Ref<const VectorXs>& x,
135
                        const Eigen::Ref<const VectorXs>& u) = 0;
136
137
  /**
138
   * @brief Compute the Jacobian of the constraint with respect to the state
139
   * only
140
   *
141
   * It computes the Jacobian of the constraint function based on the state
142
   * only. This function is commonly used in the terminal nodes of an optimal
143
   * control problem.
144
   *
145
   * @param[in] data  Constraint data
146
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
147
   */
148
  virtual void calcDiff(const boost::shared_ptr<ConstraintDataAbstract>& data,
149
                        const Eigen::Ref<const VectorXs>& x);
150
151
  /**
152
   * @brief Create the constraint data
153
   *
154
   * The default data contains objects to store the values of the constraint,
155
   * residual vector and their first derivatives. However, it is possible to
156
   * specialize this function is we need to create additional data, for
157
   * instance, to avoid dynamic memory allocation.
158
   *
159
   * @param data  Data collector
160
   * @return the constraint data
161
   */
162
  virtual boost::shared_ptr<ConstraintDataAbstract> createData(
163
      DataCollectorAbstract* const data);
164
165
  /**
166
   * @brief Update the lower and upper bounds the upper bound of constraint
167
   */
168
  void update_bounds(const VectorXs& lower, const VectorXs& upper);
169
170
  /**
171
   * @brief Remove the bounds of the constraint
172
   */
173
  void remove_bounds();
174
175
  /**
176
   * @brief Return the state
177
   */
178
  const boost::shared_ptr<StateAbstract>& get_state() const;
179
180
  /**
181
   * @brief Return the residual model
182
   */
183
  const boost::shared_ptr<ResidualModelAbstract>& get_residual() const;
184
185
  /**
186
   * @brief Return the type of constraint
187
   */
188
  ConstraintType get_type() const;
189
190
  /**
191
   * @brief Return the lower bound of the constraint
192
   */
193
  const VectorXs& get_lb() const;
194
195
  /**
196
   * @brief Return the upper bound of the constraint
197
   */
198
  const VectorXs& get_ub() const;
199
200
  /**
201
   * @brief Return the dimension of the control input
202
   */
203
  std::size_t get_nu() const;
204
205
  /**
206
   * @brief Return the number of inequality constraints
207
   */
208
  std::size_t get_ng() const;
209
210
  /**
211
   * @brief Return the number of equality constraints
212
   */
213
  std::size_t get_nh() const;
214
215
  /**
216
   * @brief Print information on the constraint model
217
   */
218
  template <class Scalar>
219
  friend std::ostream& operator<<(std::ostream& os,
220
                                  const CostModelAbstractTpl<Scalar>& model);
221
222
  /**
223
   * @brief Print relevant information of the constraint model
224
   *
225
   * @param[out] os  Output stream object
226
   */
227
  virtual void print(std::ostream& os) const;
228
229
 private:
230
  std::size_t ng_internal_;  //!< Number of inequality constraints defined at
231
                             //!< construction time
232
  std::size_t nh_internal_;  //!< Number of equality constraints defined at
233
                             //!< construction time
234
235
 protected:
236
  boost::shared_ptr<StateAbstract> state_;             //!< State description
237
  boost::shared_ptr<ResidualModelAbstract> residual_;  //!< Residual model
238
  ConstraintType
239
      type_;        //!< Type of constraint: inequality=0, equality=1, both=2
240
  VectorXs lb_;     //!< Lower bound of the constraint
241
  VectorXs ub_;     //!< Upper bound of the constraint
242
  std::size_t nu_;  //!< Control dimension
243
  std::size_t ng_;  //!< Number of inequality constraints
244
  std::size_t nh_;  //!< Number of equality constraints
245
  VectorXs unone_;  //!< No control vector
246
};
247
248
template <typename _Scalar>
249
struct ConstraintDataAbstractTpl {
250
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
251
252
  typedef _Scalar Scalar;
253
  typedef MathBaseTpl<Scalar> MathBase;
254
  typedef ResidualDataAbstractTpl<Scalar> ResidualDataAbstract;
255
  typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract;
256
  typedef typename MathBase::VectorXs VectorXs;
257
  typedef typename MathBase::MatrixXs MatrixXs;
258
259
  template <template <typename Scalar> class Model>
260
459616
  ConstraintDataAbstractTpl(Model<Scalar>* const model,
261
                            DataCollectorAbstract* const data)
262
      : shared(data),
263
459616
        residual(model->get_residual()->createData(data)),
264
        g(model->get_ng()),
265
459616
        Gx(model->get_ng(), model->get_state()->get_ndx()),
266
        Gu(model->get_ng(), model->get_nu()),
267
        h(model->get_nh()),
268
459616
        Hx(model->get_nh(), model->get_state()->get_ndx()),
269



919232
        Hu(model->get_nh(), model->get_nu()) {
270

459616
    if (model->get_ng() == 0 && model->get_nh() == 0) {
271
      throw_pretty("Invalid argument: "
272
                   << "ng and nh cannot be equals to 0");
273
    }
274
459616
    g.setZero();
275
459616
    Gx.setZero();
276
459616
    Gu.setZero();
277
459616
    h.setZero();
278
459616
    Hx.setZero();
279
459616
    Hu.setZero();
280
  }
281
229818
  virtual ~ConstraintDataAbstractTpl() {}
282
283
  DataCollectorAbstract* shared;                     //!< Shared data
284
  boost::shared_ptr<ResidualDataAbstract> residual;  //!< Residual data
285
  VectorXs g;   //!< Inequality constraint values
286
  MatrixXs Gx;  //!< Jacobian of the inequality constraint
287
  MatrixXs Gu;  //!< Jacobian of the inequality constraint
288
  VectorXs h;   //!< Equality constraint values
289
  MatrixXs Hx;  //!< Jacobian of the equality constraint
290
  MatrixXs Hu;  //!< Jacobian of the equality constraint
291
};
292
293
}  // namespace crocoddyl
294
295
/* --- Details -------------------------------------------------------------- */
296
/* --- Details -------------------------------------------------------------- */
297
/* --- Details -------------------------------------------------------------- */
298
#include "crocoddyl/core/constraint-base.hxx"
299
300
#endif  // CROCODDYL_CORE_CONSTRAINT_BASE_HPP_