GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/pinocchio/algorithm/contact-dynamics.hxx Lines: 83 83 100.0 %
Date: 2024-04-26 13:14:21 Branches: 87 416 20.9 %

Line Branch Exec Source
1
//
2
// Copyright (c) 2016-2020 CNRS INRIA
3
//
4
5
#ifndef __pinocchio_contact_dynamics_hxx__
6
#define __pinocchio_contact_dynamics_hxx__
7
8
#include "pinocchio/algorithm/compute-all-terms.hpp"
9
#include "pinocchio/algorithm/cholesky.hpp"
10
#include "pinocchio/algorithm/crba.hpp"
11
#include "pinocchio/algorithm/check.hpp"
12
13
#include <Eigen/Cholesky>
14
15
namespace pinocchio
16
{
17
18
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename TangentVectorType,
19
  typename ConstraintMatrixType, typename DriftVectorType>
20
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::TangentVectorType &
21
199
  forwardDynamics(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
22
                  DataTpl<Scalar,Options,JointCollectionTpl> & data,
23
                  const Eigen::MatrixBase<TangentVectorType> & tau,
24
                  const Eigen::MatrixBase<ConstraintMatrixType> & J,
25
                  const Eigen::MatrixBase<DriftVectorType> & gamma,
26
                  const Scalar inv_damping)
27
  {
28






199
    PINOCCHIO_CHECK_ARGUMENT_SIZE(tau.size(), model.nv);
29






199
    PINOCCHIO_CHECK_ARGUMENT_SIZE(J.cols(), model.nv);
30







199
    PINOCCHIO_CHECK_ARGUMENT_SIZE(J.rows(), gamma.size());
31
199
    assert(model.check(data) && "data is not consistent with model.");
32
33
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
34
35
199
    typename Data::TangentVectorType & a = data.ddq;
36
199
    typename Data::VectorXs & lambda_c = data.lambda_c;
37
38
    // Compute the UDUt decomposition of data.M
39
199
    cholesky::decompose(model, data);
40
41
    // Compute the dynamic drift (control - nle)
42
199
    data.torque_residual = tau - data.nle;
43
199
    cholesky::solve(model, data, data.torque_residual);
44
45
199
    data.sDUiJt = J.transpose();
46
    // Compute U^-1 * J.T
47
199
    cholesky::Uiv(model, data, data.sDUiJt);
48
6553
    for(Eigen::DenseIndex k=0;k<model.nv;++k)
49

6354
      data.sDUiJt.row(k) /= sqrt(data.D[k]);
50
51

199
    data.JMinvJt.noalias() = data.sDUiJt.transpose() * data.sDUiJt;
52
53

199
    data.JMinvJt.diagonal().array() += inv_damping;
54
199
    data.llt_JMinvJt.compute(data.JMinvJt);
55
56
    // Compute the Lagrange Multipliers
57

199
    lambda_c.noalias() = -J*data.torque_residual;
58
199
    lambda_c -= gamma;
59
199
    data.llt_JMinvJt.solveInPlace(lambda_c);
60
61
    // Compute the joint acceleration
62

199
    a.noalias() = J.transpose() * lambda_c;
63
199
    cholesky::solve(model, data, a);
64
199
    a += data.torque_residual;
65
66
199
    return a;
67
  }
68
69
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType, typename TangentVectorType1, typename TangentVectorType2,
70
  typename ConstraintMatrixType, typename DriftVectorType>
71
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::TangentVectorType &
72
199
  forwardDynamics(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
73
                  DataTpl<Scalar,Options,JointCollectionTpl> & data,
74
                  const Eigen::MatrixBase<ConfigVectorType> & q,
75
                  const Eigen::MatrixBase<TangentVectorType1> & v,
76
                  const Eigen::MatrixBase<TangentVectorType2> & tau,
77
                  const Eigen::MatrixBase<ConstraintMatrixType> & J,
78
                  const Eigen::MatrixBase<DriftVectorType> & gamma,
79
                  const Scalar inv_damping)
80
  {
81






199
    PINOCCHIO_CHECK_ARGUMENT_SIZE(q.size(), model.nq);
82






199
    PINOCCHIO_CHECK_ARGUMENT_SIZE(v.size(), model.nv);
83
84
199
    computeAllTerms(model, data, q, v);
85
86
199
    return forwardDynamics(model,data,tau,J,gamma,inv_damping);
87
  }
88
89
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl,
90
           typename ConfigVectorType, typename ConstraintMatrixType, typename KKTMatrixType>
91
1
  void computeKKTContactDynamicMatrixInverse(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
92
                                             DataTpl<Scalar,Options,JointCollectionTpl> & data,
93
                                             const Eigen::MatrixBase<ConfigVectorType> & q,
94
                                             const Eigen::MatrixBase<ConstraintMatrixType> & J,
95
                                             const Eigen::MatrixBase<KKTMatrixType> & KKTMatrix_inv,
96
                                             const Scalar & inv_damping)
97
  {
98
1
    assert(model.check(data));
99

1
    PINOCCHIO_CHECK_INPUT_ARGUMENT(inv_damping >= 0., "mu must be positive.");
100
101
    // Compute the mass matrix.
102
1
    crbaMinimal(model,data,q);
103
104
    // Compute the UDUt decomposition of data.M.
105
1
    cholesky::decompose(model, data);
106
107
    using std::sqrt;
108
1
    data.sDUiJt = J.transpose();
109
    // Compute U^-1 * J.T
110
1
    cholesky::Uiv(model, data, data.sDUiJt);
111
33
    for(Eigen::DenseIndex k=0;k<model.nv;++k)
112

32
      data.sDUiJt.row(k) /= sqrt(data.D[k]);
113
114

1
    data.JMinvJt.noalias() = data.sDUiJt.transpose() * data.sDUiJt;
115
116

1
    data.JMinvJt.diagonal().array() += inv_damping;
117
1
    data.llt_JMinvJt.compute(data.JMinvJt);
118
119
1
    getKKTContactDynamicMatrixInverse(model,data,J,KKTMatrix_inv.const_cast_derived());
120
1
  }
121
122
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl,
123
  typename ConstraintMatrixType, typename KKTMatrixType>
124
3
  inline void getKKTContactDynamicMatrixInverse(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
125
                                                const DataTpl<Scalar,Options,JointCollectionTpl> & data,
126
                                                const Eigen::MatrixBase<ConstraintMatrixType> & J,
127
                                                const Eigen::MatrixBase<KKTMatrixType> & KKTMatrix_inv)
128
  {
129

3
    assert(model.check(data));
130








3
    PINOCCHIO_CHECK_ARGUMENT_SIZE(KKTMatrix_inv.cols(), data.JMinvJt.cols() + model.nv);
131








3
    PINOCCHIO_CHECK_ARGUMENT_SIZE(KKTMatrix_inv.rows(), data.JMinvJt.rows() + model.nv);
132
133
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
134
3
    const Eigen::DenseIndex nc = data.JMinvJt.cols();
135
136
3
    KKTMatrixType & KKTMatrix_inv_ = PINOCCHIO_EIGEN_CONST_CAST(KKTMatrixType,KKTMatrix_inv);
137
138
    typedef Eigen::Block<KKTMatrixType> BlockType;
139
3
    BlockType topLeft = KKTMatrix_inv_.topLeftCorner(model.nv, model.nv);
140
3
    BlockType topRight = KKTMatrix_inv_.topRightCorner(model.nv, nc);
141
3
    BlockType bottomLeft = KKTMatrix_inv_.bottomLeftCorner(nc, model.nv);
142
3
    BlockType bottomRight = KKTMatrix_inv_.bottomRightCorner(nc, nc);
143
144


3
    bottomRight = -Data::MatrixXs::Identity(nc,nc); data.llt_JMinvJt.solveInPlace(bottomRight);
145

3
    topLeft.setIdentity(); cholesky::solve(model, data, topLeft);
146
147

3
    bottomLeft.noalias() = J*topLeft;
148


3
    topRight.noalias() = bottomLeft.transpose() * (-bottomRight);
149

3
    topLeft.noalias() -= topRight*bottomLeft;
150

3
    bottomLeft = topRight.transpose();
151
3
  }
152
153
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType, typename TangentVectorType, typename ConstraintMatrixType>
154
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::TangentVectorType &
155
2
  impulseDynamics(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
156
                  DataTpl<Scalar,Options,JointCollectionTpl> & data,
157
                  const Eigen::MatrixBase<ConfigVectorType> & q,
158
                  const Eigen::MatrixBase<TangentVectorType> & v_before,
159
                  const Eigen::MatrixBase<ConstraintMatrixType> & J,
160
                  const Scalar r_coeff,
161
                  const Scalar inv_damping)
162
  {
163






2
    PINOCCHIO_CHECK_ARGUMENT_SIZE(q.size(), model.nq);
164
165
    // Compute the mass matrix
166
2
    crba(model, data, q);
167
168
2
    return impulseDynamics(model,data,v_before,J,r_coeff,inv_damping);
169
  }
170
171
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename TangentVectorType, typename ConstraintMatrixType>
172
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::TangentVectorType &
173
2
  impulseDynamics(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
174
                  DataTpl<Scalar,Options,JointCollectionTpl> & data,
175
                  const Eigen::MatrixBase<TangentVectorType> & v_before,
176
                  const Eigen::MatrixBase<ConstraintMatrixType> & J,
177
                  const Scalar r_coeff,
178
                  const Scalar inv_damping)
179
  {
180






2
    PINOCCHIO_CHECK_ARGUMENT_SIZE(v_before.size(), model.nv);
181






2
    PINOCCHIO_CHECK_ARGUMENT_SIZE(J.cols(), model.nv);
182
2
    assert(model.check(data) && "data is not consistent with model.");
183
184
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
185
186
2
    typename Data::VectorXs & impulse_c = data.impulse_c;
187
2
    typename Data::TangentVectorType & dq_after = data.dq_after;
188
189
    // Compute the UDUt decomposition of data.M
190
2
    cholesky::decompose(model, data);
191
192
2
    data.sDUiJt = J.transpose();
193
    // Compute U^-1 * J.T
194
2
    cholesky::Uiv(model, data, data.sDUiJt);
195

66
    for(int k=0;k<model.nv;++k) data.sDUiJt.row(k) /= sqrt(data.D[k]);
196
197

2
    data.JMinvJt.noalias() = data.sDUiJt.transpose() * data.sDUiJt;
198
199

2
    data.JMinvJt.diagonal().array() += inv_damping;
200
2
    data.llt_JMinvJt.compute(data.JMinvJt);
201
202
    // Compute the Lagrange Multipliers related to the contact impulses
203

2
    impulse_c.noalias() = (-r_coeff - 1.) * (J * v_before);
204
2
    data.llt_JMinvJt.solveInPlace(impulse_c);
205
206
    // Compute the joint velocity after impacts
207

2
    dq_after.noalias() = J.transpose() * impulse_c;
208
2
    cholesky::solve(model, data, dq_after);
209
2
    dq_after += v_before;
210
211
2
    return dq_after;
212
  }
213
} // namespace pinocchio
214
215
#endif // ifndef __pinocchio_contact_dynamics_hxx__