GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/crocoddyl/multibody/actions/contact-invdyn.hpp Lines: 116 133 87.2 %
Date: 2024-02-13 11:12:33 Branches: 66 136 48.5 %

Line Branch Exec Source
1
///////////////////////////////////////////////////////////////////////////////
2
// BSD 3-Clause License
3
//
4
// Copyright (C) 2021-2024, Heriot-Watt University, University of Edinburgh
5
// Copyright note valid unless otherwise stated in individual files.
6
// All rights reserved.
7
///////////////////////////////////////////////////////////////////////////////
8
9
#ifndef CROCODDYL_MULTIBODY_ACTIONS_CONTACT_INVDYN_HPP_
10
#define CROCODDYL_MULTIBODY_ACTIONS_CONTACT_INVDYN_HPP_
11
12
#include "crocoddyl/core/actuation-base.hpp"
13
#include "crocoddyl/core/constraints/constraint-manager.hpp"
14
#include "crocoddyl/core/costs/cost-sum.hpp"
15
#include "crocoddyl/core/diff-action-base.hpp"
16
#include "crocoddyl/multibody/contacts/multiple-contacts.hpp"
17
#include "crocoddyl/multibody/data/contacts.hpp"
18
#include "crocoddyl/multibody/fwd.hpp"
19
#include "crocoddyl/multibody/states/multibody.hpp"
20
21
namespace crocoddyl {
22
23
/**
24
 * @brief Differential action model for contact inverse dynamics in multibody
25
 * systems.
26
 *
27
 * This class implements forward kinematic with holonomic contact constraints
28
 * (defined at the acceleration level) and inverse-dynamics computation using
29
 * the Recursive Newton Euler Algorithm (RNEA). The stack of cost and constraint
30
 * functions are implemented in `CostModelSumTpl` and
31
 * `ConstraintModelManagerTpl`, respectively. The acceleration and contact
32
 * forces are decision variables defined as the control inputs, and the
33
 * under-actuation and contact constraint are under the name `tau` and its frame
34
 * name, thus the user is not allowed to use it.
35
 *
36
 * Additionally, it is important to note that `calcDiff()` computes the
37
 * derivatives using the latest stored values by `calc()`. Thus, we need to
38
 * first run `calc()`.
39
 *
40
 * \sa `DifferentialActionModelAbstractTpl`, `calc()`, `calcDiff()`,
41
 * `createData()`
42
 */
43
template <typename _Scalar>
44
class DifferentialActionModelContactInvDynamicsTpl
45
    : public DifferentialActionModelAbstractTpl<_Scalar> {
46
 public:
47
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
48
49
  typedef _Scalar Scalar;
50
  typedef DifferentialActionModelAbstractTpl<Scalar> Base;
51
  typedef DifferentialActionDataContactInvDynamicsTpl<Scalar> Data;
52
  typedef StateMultibodyTpl<Scalar> StateMultibody;
53
  typedef ActuationModelAbstractTpl<Scalar> ActuationModelAbstract;
54
  typedef CostModelSumTpl<Scalar> CostModelSum;
55
  typedef ConstraintModelManagerTpl<Scalar> ConstraintModelManager;
56
  typedef ContactModelMultipleTpl<Scalar> ContactModelMultiple;
57
  typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract;
58
  typedef DifferentialActionDataAbstractTpl<Scalar>
59
      DifferentialActionDataAbstract;
60
  typedef ContactItemTpl<Scalar> ContactItem;
61
  typedef MathBaseTpl<Scalar> MathBase;
62
  typedef typename MathBase::VectorXs VectorXs;
63
  typedef typename MathBase::MatrixXs MatrixXs;
64
65
  /**
66
   * @brief Initialize the contact inverse-dynamics action model
67
   *
68
   * It describes the kinematic evolution of the multibody system with contacts,
69
   * and computes the needed torques using inverse-dynamics.
70
   *
71
   * @param[in] state      State of the multibody system
72
   * @param[in] actuation  Actuation model
73
   * @param[in] contacts   Multiple contacts
74
   * @param[in] costs      Cost model
75
   */
76
  DifferentialActionModelContactInvDynamicsTpl(
77
      boost::shared_ptr<StateMultibody> state,
78
      boost::shared_ptr<ActuationModelAbstract> actuation,
79
      boost::shared_ptr<ContactModelMultiple> contacts,
80
      boost::shared_ptr<CostModelSum> costs);
81
82
  /**
83
   * @brief Initialize the contact inverse-dynamics action model
84
   *
85
   * @param[in] state        State of the multibody system
86
   * @param[in] actuation    Actuation model
87
   * @param[in] contacts     Multiple contacts
88
   * @param[in] costs        Cost model
89
   * @param[in] constraints  Constraints model
90
   */
91
  DifferentialActionModelContactInvDynamicsTpl(
92
      boost::shared_ptr<StateMultibody> state,
93
      boost::shared_ptr<ActuationModelAbstract> actuation,
94
      boost::shared_ptr<ContactModelMultiple> contacts,
95
      boost::shared_ptr<CostModelSum> costs,
96
      boost::shared_ptr<ConstraintModelManager> constraints);
97
  virtual ~DifferentialActionModelContactInvDynamicsTpl();
98
99
  /**
100
   * @brief Compute the system acceleration, cost value and constraint residuals
101
   *
102
   * It extracts the acceleration value from control vector and also computes
103
   * the cost and constraints.
104
   *
105
   * @param[in] data  Contact inverse-dynamics data
106
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
107
   * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
108
   */
109
  virtual void calc(
110
      const boost::shared_ptr<DifferentialActionDataAbstract>& data,
111
      const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& u);
112
113
  /**
114
   * @brief @copydoc Base::calc(const
115
   * boost::shared_ptr<DifferentialActionDataAbstract>& data, const
116
   * Eigen::Ref<const VectorXs>& x)
117
   */
118
  virtual void calc(
119
      const boost::shared_ptr<DifferentialActionDataAbstract>& data,
120
      const Eigen::Ref<const VectorXs>& x);
121
122
  /**
123
   * @brief Compute the derivatives of the dynamics, cost and constraint
124
   * functions
125
   *
126
   * It computes the partial derivatives of the dynamical system and the cost
127
   * and contraint functions. It assumes that `calc()` has been run first. This
128
   * function builds a quadratic approximation of the time-continuous action
129
   * model (i.e., dynamical system, cost and constraint functions).
130
   *
131
   * @param[in] data  Contact inverse-dynamics data
132
   * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
133
   * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
134
   */
135
  virtual void calcDiff(
136
      const boost::shared_ptr<DifferentialActionDataAbstract>& data,
137
      const Eigen::Ref<const VectorXs>& x, const Eigen::Ref<const VectorXs>& u);
138
139
  /**
140
   * @brief @copydoc Base::calcDiff(const
141
   * boost::shared_ptr<DifferentialActionDataAbstract>& data, const
142
   * Eigen::Ref<const VectorXs>& x)
143
   */
144
  virtual void calcDiff(
145
      const boost::shared_ptr<DifferentialActionDataAbstract>& data,
146
      const Eigen::Ref<const VectorXs>& x);
147
148
  /**
149
   * @brief Create the contact inverse-dynamics data
150
   *
151
   * @return contact inverse-dynamics data
152
   */
153
  virtual boost::shared_ptr<DifferentialActionDataAbstract> createData();
154
155
  /**
156
   * @brief Checks that a specific data belongs to the contact inverse-dynamics
157
   * model
158
   */
159
  virtual bool checkData(
160
      const boost::shared_ptr<DifferentialActionDataAbstract>& data);
161
162
  /**
163
   * @brief Computes the quasic static commands
164
   *
165
   * The quasic static commands are the ones produced for a reference posture as
166
   * an equilibrium point with zero acceleration, i.e., for
167
   * \f$\mathbf{f^q_x}\delta\mathbf{q}+\mathbf{f_u}\delta\mathbf{u}=\mathbf{0}\f$
168
   *
169
   * @param[in] data     Contact inverse-dynamics data
170
   * @param[out] u       Quasic-static commands
171
   * @param[in] x        State point (velocity has to be zero)
172
   * @param[in] maxiter  Maximum allowed number of iterations (default 100)
173
   * @param[in] tol      Tolerance (default 1e-9)
174
   */
175
  virtual void quasiStatic(
176
      const boost::shared_ptr<DifferentialActionDataAbstract>& data,
177
      Eigen::Ref<VectorXs> u, const Eigen::Ref<const VectorXs>& x,
178
      const std::size_t maxiter = 100, const Scalar tol = Scalar(1e-9));
179
180
  /**
181
   * @brief Return the number of inequality constraints
182
   */
183
  virtual std::size_t get_ng() const;
184
185
  /**
186
   * @brief Return the number of equality constraints
187
   */
188
  virtual std::size_t get_nh() const;
189
190
  /**
191
   * @brief Return the lower bound of the inequality constraints
192
   */
193
  virtual const VectorXs& get_g_lb() const;
194
195
  /**
196
   * @brief Return the upper bound of the inequality constraints
197
   */
198
  virtual const VectorXs& get_g_ub() const;
199
200
  /**
201
   * @brief Return the actuation model
202
   */
203
  const boost::shared_ptr<ActuationModelAbstract>& get_actuation() const;
204
205
  /**
206
   * @brief Return the contact model
207
   */
208
  const boost::shared_ptr<ContactModelMultiple>& get_contacts() const;
209
210
  /**
211
   * @brief Return the cost model
212
   */
213
  const boost::shared_ptr<CostModelSum>& get_costs() const;
214
215
  /**
216
   * @brief Return the constraint model manager
217
   */
218
  const boost::shared_ptr<ConstraintModelManager>& get_constraints() const;
219
220
  /**
221
   * @brief Return the Pinocchio model
222
   */
223
  pinocchio::ModelTpl<Scalar>& get_pinocchio() const;
224
225
  /**
226
   * @brief Print relevant information of the contact inverse-dynamics model
227
   * @param[out] os  Output stream object
228
   */
229
  virtual void print(std::ostream& os) const;
230
231
 protected:
232
  using Base::g_lb_;   //!< Lower bound of the inequality constraints
233
  using Base::g_ub_;   //!< Upper bound of the inequality constraints
234
  using Base::ng_;     //!< Number of inequality constraints
235
  using Base::nh_;     //!< Number of equality constraints
236
  using Base::nu_;     //!< Control dimension
237
  using Base::state_;  //!< Model of the state
238
239
 private:
240
  void init(const boost::shared_ptr<StateMultibody>& state);
241
  boost::shared_ptr<ActuationModelAbstract> actuation_;    //!< Actuation model
242
  boost::shared_ptr<ContactModelMultiple> contacts_;       //!< Contact model
243
  boost::shared_ptr<CostModelSum> costs_;                  //!< Cost model
244
  boost::shared_ptr<ConstraintModelManager> constraints_;  //!< Constraint model
245
  pinocchio::ModelTpl<Scalar>& pinocchio_;                 //!< Pinocchio model
246
247
 public:
248
  /**
249
   * @brief Actuation residual
250
   *
251
   * This residual function enforces the torques of under-actuated joints (e.g.,
252
   * floating-base joints) to be zero. We compute these torques and their
253
   * derivatives using RNEA inside
254
   * `DifferentialActionModelContactInvDynamicsTpl`.
255
   *
256
   * As described in `ResidualModelAbstractTpl`, the residual value and its
257
   * Jacobians are calculated by `calc` and `calcDiff`, respectively.
258
   *
259
   * \sa `ResidualModelAbstractTpl`, `calc()`, `calcDiff()`, `createData()`
260
   */
261
  class ResidualModelActuation : public ResidualModelAbstractTpl<_Scalar> {
262
   public:
263
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
264
265
    typedef _Scalar Scalar;
266
    typedef MathBaseTpl<Scalar> MathBase;
267
    typedef ResidualModelAbstractTpl<Scalar> Base;
268
    typedef StateMultibodyTpl<Scalar> StateMultibody;
269
    typedef ResidualDataAbstractTpl<Scalar> ResidualDataAbstract;
270
    typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract;
271
    typedef typename MathBase::VectorXs VectorXs;
272
273
    /**
274
     * @brief Initialize the actuation residual model
275
     *
276
     * @param[in] state  State of the multibody system
277
     * @param[in] nu     Dimension of the joint torques
278
     * @param[in] nc     Dimension of all the contacts
279
     */
280
251
    ResidualModelActuation(boost::shared_ptr<StateMultibody> state,
281
                           const std::size_t nu, const std::size_t nc)
282
502
        : Base(state, state->get_nv() - nu, state->get_nv() + nc, true, true,
283
               true),
284
          na_(nu),
285
753
          nc_(nc) {}
286
502
    virtual ~ResidualModelActuation() {}
287
288
    /**
289
     * @brief Compute the actuation residual
290
     *
291
     * @param[in] data  Actuation residual data
292
     * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
293
     * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nv+nu}\f$
294
     */
295
23365
    virtual void calc(const boost::shared_ptr<ResidualDataAbstract>& data,
296
                      const Eigen::Ref<const VectorXs>&,
297
                      const Eigen::Ref<const VectorXs>&) {
298
      typename Data::ResidualDataActuation* d =
299
23365
          static_cast<typename Data::ResidualDataActuation*>(data.get());
300
      // Update the under-actuation set and residual
301
23365
      std::size_t nrow = 0;
302
665320
      for (std::size_t k = 0;
303
665320
           k < static_cast<std::size_t>(d->actuation->tau_set.size()); ++k) {
304
641955
        if (!d->actuation->tau_set[k]) {
305
127365
          data->r(nrow) = d->pinocchio->tau(k);
306
127365
          nrow += 1;
307
        }
308
      }
309
23365
    }
310
311
    /**
312
     * @brief @copydoc Base::calc(const boost::shared_ptr<ResidualDataAbstract>&
313
     * data, const Eigen::Ref<const VectorXs>& x)
314
     */
315
2665
    virtual void calc(const boost::shared_ptr<ResidualDataAbstract>& data,
316
                      const Eigen::Ref<const VectorXs>&) {
317
2665
      data->r.setZero();
318
2665
    }
319
320
    /**
321
     * @brief Compute the derivatives of the actuation residual
322
     *
323
     * @param[in] data  Actuation residual data
324
     * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
325
     * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
326
     */
327
3135
    virtual void calcDiff(const boost::shared_ptr<ResidualDataAbstract>& data,
328
                          const Eigen::Ref<const VectorXs>&,
329
                          const Eigen::Ref<const VectorXs>&) {
330
      typename Data::ResidualDataActuation* d =
331
3135
          static_cast<typename Data::ResidualDataActuation*>(data.get());
332
3135
      std::size_t nrow = 0;
333
3135
      const std::size_t nv = state_->get_nv();
334
3135
      d->dtau_dx.leftCols(nv) = d->pinocchio->dtau_dq;
335
3135
      d->dtau_dx.rightCols(nv) = d->pinocchio->dtau_dv;
336
3135
      d->dtau_dx -= d->actuation->dtau_dx;
337
3135
      d->dtau_du.leftCols(nv) = d->pinocchio->M;
338

3135
      d->dtau_du.rightCols(nc_) = -d->contact->Jc.transpose();
339
77748
      for (std::size_t k = 0;
340
77748
           k < static_cast<std::size_t>(d->actuation->tau_set.size()); ++k) {
341
74613
        if (!d->actuation->tau_set[k]) {
342

15675
          d->Rx.row(nrow) = d->dtau_dx.row(k);
343

15675
          d->Ru.row(nrow) = d->dtau_du.row(k);
344
15675
          nrow += 1;
345
        }
346
      }
347
3135
    }
348
349
    /**
350
     * @brief @copydoc Base::calcDiff(const
351
     * boost::shared_ptr<ResidualDataAbstract>& data, const Eigen::Ref<const
352
     * VectorXs>& x)
353
     */
354
110
    virtual void calcDiff(const boost::shared_ptr<ResidualDataAbstract>& data,
355
                          const Eigen::Ref<const VectorXs>&) {
356
110
      data->Rx.setZero();
357
110
      data->Ru.setZero();
358
110
    }
359
360
    /**
361
     * @brief Create the actuation residual data
362
     *
363
     * @return Actuation residual data
364
     */
365
27948
    virtual boost::shared_ptr<ResidualDataAbstract> createData(
366
        DataCollectorAbstract* const data) {
367
      return boost::allocate_shared<typename Data::ResidualDataActuation>(
368
          Eigen::aligned_allocator<typename Data::ResidualDataActuation>(),
369
27948
          this, data);
370
    }
371
372
    /**
373
     * @brief Print relevant information of the actuation residual model
374
     *
375
     * @param[out] os  Output stream object
376
     */
377
    virtual void print(std::ostream& os) const {
378
      os << "ResidualModelActuation {nx=" << state_->get_nx()
379
         << ", ndx=" << state_->get_ndx() << ", nu=" << nu_ << ", na=" << na_
380
         << "}";
381
    }
382
383
   protected:
384
    using Base::nu_;
385
    using Base::state_;
386
387
   private:
388
    std::size_t na_;  //!< Number of actuated joints
389
    std::size_t nc_;  //!< Number of contacts
390
  };
391
392
 public:
393
  /**
394
   * @brief Contact-acceleration residual
395
   *
396
   * This residual function is defined as \f$\mathbf{r} = \mathbf{a_0}\f$, where
397
   * \f$\mathbf{a_0}\f$ defines the desired contact acceleration, which might
398
   * also include the Baumgarte stabilization gains. Furthermore, the Jacobians
399
   * of the residual function are computed analytically. This is used by
400
   * `ConstraintModelManagerTpl` inside parent
401
   * `DifferentialActionModelContactInvDynamicsTpl` class.
402
   *
403
   * As described in `ResidualModelAbstractTpl`, the residual value and its
404
   * Jacobians are calculated by `calc` and `calcDiff`, respectively.
405
   *
406
   * \sa `ResidualModelAbstractTpl`, `calc()`, `calcDiff()`, `createData()`
407
   */
408
  class ResidualModelContact : public ResidualModelAbstractTpl<_Scalar> {
409
   public:
410
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
411
412
    typedef _Scalar Scalar;
413
    typedef MathBaseTpl<Scalar> MathBase;
414
    typedef ResidualModelAbstractTpl<Scalar> Base;
415
    typedef StateMultibodyTpl<Scalar> StateMultibody;
416
    typedef ResidualDataAbstractTpl<Scalar> ResidualDataAbstract;
417
    typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract;
418
    typedef typename MathBase::VectorXs VectorXs;
419
    typedef typename MathBase::MatrixXs MatrixXs;
420
421
    /**
422
     * @brief Initialize the contact-acceleration residual model
423
     *
424
     * @param[in] state  State of the multibody system
425
     * @param[in] id     Contact frame id
426
     * @param[in] nr     Dimension of the contact-acceleration residual
427
     * @param[in] nc     Dimension of all contacts
428
     */
429
700
    ResidualModelContact(boost::shared_ptr<StateMultibody> state,
430
                         const pinocchio::FrameIndex id, const std::size_t nr,
431
                         const std::size_t nc)
432
700
        : Base(state, nr, state->get_nv() + nc, true, true, true),
433
          id_(id),
434

1400
          frame_name_(state->get_pinocchio()->frames[id].name) {}
435
1400
    virtual ~ResidualModelContact() {}
436
437
    /**
438
     * @brief Compute the contact-acceleration residual
439
     *
440
     * @param[in] data  Contact-acceleration residual data
441
     * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
442
     * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nv+nu}\f$
443
     */
444
63366
    void calc(const boost::shared_ptr<ResidualDataAbstract>& data,
445
              const Eigen::Ref<const VectorXs>&,
446
              const Eigen::Ref<const VectorXs>&) {
447
      typename Data::ResidualDataContact* d =
448
63366
          static_cast<typename Data::ResidualDataContact*>(data.get());
449
63366
      d->r = d->contact->a0;
450
63366
    }
451
452
    /**
453
     * @brief @copydoc Base::calc(const boost::shared_ptr<ResidualDataAbstract>&
454
     * data, const Eigen::Ref<const VectorXs>& x)
455
     */
456
6998
    virtual void calc(const boost::shared_ptr<ResidualDataAbstract>& data,
457
                      const Eigen::Ref<const VectorXs>&) {
458
6998
      data->r.setZero();
459
6998
    }
460
461
    /**
462
     * @brief Compute the derivatives of the contact-acceleration residual
463
     *
464
     * @param[in] data  Contact-acceleration residual data
465
     * @param[in] x     State point \f$\mathbf{x}\in\mathbb{R}^{ndx}\f$
466
     * @param[in] u     Control input \f$\mathbf{u}\in\mathbb{R}^{nu}\f$
467
     */
468
8778
    void calcDiff(const boost::shared_ptr<ResidualDataAbstract>& data,
469
                  const Eigen::Ref<const VectorXs>&,
470
                  const Eigen::Ref<const VectorXs>&) {
471
      typename Data::ResidualDataContact* d =
472
8778
          static_cast<typename Data::ResidualDataContact*>(data.get());
473
8778
      d->Rx = d->contact->da0_dx;
474
8778
      d->Ru.leftCols(state_->get_nv()) = d->contact->Jc;
475
8778
    }
476
477
    /**
478
     * @brief @copydoc Base::calcDiff(const
479
     * boost::shared_ptr<ResidualDataAbstract>& data, const Eigen::Ref<const
480
     * VectorXs>& x)
481
     */
482
308
    virtual void calcDiff(const boost::shared_ptr<ResidualDataAbstract>& data,
483
                          const Eigen::Ref<const VectorXs>&) {
484
308
      data->Rx.setZero();
485
308
      data->Ru.setZero();
486
308
    }
487
488
    /**
489
     * @brief Create the contact-acceleration residual data
490
     *
491
     * @return contact-acceleration residual data
492
     */
493
76196
    virtual boost::shared_ptr<ResidualDataAbstract> createData(
494
        DataCollectorAbstract* const data) {
495
      return boost::allocate_shared<typename Data::ResidualDataContact>(
496
          Eigen::aligned_allocator<typename Data::ResidualDataContact>(), this,
497
76196
          data, id_);
498
    }
499
500
    /**
501
     * @brief Print relevant information of the contact-acceleration residual
502
     * model
503
     *
504
     * @param[out] os  Output stream object
505
     */
506
    virtual void print(std::ostream& os) const {
507
      os << "ResidualModelContact {frame=" << frame_name_ << ", nr=" << nr_
508
         << "}";
509
    }
510
511
   protected:
512
    using Base::nr_;
513
    using Base::nu_;
514
    using Base::state_;
515
516
   private:
517
    pinocchio::FrameIndex id_;  //!< Reference frame id
518
    std::string frame_name_;    //!< Reference frame name
519
  };
520
};
521
template <typename _Scalar>
522
struct DifferentialActionDataContactInvDynamicsTpl
523
    : public DifferentialActionDataAbstractTpl<_Scalar> {
524
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
525
  typedef _Scalar Scalar;
526
  typedef MathBaseTpl<Scalar> MathBase;
527
  typedef DifferentialActionDataAbstractTpl<Scalar> Base;
528
  typedef JointDataAbstractTpl<Scalar> JointDataAbstract;
529
  typedef DataCollectorJointActMultibodyInContactTpl<Scalar>
530
      DataCollectorJointActMultibodyInContact;
531
  typedef CostDataSumTpl<Scalar> CostDataSum;
532
  typedef ConstraintDataManagerTpl<Scalar> ConstraintDataManager;
533
  typedef ContactModelMultipleTpl<Scalar> ContactModelMultiple;
534
  typedef typename MathBase::VectorXs VectorXs;
535
  typedef typename MathBase::MatrixXs MatrixXs;
536
537
  template <template <typename Scalar> class Model>
538
31430
  explicit DifferentialActionDataContactInvDynamicsTpl(
539
      Model<Scalar>* const model)
540
      : Base(model),
541
31430
        pinocchio(pinocchio::DataTpl<Scalar>(model->get_pinocchio())),
542
        multibody(
543
31430
            &pinocchio, model->get_actuation()->createData(),
544
31430
            boost::make_shared<JointDataAbstract>(
545
                model->get_state(), model->get_actuation(), model->get_nu()),
546
31430
            model->get_contacts()->createData(&pinocchio)),
547
31430
        tmp_xstatic(model->get_state()->get_nx()),
548
62860
        tmp_rstatic(model->get_actuation()->get_nu() +
549
31430
                    model->get_contacts()->get_nc()),
550
31430
        tmp_Jstatic(model->get_state()->get_nv(),
551
62860
                    model->get_actuation()->get_nu() +
552




188580
                        model->get_contacts()->get_nc()) {
553
    // Set constant values for Fu, df_dx, and df_du
554
31430
    const std::size_t nv = model->get_state()->get_nv();
555
31430
    const std::size_t nc = model->get_contacts()->get_nc_total();
556

31430
    Fu.leftCols(nv).diagonal().setOnes();
557

31430
    multibody.joint->da_du.leftCols(nv).diagonal().setOnes();
558

62860
    MatrixXs df_dx = MatrixXs::Zero(nc, model->get_state()->get_ndx());
559

62860
    MatrixXs df_du = MatrixXs::Zero(nc, model->get_nu());
560
31430
    std::size_t fid = 0;
561
76196
    for (typename ContactModelMultiple::ContactModelContainer::const_iterator
562
31430
             it = model->get_contacts()->get_contacts().begin();
563
107626
         it != model->get_contacts()->get_contacts().end(); ++it) {
564
76196
      const std::size_t nc = it->second->contact->get_nc();
565

76196
      df_du.block(fid, nv + fid, nc, nc).diagonal().setOnes();
566
76196
      fid += nc;
567
    }
568
31430
    model->get_contacts()->updateForceDiff(multibody.contacts, df_dx, df_du);
569
31430
    costs = model->get_costs()->createData(&multibody);
570
31430
    constraints = model->get_constraints()->createData(&multibody);
571
31430
    costs->shareMemory(this);
572
31430
    constraints->shareMemory(this);
573
574
31430
    tmp_xstatic.setZero();
575
31430
    tmp_rstatic.setZero();
576
31430
    tmp_Jstatic.setZero();
577
31430
  }
578
579
  pinocchio::DataTpl<Scalar> pinocchio;                  //!< Pinocchio data
580
  DataCollectorJointActMultibodyInContact multibody;     //!< Multibody data
581
  boost::shared_ptr<CostDataSum> costs;                  //!< Costs data
582
  boost::shared_ptr<ConstraintDataManager> constraints;  //!< Constraints data
583
  VectorXs
584
      tmp_xstatic;  //!< State point used for computing the quasi-static input
585
  VectorXs
586
      tmp_rstatic;  //!< Factorization used for computing the quasi-static input
587
  MatrixXs tmp_Jstatic;  //!< Jacobian used for computing the quasi-static input
588
589
  using Base::cost;
590
  using Base::Fu;
591
  using Base::Fx;
592
  using Base::Lu;
593
  using Base::Luu;
594
  using Base::Lx;
595
  using Base::Lxu;
596
  using Base::Lxx;
597
  using Base::r;
598
  using Base::xout;
599
600
  struct ResidualDataActuation : public ResidualDataAbstractTpl<_Scalar> {
601
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
602
603
    typedef _Scalar Scalar;
604
    typedef MathBaseTpl<Scalar> MathBase;
605
    typedef ResidualDataAbstractTpl<Scalar> Base;
606
    typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract;
607
    typedef DataCollectorActMultibodyInContactTpl<Scalar>
608
        DataCollectorActMultibodyInContact;
609
    typedef ActuationDataAbstractTpl<Scalar> ActuationDataAbstract;
610
    typedef ContactDataMultipleTpl<Scalar> ContactDataMultiple;
611
    typedef typename MathBase::MatrixXs MatrixXs;
612
613
    template <template <typename Scalar> class Model>
614
27948
    ResidualDataActuation(Model<Scalar>* const model,
615
                          DataCollectorAbstract* const data)
616
        : Base(model, data),
617
55896
          dtau_dx(model->get_state()->get_nv(), model->get_state()->get_ndx()),
618

27948
          dtau_du(model->get_state()->get_nv(), model->get_nu()) {
619
      // Check that proper shared data has been passed
620
      DataCollectorActMultibodyInContact* d =
621
27948
          dynamic_cast<DataCollectorActMultibodyInContact*>(shared);
622
27948
      if (d == NULL) {
623
        throw_pretty(
624
            "Invalid argument: the shared data should be derived from "
625
            "DataCollectorActMultibodyInContact");
626
      }
627
      // Avoids data casting at runtime
628
27948
      pinocchio = d->pinocchio;
629
27948
      actuation = d->actuation;
630
27948
      contact = d->contacts;
631
27948
      dtau_dx.setZero();
632
27948
      dtau_du.setZero();
633
27948
    }
634
635
    pinocchio::DataTpl<Scalar>* pinocchio;               //!< Pinocchio data
636
    boost::shared_ptr<ActuationDataAbstract> actuation;  //!< Actuation data
637
    boost::shared_ptr<ContactDataMultiple> contact;      //!< Contact data
638
    MatrixXs dtau_dx;
639
    MatrixXs dtau_du;
640
    using Base::r;
641
    using Base::Ru;
642
    using Base::Rx;
643
    using Base::shared;
644
  };
645
646
  struct ResidualDataContact : public ResidualDataAbstractTpl<_Scalar> {
647
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
648
649
    typedef _Scalar Scalar;
650
    typedef MathBaseTpl<Scalar> MathBase;
651
    typedef ResidualDataAbstractTpl<Scalar> Base;
652
    typedef DataCollectorAbstractTpl<Scalar> DataCollectorAbstract;
653
    typedef DataCollectorMultibodyInContactTpl<Scalar>
654
        DataCollectorMultibodyInContact;
655
    typedef ContactModelMultipleTpl<Scalar> ContactModelMultiple;
656
657
    template <template <typename Scalar> class Model>
658
76196
    ResidualDataContact(Model<Scalar>* const model,
659
                        DataCollectorAbstract* const data, const std::size_t id)
660
76196
        : Base(model, data) {
661
      DataCollectorMultibodyInContact* d =
662
76196
          dynamic_cast<DataCollectorMultibodyInContact*>(shared);
663
76196
      if (d == NULL) {
664
        throw_pretty(
665
            "Invalid argument: the shared data should be derived from "
666
            "DataCollectorMultibodyInContact");
667
      }
668
76196
      typename ContactModelMultiple::ContactDataContainer::iterator it, end;
669
151420
      for (it = d->contacts->contacts.begin(),
670
76196
          end = d->contacts->contacts.end();
671
226644
           it != end; ++it) {
672
151420
        if (id == it->second->frame) {  // TODO(cmastalli): use model->get_id()
673
                                        // and avoid to pass id in constructor
674
76196
          contact = it->second.get();
675
76196
          break;
676
        }
677
      }
678
76196
    }
679
680
    ContactDataAbstractTpl<Scalar>* contact;  //!< Contact force data
681
    using Base::r;
682
    using Base::Ru;
683
    using Base::Rx;
684
    using Base::shared;
685
  };
686
};
687
}  // namespace crocoddyl
688
689
/* --- Details -------------------------------------------------------------- */
690
/* --- Details -------------------------------------------------------------- */
691
/* --- Details -------------------------------------------------------------- */
692
#include <crocoddyl/multibody/actions/contact-invdyn.hxx>
693
694
#endif  // CROCODDYL_MULTIBODY_ACTIONS_CONTACT_INVDYN_HPP_