GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/core/constraint-base.hpp
Date: 2025-03-26 19:23:43
Exec Total Coverage
Lines: 20 24 83.3%
Branches: 30 78 38.5%

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