Directory: | ./ |
---|---|
File: | include/pinocchio/algorithm/contact-inverse-dynamics.hpp |
Date: | 2025-02-12 21:03:38 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 78 | 80 | 97.5% |
Branches: | 102 | 284 | 35.9% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | // | ||
2 | // Copyright (c) 2024 INRIA | ||
3 | // | ||
4 | |||
5 | #ifndef __pinocchio_algorithm_contact_inverse_dynamics__hpp__ | ||
6 | #define __pinocchio_algorithm_contact_inverse_dynamics__hpp__ | ||
7 | |||
8 | #include "pinocchio/multibody/model.hpp" | ||
9 | #include "pinocchio/multibody/data.hpp" | ||
10 | #include "pinocchio/algorithm/constraints/coulomb-friction-cone.hpp" | ||
11 | #include "pinocchio/algorithm/rnea.hpp" | ||
12 | #include <boost/optional/optional.hpp> | ||
13 | #include <pinocchio/algorithm/contact-cholesky.hpp> | ||
14 | #include <pinocchio/algorithm/contact-jacobian.hpp> | ||
15 | #include "pinocchio/algorithm/proximal.hpp" | ||
16 | |||
17 | #include <boost/optional.hpp> | ||
18 | |||
19 | namespace pinocchio | ||
20 | { | ||
21 | |||
22 | /// | ||
23 | /// \brief Compute the contact impulses given a target velocity of contact points. | ||
24 | /// | ||
25 | /// \tparam JointCollection Collection of Joint types. | ||
26 | /// \tparam ConfigVectorType Type of the joint configuration vector. | ||
27 | /// \tparam TangentVectorType1 Type of the joint velocity vector. | ||
28 | /// \tparam TangentVectorType2 Type of the joint acceleration vector. | ||
29 | /// | ||
30 | /// \param[in] model The model structure of the rigid body system. | ||
31 | /// \param[in] data The data structure of the rigid body system. | ||
32 | /// \param[in] c_ref The contact point velocity | ||
33 | /// \param[in] contact_models The list of contact models. | ||
34 | /// \param[in] contact_datas The list of contact_datas. | ||
35 | /// \param[in] cones list of friction cones. | ||
36 | /// \param[in] R vector representing the diagonal of the compliance matrix. | ||
37 | /// \param[in] constraint_correction vector representing the constraint correction. | ||
38 | /// \param[in] settings The settings for the proximal algorithm. | ||
39 | /// \param[in] impulse_guess initial guess for the contact impulses. | ||
40 | /// | ||
41 | /// \return The desired joint torques stored in data.tau. | ||
42 | /// | ||
43 | template< | ||
44 | typename Scalar, | ||
45 | int Options, | ||
46 | template<typename, int> class JointCollectionTpl, | ||
47 | typename VectorLikeC, | ||
48 | class ConstraintModelAllocator, | ||
49 | class ConstraintDataAllocator, | ||
50 | class CoulombFrictionConelAllocator, | ||
51 | typename VectorLikeR, | ||
52 | typename VectorLikeGamma, | ||
53 | typename VectorLikeImp> | ||
54 | PINOCCHIO_UNSUPPORTED_MESSAGE("The API will change towards more flexibility") | ||
55 | const typename DataTpl<Scalar, Options, JointCollectionTpl>:: | ||
56 | 7 | TangentVectorType & computeContactImpulses( | |
57 | const ModelTpl<Scalar, Options, JointCollectionTpl> & model, | ||
58 | DataTpl<Scalar, Options, JointCollectionTpl> & data, | ||
59 | const Eigen::MatrixBase<VectorLikeC> & c_ref, | ||
60 | const std::vector<RigidConstraintModelTpl<Scalar, Options>, ConstraintModelAllocator> & | ||
61 | contact_models, | ||
62 | std::vector<RigidConstraintDataTpl<Scalar, Options>, ConstraintDataAllocator> & contact_datas, | ||
63 | const std::vector<CoulombFrictionConeTpl<Scalar>, CoulombFrictionConelAllocator> & cones, | ||
64 | const Eigen::MatrixBase<VectorLikeR> & R, | ||
65 | const Eigen::MatrixBase<VectorLikeGamma> & constraint_correction, | ||
66 | ProximalSettingsTpl<Scalar> & settings, | ||
67 | const boost::optional<VectorLikeImp> & impulse_guess = boost::none) | ||
68 | { | ||
69 | |||
70 | typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Options> MatrixXs; | ||
71 | typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1, Options> VectorXs; | ||
72 | typedef Eigen::Matrix<Scalar, 3, 1, Options> Vector3; | ||
73 | |||
74 | 7 | int problem_size = R.size(); | |
75 | 7 | int n_contacts = (int)problem_size / 3; | |
76 |
1/24✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
|
7 | PINOCCHIO_CHECK_ARGUMENT_SIZE(constraint_correction.size(), problem_size); |
77 |
1/24✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
|
7 | PINOCCHIO_CHECK_ARGUMENT_SIZE(contact_models.size(), n_contacts); |
78 |
1/24✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
|
7 | PINOCCHIO_CHECK_ARGUMENT_SIZE(contact_datas.size(), n_contacts); |
79 |
2/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
7 | PINOCCHIO_CHECK_INPUT_ARGUMENT( |
80 | check_expression_if_real<Scalar>(settings.mu > Scalar(0)), "mu has to be strictly positive"); | ||
81 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
7 | MatrixXs J = MatrixXs::Zero(problem_size, model.nv); // TODO: malloc |
82 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
7 | getConstraintsJacobian(model, data, contact_models, contact_datas, J); |
83 |
5/10✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
|
7 | VectorXs c_ref_cor, desaxce_correction, R_prox, impulse_c_prev, dimpulse_c; // TODO: malloc |
84 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
7 | R_prox = R + VectorXs::Constant(problem_size, settings.mu); |
85 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
7 | c_ref_cor = c_ref + constraint_correction; |
86 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
7 | if (impulse_guess) |
87 | { | ||
88 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
6 | data.impulse_c = impulse_guess.get(); |
89 |
1/24✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
|
6 | PINOCCHIO_CHECK_ARGUMENT_SIZE(data.impulse_c.size(), problem_size); |
90 | } | ||
91 | else | ||
92 | { | ||
93 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | data.impulse_c.setZero(); |
94 | } | ||
95 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
7 | Scalar impulse_c_prev_norm_inf = data.impulse_c.template lpNorm<Eigen::Infinity>(); |
96 | Scalar complementarity, dual_feasibility; | ||
97 | 7 | bool abs_prec_reached = false, rel_prec_reached = false; | |
98 | 7 | const size_t nc = cones.size(); // num constraints | |
99 | 7 | settings.iter = 1; | |
100 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
7 | for (; settings.iter <= settings.max_iter; ++settings.iter) |
101 | { | ||
102 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
7 | impulse_c_prev = data.impulse_c; |
103 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
|
21 | for (size_t cone_id = 0; cone_id < nc; ++cone_id) |
104 | { | ||
105 | 14 | const Eigen::DenseIndex row_id = 3 * cone_id; | |
106 | 14 | const auto & cone = cones[cone_id]; | |
107 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
14 | auto impulse_segment = data.impulse_c.template segment<3>(row_id); |
108 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
14 | auto impulse_prev_segment = impulse_c_prev.template segment<3>(row_id); |
109 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
14 | auto R_prox_segment = R_prox.template segment<3>(row_id); |
110 | // Vector3 desaxce_segment; | ||
111 | // auto desaxce_segment = desaxce_correction.template segment<3>(row_id); | ||
112 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
14 | auto c_ref_segment = c_ref.template segment<3>(row_id); |
113 |
4/8✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
|
14 | Vector3 desaxce_segment = cone.computeNormalCorrection( |
114 | c_ref_segment | ||
115 |
3/6✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
|
14 | + (R.template segment<3>(row_id).array() * impulse_segment.array()).matrix()); |
116 |
7/14✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 20 not taken.
|
14 | impulse_segment = |
117 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
14 | -((c_ref_segment + desaxce_segment - settings.mu * impulse_prev_segment).array() |
118 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
14 | / R_prox_segment.array()) |
119 | .matrix(); | ||
120 |
2/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
14 | impulse_segment = cone.weightedProject(impulse_segment, R_prox_segment); |
121 | } | ||
122 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
7 | dimpulse_c = data.impulse_c - impulse_c_prev; |
123 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
7 | settings.relative_residual = dimpulse_c.template lpNorm<Eigen::Infinity>(); |
124 | |||
125 | // if( check_expression_if_real<Scalar,false>(complementarity <= this->absolute_precision) | ||
126 | // && check_expression_if_real<Scalar,false>(dual_feasibility <= this->absolute_precision) | ||
127 | // && check_expression_if_real<Scalar,false>(primal_feasibility <= | ||
128 | // this->absolute_precision)) | ||
129 | // abs_prec_reached = true; | ||
130 | // else | ||
131 | // abs_prec_reached = false; | ||
132 | |||
133 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
7 | const Scalar impulse_c_norm_inf = data.impulse_c.template lpNorm<Eigen::Infinity>(); |
134 | 14 | if (check_expression_if_real<Scalar, false>( | |
135 | 7 | settings.relative_residual | |
136 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
7 | <= settings.relative_accuracy * math::max(impulse_c_norm_inf, impulse_c_prev_norm_inf))) |
137 | 7 | rel_prec_reached = true; | |
138 | else | ||
139 | ✗ | rel_prec_reached = false; | |
140 | |||
141 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
7 | if (abs_prec_reached || rel_prec_reached) |
142 | break; | ||
143 | |||
144 | ✗ | impulse_c_prev_norm_inf = impulse_c_norm_inf; | |
145 | } | ||
146 | 7 | return data.impulse_c; | |
147 | 7 | } | |
148 | |||
149 | /// | ||
150 | /// \brief The Contact Inverse Dynamics algorithm. It computes the inverse dynamics in the | ||
151 | /// presence of contacts, aka the joint torques according to the current state of the system and | ||
152 | /// the desired joint accelerations. | ||
153 | /// | ||
154 | /// \tparam JointCollection Collection of Joint types. | ||
155 | /// \tparam ConfigVectorType Type of the joint configuration vector. | ||
156 | /// \tparam TangentVectorType1 Type of the joint velocity vector. | ||
157 | /// \tparam TangentVectorType2 Type of the joint acceleration vector. | ||
158 | /// | ||
159 | /// \param[in] model The model structure of the rigid body system. | ||
160 | /// \param[in] data The data structure of the rigid body system. | ||
161 | /// \param[in] q The joint configuration vector (dim model.nq). | ||
162 | /// \param[in] v The joint velocity vector (dim model.nv). | ||
163 | /// \param[in] a The joint acceleration vector (dim model.nv). | ||
164 | /// \param[in] dt The time step. | ||
165 | /// \param[in] contact_models The list of contact models. | ||
166 | /// \param[in] contact_datas The list of contact_datas. | ||
167 | /// \param[in] cones list of friction cones. | ||
168 | /// \param[in] R vector representing the diagonal of the compliance matrix. | ||
169 | /// \param[in] constraint_correction vector representing the constraint correction. | ||
170 | /// \param[in] settings The settings for the proximal algorithm. | ||
171 | /// \param[in] lambda_guess initial guess for the contact forces. | ||
172 | /// | ||
173 | /// \return The desired joint torques stored in data.tau. | ||
174 | /// | ||
175 | template< | ||
176 | typename Scalar, | ||
177 | int Options, | ||
178 | template<typename, int> class JointCollectionTpl, | ||
179 | typename ConfigVectorType, | ||
180 | typename TangentVectorType1, | ||
181 | typename TangentVectorType2, | ||
182 | class ConstraintModelAllocator, | ||
183 | class ConstraintDataAllocator, | ||
184 | class CoulombFrictionConelAllocator, | ||
185 | typename VectorLikeR, | ||
186 | typename VectorLikeGamma, | ||
187 | typename VectorLikeLam> | ||
188 | PINOCCHIO_UNSUPPORTED_MESSAGE("The API will change towards more flexibility") | ||
189 | const typename DataTpl<Scalar, Options, JointCollectionTpl>:: | ||
190 | 4 | TangentVectorType & contactInverseDynamics( | |
191 | const ModelTpl<Scalar, Options, JointCollectionTpl> & model, | ||
192 | DataTpl<Scalar, Options, JointCollectionTpl> & data, | ||
193 | const Eigen::MatrixBase<ConfigVectorType> & q, | ||
194 | const Eigen::MatrixBase<TangentVectorType1> & v, | ||
195 | const Eigen::MatrixBase<TangentVectorType2> & a, | ||
196 | Scalar dt, | ||
197 | const std::vector<RigidConstraintModelTpl<Scalar, Options>, ConstraintModelAllocator> & | ||
198 | contact_models, | ||
199 | std::vector<RigidConstraintDataTpl<Scalar, Options>, ConstraintDataAllocator> & contact_datas, | ||
200 | const std::vector<CoulombFrictionConeTpl<Scalar>, CoulombFrictionConelAllocator> & cones, | ||
201 | const Eigen::MatrixBase<VectorLikeR> & R, | ||
202 | const Eigen::MatrixBase<VectorLikeGamma> & constraint_correction, | ||
203 | ProximalSettingsTpl<Scalar> & settings, | ||
204 | const boost::optional<VectorLikeLam> & lambda_guess = boost::none) | ||
205 | { | ||
206 | |||
207 | typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Options> MatrixXs; | ||
208 | typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1, Options> VectorXs; | ||
209 | typedef ForceTpl<Scalar, Options> Force; | ||
210 | typedef RigidConstraintDataTpl<Scalar, Options> RigidConstraintData; | ||
211 | |||
212 | 4 | int problem_size = R.size(); | |
213 | 4 | int n_contacts = (int)problem_size / 3; | |
214 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | MatrixXs J = MatrixXs::Zero(problem_size, model.nv); // TODO: malloc |
215 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | getConstraintsJacobian(model, data, contact_models, contact_datas, J); |
216 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
4 | VectorXs v_ref, c_ref, tau_c; |
217 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
4 | v_ref = v + dt * a; |
218 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
4 | c_ref.noalias() = J * v_ref; // TODO should rather use the displacement |
219 | 4 | boost::optional<VectorXs> impulse_guess = boost::none; | |
220 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | if (lambda_guess) |
221 | { | ||
222 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | data.impulse_c = lambda_guess.get(); |
223 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | data.impulse_c *= dt; |
224 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | impulse_guess = boost::make_optional(data.impulse_c); |
225 | } | ||
226 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | computeContactImpulses( |
227 | model, data, c_ref, contact_models, contact_datas, cones, R, constraint_correction, settings, | ||
228 | impulse_guess); | ||
229 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | data.lambda_c = data.impulse_c / dt; |
230 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | container::aligned_vector<Force> fext(model.njoints); |
231 |
2/2✓ Branch 0 taken 130 times.
✓ Branch 1 taken 4 times.
|
134 | for (int i = 0; i < model.njoints; i++) |
232 | { | ||
233 |
2/4✓ Branch 1 taken 130 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 130 times.
✗ Branch 6 not taken.
|
130 | fext[i] = Force::Zero(); |
234 | } | ||
235 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
|
12 | for (int i = 0; i < n_contacts; i++) |
236 | { | ||
237 | 8 | const auto & cmodel = contact_models[i]; | |
238 | 8 | const Eigen::DenseIndex row_id = 3 * i; | |
239 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto lambda_segment = data.lambda_c.template segment<3>(row_id); |
240 | 8 | typename RigidConstraintData::Matrix6 actInv_transpose1 = | |
241 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | cmodel.joint1_placement.toActionMatrixInverse(); |
242 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | actInv_transpose1.transposeInPlace(); |
243 |
4/8✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 8 times.
✗ Branch 12 not taken.
|
8 | fext[cmodel.joint1_id] += Force(actInv_transpose1.template leftCols<3>() * lambda_segment); |
244 | 8 | typename RigidConstraintData::Matrix6 actInv_transpose2 = | |
245 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | cmodel.joint2_placement.toActionMatrixInverse(); |
246 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | actInv_transpose2.transposeInPlace(); |
247 |
4/8✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 8 times.
✗ Branch 12 not taken.
|
8 | fext[cmodel.joint2_id] += Force(actInv_transpose2.template leftCols<3>() * lambda_segment); |
248 | } | ||
249 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | rnea(model, data, q, v, a, fext); |
250 | 4 | return data.tau; | |
251 | 4 | } | |
252 | |||
253 | } // namespace pinocchio | ||
254 | |||
255 | // #if PINOCCHIO_ENABLE_TEMPLATE_INSTANTIATION | ||
256 | // #include "pinocchio/algorithm/contact-inverse-dynamics.txx" | ||
257 | // #endif // PINOCCHIO_ENABLE_TEMPLATE_INSTANTIATION | ||
258 | |||
259 | #endif // ifndef __pinocchio_algorithm_contact_inverse_dynamics_hpp__ | ||
260 |