GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/core/action-base.hpp
Date: 2025-01-16 08:47:40
Exec Total Coverage
Lines: 44 44 100.0%
Branches: 60 120 50.0%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2024, 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 (default 0)
112 * @param[in] nh Number of equality constraints (default 0)
113 * @param[in] ng_T Number of inequality terminal constraints (default 0)
114 * @param[in] nh_T Number of equality terminal constraints (default 0)
115 */
116 ActionModelAbstractTpl(boost::shared_ptr<StateAbstract> state,
117 const std::size_t nu, const std::size_t nr = 0,
118 const std::size_t ng = 0, const std::size_t nh = 0,
119 const std::size_t ng_T = 0,
120 const std::size_t nh_T = 0);
121 virtual ~ActionModelAbstractTpl();
122
123 /**
124 * @brief Compute the next state and cost value
125 *
126 * @param[in] data Action data
127 * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
128 * @param[in] u Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
129 */
130 virtual void calc(const boost::shared_ptr<ActionDataAbstract>& data,
131 const Eigen::Ref<const VectorXs>& x,
132 const Eigen::Ref<const VectorXs>& u) = 0;
133
134 /**
135 * @brief Compute the total cost value for nodes that depends only on the
136 * state
137 *
138 * It updates the total cost and the next state is not computed as it is not
139 * expected to change. This function is used in the terminal nodes of an
140 * optimal control problem.
141 *
142 * @param[in] data Action data
143 * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
144 */
145 virtual void calc(const boost::shared_ptr<ActionDataAbstract>& data,
146 const Eigen::Ref<const VectorXs>& x);
147
148 /**
149 * @brief Compute the derivatives of the dynamics and cost functions
150 *
151 * It computes the partial derivatives of the dynamical system and the cost
152 * function. It assumes that `calc()` has been run first. This function builds
153 * a linear-quadratic approximation of the action model (i.e. dynamical system
154 * and cost function).
155 *
156 * @param[in] data Action data
157 * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
158 * @param[in] u Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
159 */
160 virtual void calcDiff(const boost::shared_ptr<ActionDataAbstract>& data,
161 const Eigen::Ref<const VectorXs>& x,
162 const Eigen::Ref<const VectorXs>& u) = 0;
163
164 /**
165 * @brief Compute the derivatives of the cost functions with respect to the
166 * state only
167 *
168 * It updates the derivatives of the cost function with respect to the state
169 * only. This function is used in the terminal nodes of an optimal control
170 * problem.
171 *
172 * @param[in] data Action data
173 * @param[in] x State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
174 */
175 virtual void calcDiff(const boost::shared_ptr<ActionDataAbstract>& data,
176 const Eigen::Ref<const VectorXs>& x);
177
178 /**
179 * @brief Create the action data
180 *
181 * @return the action data
182 */
183 virtual boost::shared_ptr<ActionDataAbstract> createData();
184
185 /**
186 * @brief Checks that a specific data belongs to this model
187 */
188 virtual bool checkData(const boost::shared_ptr<ActionDataAbstract>& data);
189
190 /**
191 * @brief Computes the quasic static commands
192 *
193 * The quasic static commands are the ones produced for a the reference
194 * posture as an equilibrium point, i.e. for
195 * \f$\mathbf{f^q_x}\delta\mathbf{q}+\mathbf{f_u}\delta\mathbf{u}=\mathbf{0}\f$
196 *
197 * @param[in] data Action data
198 * @param[out] u Quasic static commands
199 * @param[in] x State point (velocity has to be zero)
200 * @param[in] maxiter Maximum allowed number of iterations
201 * @param[in] tol Tolerance
202 */
203 virtual void quasiStatic(const boost::shared_ptr<ActionDataAbstract>& data,
204 Eigen::Ref<VectorXs> u,
205 const Eigen::Ref<const VectorXs>& x,
206 const std::size_t maxiter = 100,
207 const Scalar tol = Scalar(1e-9));
208
209 /**
210 * @copybrief quasicStatic()
211 *
212 * @copydetails quasicStatic()
213 *
214 * @param[in] data Action data
215 * @param[in] x State point (velocity has to be zero)
216 * @param[in] maxiter Maximum allowed number of iterations
217 * @param[in] tol Tolerance
218 * @return Quasic static commands
219 */
220 VectorXs quasiStatic_x(const boost::shared_ptr<ActionDataAbstract>& data,
221 const VectorXs& x, const std::size_t maxiter = 100,
222 const Scalar tol = Scalar(1e-9));
223
224 /**
225 * @brief Return the dimension of the control input
226 */
227 std::size_t get_nu() const;
228
229 /**
230 * @brief Return the dimension of the cost-residual vector
231 */
232 std::size_t get_nr() const;
233
234 /**
235 * @brief Return the number of inequality constraints
236 */
237 virtual std::size_t get_ng() const;
238
239 /**
240 * @brief Return the number of equality constraints
241 */
242 virtual std::size_t get_nh() const;
243
244 /**
245 * @brief Return the number of inequality terminal constraints
246 */
247 virtual std::size_t get_ng_T() const;
248
249 /**
250 * @brief Return the number of equality terminal constraints
251 */
252 virtual std::size_t get_nh_T() const;
253
254 /**
255 * @brief Return the state
256 */
257 const boost::shared_ptr<StateAbstract>& get_state() const;
258
259 /**
260 * @brief Return the lower bound of the inequality constraints
261 */
262 virtual const VectorXs& get_g_lb() const;
263
264 /**
265 * @brief Return the upper bound of the inequality constraints
266 */
267 virtual const VectorXs& get_g_ub() const;
268
269 /**
270 * @brief Return the control lower bound
271 */
272 const VectorXs& get_u_lb() const;
273
274 /**
275 * @brief Return the control upper bound
276 */
277 const VectorXs& get_u_ub() const;
278
279 /**
280 * @brief Indicates if there are defined control limits
281 */
282 bool get_has_control_limits() const;
283
284 /**
285 * @brief Modify the lower bound of the inequality constraints
286 */
287 void set_g_lb(const VectorXs& g_lb);
288
289 /**
290 * @brief Modify the upper bound of the inequality constraints
291 */
292 void set_g_ub(const VectorXs& g_ub);
293
294 /**
295 * @brief Modify the control lower bounds
296 */
297 void set_u_lb(const VectorXs& u_lb);
298
299 /**
300 * @brief Modify the control upper bounds
301 */
302 void set_u_ub(const VectorXs& u_ub);
303
304 /**
305 * @brief Print information on the action model
306 */
307 template <class Scalar>
308 friend std::ostream& operator<<(std::ostream& os,
309 const ActionModelAbstractTpl<Scalar>& model);
310
311 /**
312 * @brief Print relevant information of the action model
313 *
314 * @param[out] os Output stream object
315 */
316 virtual void print(std::ostream& os) const;
317
318 protected:
319 std::size_t nu_; //!< Control dimension
320 std::size_t nr_; //!< Dimension of the cost residual
321 std::size_t ng_; //!< Number of inequality constraints
322 std::size_t nh_; //!< Number of equality constraints
323 std::size_t ng_T_; //!< Number of inequality terminal constraints
324 std::size_t nh_T_; //!< Number of equality terminal constraints
325 boost::shared_ptr<StateAbstract> state_; //!< Model of the state
326 VectorXs unone_; //!< Neutral state
327 VectorXs g_lb_; //!< Lower bound of the inequality constraints
328 VectorXs g_ub_; //!< Lower bound of the inequality constraints
329 VectorXs u_lb_; //!< Lower control limits
330 VectorXs u_ub_; //!< Upper control limits
331 bool has_control_limits_; //!< Indicates whether any of the control limits is
332 //!< finite
333
334 /**
335 * @brief Update the status of the control limits (i.e. if there are defined
336 * limits)
337 */
338 void update_has_control_limits();
339
340 template <class Scalar>
341 friend class ConstraintModelManagerTpl;
342 };
343
344 template <typename _Scalar>
345 struct ActionDataAbstractTpl {
346 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
347
348 typedef _Scalar Scalar;
349 typedef MathBaseTpl<Scalar> MathBase;
350 typedef typename MathBase::VectorXs VectorXs;
351 typedef typename MathBase::MatrixXs MatrixXs;
352
353 template <template <typename Scalar> class Model>
354 93157 explicit ActionDataAbstractTpl(Model<Scalar>* const model)
355 93157 : cost(Scalar(0.)),
356
1/2
✓ Branch 3 taken 46669 times.
✗ Branch 4 not taken.
93157 xnext(model->get_state()->get_nx()),
357
1/2
✓ Branch 7 taken 46669 times.
✗ Branch 8 not taken.
93157 Fx(model->get_state()->get_ndx(), model->get_state()->get_ndx()),
358
1/2
✓ Branch 5 taken 46669 times.
✗ Branch 6 not taken.
93157 Fu(model->get_state()->get_ndx(), model->get_nu()),
359
1/2
✓ Branch 2 taken 46669 times.
✗ Branch 3 not taken.
93157 r(model->get_nr()),
360
1/2
✓ Branch 4 taken 46669 times.
✗ Branch 5 not taken.
93157 Lx(model->get_state()->get_ndx()),
361
1/2
✓ Branch 2 taken 46669 times.
✗ Branch 3 not taken.
93157 Lu(model->get_nu()),
362
1/2
✓ Branch 7 taken 46669 times.
✗ Branch 8 not taken.
93157 Lxx(model->get_state()->get_ndx(), model->get_state()->get_ndx()),
363
1/2
✓ Branch 5 taken 46669 times.
✗ Branch 6 not taken.
93157 Lxu(model->get_state()->get_ndx(), model->get_nu()),
364
1/2
✓ Branch 3 taken 46669 times.
✗ Branch 4 not taken.
93157 Luu(model->get_nu(), model->get_nu()),
365
4/10
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 46669 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 46669 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 12 taken 46669 times.
✗ Branch 13 not taken.
186314 g(model->get_ng() > model->get_ng_T() ? model->get_ng()
366
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 : model->get_ng_T()),
367
3/8
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 46669 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 9 taken 46669 times.
✗ Branch 10 not taken.
186314 Gx(model->get_ng() > model->get_ng_T() ? model->get_ng()
368
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 : model->get_ng_T(),
369
1/2
✓ Branch 4 taken 46669 times.
✗ Branch 5 not taken.
93157 model->get_state()->get_ndx()),
370
3/8
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 46669 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 9 taken 46669 times.
✗ Branch 10 not taken.
186314 Gu(model->get_ng() > model->get_ng_T() ? model->get_ng()
371
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 : model->get_ng_T(),
372
1/2
✓ Branch 2 taken 46669 times.
✗ Branch 3 not taken.
93157 model->get_nu()),
373
6/10
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 46669 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12667 times.
✓ Branch 7 taken 34002 times.
✓ Branch 9 taken 12667 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 46669 times.
✗ Branch 13 not taken.
160980 h(model->get_nh() > model->get_nh_T() ? model->get_nh()
374
1/2
✓ Branch 1 taken 34002 times.
✗ Branch 2 not taken.
67823 : model->get_nh_T()),
375
5/8
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12667 times.
✓ Branch 4 taken 34002 times.
✓ Branch 6 taken 12667 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 46669 times.
✗ Branch 10 not taken.
160980 Hx(model->get_nh() > model->get_nh_T() ? model->get_nh()
376
1/2
✓ Branch 1 taken 34002 times.
✗ Branch 2 not taken.
67823 : model->get_nh_T(),
377
1/2
✓ Branch 4 taken 46669 times.
✗ Branch 5 not taken.
93157 model->get_state()->get_ndx()),
378
5/8
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12667 times.
✓ Branch 4 taken 34002 times.
✓ Branch 6 taken 12667 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 46669 times.
✗ Branch 10 not taken.
160980 Hu(model->get_nh() > model->get_nh_T() ? model->get_nh()
379
1/2
✓ Branch 1 taken 34002 times.
✗ Branch 2 not taken.
67823 : model->get_nh_T(),
380
1/2
✓ Branch 3 taken 46669 times.
✗ Branch 4 not taken.
186314 model->get_nu()) {
381
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 xnext.setZero();
382
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 Fx.setZero();
383
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 Fu.setZero();
384
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 r.setZero();
385
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 Lx.setZero();
386
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 Lu.setZero();
387
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 Lxx.setZero();
388
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 Lxu.setZero();
389
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 Luu.setZero();
390
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 g.setZero();
391
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 Gx.setZero();
392
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 Gu.setZero();
393
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 h.setZero();
394
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 Hx.setZero();
395
1/2
✓ Branch 1 taken 46669 times.
✗ Branch 2 not taken.
93157 Hu.setZero();
396 93157 }
397 48098 virtual ~ActionDataAbstractTpl() {}
398
399 Scalar cost; //!< cost value
400 VectorXs xnext; //!< evolution state
401 MatrixXs Fx; //!< Jacobian of the dynamics w.r.t. the state \f$\mathbf{x}\f$
402 MatrixXs
403 Fu; //!< Jacobian of the dynamics w.r.t. the control \f$\mathbf{u}\f$
404 VectorXs r; //!< Cost residual
405 VectorXs Lx; //!< Jacobian of the cost w.r.t. the state \f$\mathbf{x}\f$
406 VectorXs Lu; //!< Jacobian of the cost w.r.t. the control \f$\mathbf{u}\f$
407 MatrixXs Lxx; //!< Hessian of the cost w.r.t. the state \f$\mathbf{x}\f$
408 MatrixXs Lxu; //!< Hessian of the cost w.r.t. the state \f$\mathbf{x}\f$ and
409 //!< control \f$\mathbf{u}\f$
410 MatrixXs Luu; //!< Hessian of the cost w.r.t. the control \f$\mathbf{u}\f$
411 VectorXs g; //!< Inequality constraint values
412 MatrixXs Gx; //!< Jacobian of the inequality constraint w.r.t. the state
413 //!< \f$\mathbf{x}\f$
414 MatrixXs Gu; //!< Jacobian of the inequality constraint w.r.t. the control
415 //!< \f$\mathbf{u}\f$
416 VectorXs h; //!< Equality constraint values
417 MatrixXs Hx; //!< Jacobian of the equality constraint w.r.t. the state
418 //!< \f$\mathbf{x}\f$
419 MatrixXs Hu; //!< Jacobian of the equality constraint w.r.t. the control
420 //!< \f$\mathbf{u}\f$
421 };
422
423 } // namespace crocoddyl
424
425 /* --- Details -------------------------------------------------------------- */
426 /* --- Details -------------------------------------------------------------- */
427 /* --- Details -------------------------------------------------------------- */
428 #include "crocoddyl/core/action-base.hxx"
429
430 #endif // CROCODDYL_CORE_ACTION_BASE_HPP_
431