GCC Code Coverage Report


Directory: ./
File: include/pinocchio/algorithm/contact-cholesky.hxx
Date: 2025-02-12 21:03:38
Exec Total Coverage
Lines: 274 279 98.2%
Branches: 251 542 46.3%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019-2024 INRIA
3 //
4
5 #ifndef __pinocchio_algorithm_contact_cholesky_hxx__
6 #define __pinocchio_algorithm_contact_cholesky_hxx__
7
8 #include "pinocchio/algorithm/check.hpp"
9
10 #include <algorithm>
11
12 namespace pinocchio
13 {
14
15 // TODO Remove when API is stabilized
16 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
17 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_DEPRECECATED_DECLARATIONS
18
19 template<typename Scalar, int Options>
20 template<typename S1, int O1, template<typename, int> class JointCollectionTpl, class Allocator>
21 84 void ContactCholeskyDecompositionTpl<Scalar, Options>::allocate(
22 const ModelTpl<S1, O1, JointCollectionTpl> & model,
23 const std::vector<RigidConstraintModelTpl<S1, O1>, Allocator> & contact_models)
24 {
25 typedef ModelTpl<S1, O1, JointCollectionTpl> Model;
26 typedef typename Model::JointModel JointModel;
27 typedef RigidConstraintModelTpl<S1, O1> RigidConstraintModel;
28 typedef std::vector<RigidConstraintModel, Allocator> RigidConstraintModelVector;
29
30 84 nv = model.nv;
31 84 num_contacts = (Eigen::DenseIndex)contact_models.size();
32
33 84 Eigen::DenseIndex num_total_constraints = 0;
34 84 for (typename RigidConstraintModelVector::const_iterator it = contact_models.begin();
35
2/2
✓ Branch 2 taken 132 times.
✓ Branch 3 taken 84 times.
216 it != contact_models.end(); ++it)
36 {
37
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 132 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
132 PINOCCHIO_CHECK_INPUT_ARGUMENT(
38 it->size() > 0, "The dimension of the constraint must be positive");
39 132 num_total_constraints += it->size();
40 }
41
42 84 U1inv.resize(num_total_constraints, num_total_constraints);
43 84 OSIMinv_tmp.resize(num_total_constraints, num_total_constraints);
44 84 U4inv.resize(nv, nv);
45 84 Minv_tmp.resize(nv, nv);
46
47 84 const Eigen::DenseIndex total_dim = nv + num_total_constraints;
48
49 // Compute first parents_fromRow for all the joints.
50 // This code is very similar to the code of Data::computeParents_fromRow,
51 // but shifted with a value corresponding to the number of constraints.
52 84 parents_fromRow.resize(total_dim);
53
1/2
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 parents_fromRow.fill(-1);
54
55 84 nv_subtree_fromRow.resize(total_dim);
56 // nv_subtree_fromRow.fill(0);
57
58 84 last_child.resize(model.njoints);
59
1/2
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 last_child.fill(-1);
60
2/2
✓ Branch 0 taken 2201 times.
✓ Branch 1 taken 84 times.
2285 for (long joint_id = model.njoints - 1; joint_id >= 0; --joint_id)
61 {
62 2201 const JointIndex & parent = model.parents[(size_t)joint_id];
63
2/2
✓ Branch 1 taken 318 times.
✓ Branch 2 taken 1883 times.
2201 if (last_child[joint_id] == -1)
64 318 last_child[joint_id] = joint_id;
65 2201 last_child[(Eigen::DenseIndex)parent] =
66 2201 std::max(last_child[joint_id], last_child[(Eigen::DenseIndex)parent]);
67 }
68
69 // Fill nv_subtree_fromRow for model
70
2/2
✓ Branch 0 taken 2117 times.
✓ Branch 1 taken 84 times.
2201 for (JointIndex joint_id = 1; joint_id < (JointIndex)(model.njoints); joint_id++)
71 {
72 2117 const JointIndex parent_id = model.parents[joint_id];
73
74 2117 const JointModel & joint = model.joints[joint_id];
75 2117 const JointModel & parent_joint = model.joints[parent_id];
76 2117 const int nvj = joint.nv();
77 2117 const int idx_vj = joint.idx_v();
78
79
2/2
✓ Branch 0 taken 2033 times.
✓ Branch 1 taken 84 times.
2117 if (parent_id > 0)
80 2033 parents_fromRow[idx_vj + num_total_constraints] =
81 2033 parent_joint.idx_v() + parent_joint.nv() - 1 + num_total_constraints;
82 else
83 84 parents_fromRow[idx_vj + num_total_constraints] = -1;
84
85 4234 nv_subtree_fromRow[idx_vj + num_total_constraints] =
86 2117 model.joints[(size_t)last_child[(Eigen::DenseIndex)joint_id]].idx_v()
87 2117 + model.joints[(size_t)last_child[(Eigen::DenseIndex)joint_id]].nv() - idx_vj;
88
89
2/2
✓ Branch 0 taken 415 times.
✓ Branch 1 taken 2117 times.
2532 for (int row = 1; row < nvj; ++row)
90 {
91 830 parents_fromRow[idx_vj + num_total_constraints + row] =
92 415 idx_vj + row - 1 + num_total_constraints;
93 415 nv_subtree_fromRow[idx_vj + num_total_constraints + row] =
94 415 nv_subtree_fromRow[idx_vj + num_total_constraints] - row;
95 }
96 }
97
98 84 Eigen::DenseIndex row_id = 0;
99 84 for (typename RigidConstraintModelVector::const_iterator it = contact_models.begin();
100
2/2
✓ Branch 3 taken 132 times.
✓ Branch 4 taken 84 times.
216 it != contact_models.end(); ++it)
101 {
102 132 const RigidConstraintModel & cmodel = *it;
103 132 const JointIndex joint1_id = cmodel.joint1_id;
104 132 const JointModel & joint1 = model.joints[joint1_id];
105 132 const JointIndex joint2_id = cmodel.joint2_id;
106 132 const JointModel & joint2 = model.joints[joint2_id];
107
108 // Fill nv_subtree_fromRow for constraints
109
2/4
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 132 times.
✗ Branch 5 not taken.
132 const Eigen::DenseIndex nv1 = joint1.idx_v() + joint1.nv();
110
2/4
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 132 times.
✗ Branch 5 not taken.
132 const Eigen::DenseIndex nv2 = joint2.idx_v() + joint2.nv();
111 132 const Eigen::DenseIndex nv = std::max(nv1, nv2);
112
2/2
✓ Branch 1 taken 633 times.
✓ Branch 2 taken 132 times.
765 for (Eigen::DenseIndex k = 0; k < cmodel.size(); ++k, row_id++)
113 {
114
1/2
✓ Branch 1 taken 633 times.
✗ Branch 2 not taken.
633 nv_subtree_fromRow[row_id] = nv + (num_total_constraints - row_id);
115 }
116 }
117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 assert(row_id == num_total_constraints);
118
119 // Fill the sparsity pattern for each Row of the Cholesky decomposition (matrix U)
120 /*
121 static const Slice default_slice_value(1,1);
122 static const SliceVector default_slice_vector(1,default_slice_value);
123
124 rowise_sparsity_pattern.clear();
125 rowise_sparsity_pattern.resize((size_t)num_total_constraints,default_slice_vector);
126 row_id = 0; size_t ee_id = 0;
127 for(typename RigidConstraintModelVector::const_iterator it = contact_models.begin();
128 it != contact_models.end();
129 ++it, ++ee_id)
130 {
131 const RigidConstraintModel & cmodel = *it;
132 const BooleanVector & joint1_indexes_ee = cmodel.colwise_joint1_sparsity;
133 const Eigen::DenseIndex contact_dim = cmodel.size();
134
135 for(Eigen::DenseIndex k = 0; k < contact_dim; ++k)
136 {
137 SliceVector & slice_vector = rowise_sparsity_pattern[(size_t)row_id];
138 slice_vector.clear();
139 slice_vector.push_back(Slice(row_id,num_total_constraints-row_id));
140
141 bool previous_index_was_true = true;
142 for(Eigen::DenseIndex joint1_indexes_ee_id = num_total_constraints;
143 joint1_indexes_ee_id < total_dim;
144 ++joint1_indexes_ee_id)
145 {
146 if(joint1_indexes_ee[joint1_indexes_ee_id])
147 {
148 if(previous_index_was_true) // no discontinuity
149 slice_vector.back().size++;
150 else // discontinuity; need to create a new slice
151 {
152 const Slice new_slice(joint1_indexes_ee_id,1);
153 slice_vector.push_back(new_slice);
154 }
155 }
156
157 previous_index_was_true = joint1_indexes_ee[joint1_indexes_ee_id];
158 }
159
160 row_id++;
161 }
162 }
163 */
164
165 // Allocate memory
166 84 D.resize(total_dim);
167 84 Dinv.resize(total_dim);
168 84 U.resize(total_dim, total_dim);
169 84 U.setIdentity();
170 84 DUt.resize(total_dim);
171 84 }
172
173 template<typename Scalar, int Options>
174 template<
175 typename S1,
176 int O1,
177 template<typename, int> class JointCollectionTpl,
178 class ConstraintModelAllocator,
179 class ConstraintDataAllocator,
180 typename VectorLike>
181 1985 void ContactCholeskyDecompositionTpl<Scalar, Options>::compute(
182 const ModelTpl<S1, O1, JointCollectionTpl> & model,
183 DataTpl<S1, O1, JointCollectionTpl> & data,
184 const std::vector<RigidConstraintModelTpl<S1, O1>, ConstraintModelAllocator> & contact_models,
185 std::vector<RigidConstraintDataTpl<S1, O1>, ConstraintDataAllocator> & contact_datas,
186 const Eigen::MatrixBase<VectorLike> & mus)
187 {
188 typedef RigidConstraintModelTpl<S1, O1> RigidConstraintModel;
189 typedef RigidConstraintDataTpl<S1, O1> RigidConstraintData;
190
191
1/2
✓ Branch 1 taken 1985 times.
✗ Branch 2 not taken.
1985 assert(model.check(data) && "data is not consistent with model.");
192
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1985 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
1985 PINOCCHIO_CHECK_INPUT_ARGUMENT(
193 (Eigen::DenseIndex)contact_models.size() == num_contacts,
194 "The number of contacts inside contact_models and the one during allocation do not match.\n"
195 "Please call first ContactCholeskyDecompositionTpl::allocate method.");
196
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1985 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
1985 PINOCCHIO_CHECK_INPUT_ARGUMENT(
197 (Eigen::DenseIndex)contact_datas.size() == num_contacts,
198 "The number of contacts inside contact_datas and the one during allocation do not match.\n"
199 "Please call first ContactCholeskyDecompositionTpl::allocate method.");
200 PINOCCHIO_UNUSED_VARIABLE(model);
201
202 1985 const Eigen::DenseIndex total_dim = size();
203 1985 const Eigen::DenseIndex total_constraints_dim = total_dim - nv;
204
205 typedef DataTpl<Scalar, Options, JointCollectionTpl> Data;
206 1985 const typename Data::MatrixXs & M = data.M;
207
208 1985 const size_t num_ee = contact_models.size();
209
210 // Update frame placements if needed
211
2/2
✓ Branch 0 taken 3149 times.
✓ Branch 1 taken 1985 times.
5134 for (size_t ee_id = 0; ee_id < num_ee; ++ee_id)
212 {
213 3149 const RigidConstraintModel & cmodel = contact_models[ee_id];
214 3149 RigidConstraintData & cdata = contact_datas[ee_id];
215
216 3149 cmodel.calc(model, data, cdata);
217 }
218
219
2/4
✓ Branch 2 taken 1985 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1985 times.
✗ Branch 6 not taken.
1985 D.tail(model.nv) = M.diagonal();
220
3/6
✓ Branch 1 taken 1985 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1985 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1985 times.
✗ Branch 8 not taken.
1985 U.bottomRightCorner(model.nv, model.nv).template triangularView<Eigen::StrictlyUpper>() =
221 1985 M.template triangularView<Eigen::StrictlyUpper>();
222
223 // Constraint filling
224 1985 Eigen::DenseIndex current_row = 0;
225
1/2
✓ Branch 2 taken 1985 times.
✗ Branch 3 not taken.
1985 U.topRightCorner(total_constraints_dim, model.nv).setZero();
226
2/2
✓ Branch 0 taken 3149 times.
✓ Branch 1 taken 1985 times.
5134 for (size_t ee_id = 0; ee_id < num_ee; ++ee_id)
227 {
228 3149 const RigidConstraintModel & cmodel = contact_models[ee_id];
229 3149 RigidConstraintData & cdata = contact_datas[ee_id];
230
231 3149 const Eigen::DenseIndex constraint_dim = cmodel.size();
232
1/2
✓ Branch 1 taken 3149 times.
✗ Branch 2 not taken.
3149 cmodel.jacobian(
233 3149 model, data, cdata, U.block(current_row, total_constraints_dim, cmodel.size(), model.nv));
234 3149 current_row += constraint_dim;
235 }
236
237 // Cholesky
238
2/2
✓ Branch 0 taken 52912 times.
✓ Branch 1 taken 1985 times.
54897 for (Eigen::DenseIndex j = nv - 1; j >= 0; --j)
239 {
240 // Classic Cholesky decomposition related to the mass matrix
241 52912 const Eigen::DenseIndex jj = total_constraints_dim + j; // shifted index
242
1/2
✓ Branch 1 taken 52912 times.
✗ Branch 2 not taken.
52912 const Eigen::DenseIndex NVT = nv_subtree_fromRow[jj] - 1;
243
1/2
✓ Branch 1 taken 52912 times.
✗ Branch 2 not taken.
52912 typename Vector::SegmentReturnType DUt_partial = DUt.head(NVT);
244
245
2/2
✓ Branch 0 taken 46196 times.
✓ Branch 1 taken 6716 times.
52912 if (NVT)
246
3/6
✓ Branch 1 taken 46196 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 46196 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 46196 times.
✗ Branch 8 not taken.
46196 DUt_partial.noalias() =
247
4/8
✓ Branch 1 taken 46196 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 46196 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 46196 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 46196 times.
✗ Branch 11 not taken.
92392 U.row(jj).segment(jj + 1, NVT).transpose().cwiseProduct(D.segment(jj + 1, NVT));
248
249
4/10
✓ Branch 1 taken 52912 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 52912 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 52912 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 52912 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
52912 D[jj] -= U.row(jj).segment(jj + 1, NVT).dot(DUt_partial);
250
3/19
✓ Branch 1 taken 52912 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 52912 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 52912 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
52912 assert(
251 check_expression_if_real<Scalar>(D[jj] != Scalar(0))
252 && "The diagonal element is equal to zero.");
253
2/10
✓ Branch 1 taken 52912 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 52912 times.
✗ 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.
52912 Dinv[jj] = Scalar(1) / D[jj];
254
255
3/4
✓ Branch 1 taken 52912 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 409832 times.
✓ Branch 4 taken 52912 times.
462744 for (Eigen::DenseIndex _ii = parents_fromRow[jj]; _ii >= total_constraints_dim;
256
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
409832 _ii = parents_fromRow[_ii])
257 {
258
4/10
✓ Branch 1 taken 409832 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 409832 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 409832 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 409832 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
409832 U(_ii, jj) -= U.row(_ii).segment(jj + 1, NVT).dot(DUt_partial);
259
3/6
✓ Branch 1 taken 409832 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 409832 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 409832 times.
✗ Branch 8 not taken.
409832 U(_ii, jj) *= Dinv[jj];
260 }
261
262 // Constraint part
263 // Eigen::DenseIndex current_row = total_constraints_dim - 1;
264 // for(size_t ee_id = 0; ee_id < num_ee; ++ee_id)
265 // {
266 // const RigidConstraintModel & cmodel = contact_models[num_ee - 1 - ee_id];
267 //
268 // const Eigen::DenseIndex constraint_dim = cmodel.size();
269 // if(cmodel.colwise_sparsity[j])
270 // {
271 // for(Eigen::DenseIndex k = 0; k < constraint_dim; ++k)
272 // {
273 // U(current_row - k,jj) -= U.row(current_row -
274 // k).segment(jj+1,NVT).dot(DUt_partial); U(current_row - k,jj) *= Dinv[jj];
275 // }
276 // }
277 //
278 // current_row -= constraint_dim;
279 // }
280
2/2
✓ Branch 0 taken 322920 times.
✓ Branch 1 taken 52912 times.
375832 for (Eigen::DenseIndex current_row = total_constraints_dim - 1; current_row >= 0;
281 --current_row)
282 {
283
4/10
✓ Branch 1 taken 322920 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 322920 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 322920 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 322920 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
322920 U(current_row, jj) -= U.row(current_row).segment(jj + 1, NVT).dot(DUt_partial);
284
2/6
✓ Branch 1 taken 322920 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 322920 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
322920 U(current_row, jj) *= Dinv[jj];
285 }
286 }
287
288 1985 updateDamping(mus);
289 1985 }
290
291 template<typename Scalar, int Options>
292 template<typename VectorLike>
293 1987 void ContactCholeskyDecompositionTpl<Scalar, Options>::updateDamping(
294 const Eigen::MatrixBase<VectorLike> & vec)
295 {
296 EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorLike)
297 1987 const Eigen::DenseIndex total_dim = size();
298 1987 const Eigen::DenseIndex total_constraints_dim = total_dim - nv;
299
300 // Upper left triangular part of U
301
2/2
✓ Branch 0 taken 13089 times.
✓ Branch 1 taken 1987 times.
15076 for (Eigen::DenseIndex j = total_constraints_dim - 1; j >= 0; --j)
302 {
303 13089 const Eigen::DenseIndex slice_dim = total_dim - j - 1;
304
1/2
✓ Branch 1 taken 13089 times.
✗ Branch 2 not taken.
13089 typename Vector::SegmentReturnType DUt_partial = DUt.head(slice_dim);
305
3/6
✓ Branch 1 taken 13089 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13089 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13089 times.
✗ Branch 8 not taken.
13089 DUt_partial.noalias() =
306
4/8
✓ Branch 1 taken 13089 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13089 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13089 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 13089 times.
✗ Branch 11 not taken.
13089 U.row(j).segment(j + 1, slice_dim).transpose().cwiseProduct(D.segment(j + 1, slice_dim));
307
308
5/16
✓ Branch 1 taken 13089 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13089 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13089 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 13089 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 13089 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
13089 D[j] = -vec[j] - U.row(j).segment(j + 1, slice_dim).dot(DUt_partial);
309
3/19
✓ Branch 1 taken 13089 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13089 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13089 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
13089 assert(
310 check_expression_if_real<Scalar>(D[j] != Scalar(0))
311 && "The diagonal element is equal to zero.");
312
2/10
✓ Branch 1 taken 13089 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13089 times.
✗ 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.
13089 Dinv[j] = Scalar(1) / D[j];
313
314
2/2
✓ Branch 0 taken 51933 times.
✓ Branch 1 taken 13089 times.
65022 for (Eigen::DenseIndex _i = j - 1; _i >= 0; _i--)
315 {
316
5/16
✓ Branch 1 taken 51933 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 51933 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 51933 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 51933 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 51933 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
51933 U(_i, j) = -U.row(_i).segment(j + 1, slice_dim).dot(DUt_partial) * Dinv[j];
317 }
318 }
319 1987 }
320
321 template<typename Scalar, int Options>
322 2 void ContactCholeskyDecompositionTpl<Scalar, Options>::updateDamping(const Scalar & mu)
323 {
324 // PINOCCHIO_CHECK_INPUT_ARGUMENT(check_expression_if_real<Scalar>(mu >= 0), "mu should be
325 // positive.");
326
327 2 const Eigen::DenseIndex total_dim = size();
328 2 const Eigen::DenseIndex total_constraints_dim = total_dim - nv;
329
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 updateDamping(Vector::Constant(total_constraints_dim, mu));
330 2 }
331
332 template<typename Scalar, int Options>
333 template<typename MatrixLike>
334 3058 void ContactCholeskyDecompositionTpl<Scalar, Options>::solveInPlace(
335 const Eigen::MatrixBase<MatrixLike> & mat) const
336 {
337 3058 MatrixLike & mat_ = PINOCCHIO_EIGEN_CONST_CAST(MatrixLike, mat);
338
339 3058 Uiv(mat_);
340
3/6
✓ Branch 2 taken 3058 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3058 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3058 times.
✗ Branch 9 not taken.
3058 mat_.array().colwise() *= Dinv.array();
341 3058 Utiv(mat_);
342 3058 }
343
344 template<typename Scalar, int Options>
345 template<typename MatrixLike>
346 typename ContactCholeskyDecompositionTpl<Scalar, Options>::Matrix
347 3 ContactCholeskyDecompositionTpl<Scalar, Options>::solve(
348 const Eigen::MatrixBase<MatrixLike> & mat) const
349 {
350 3 Matrix res(mat);
351
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 solveInPlace(res);
352 3 return res;
353 }
354
355 template<typename Scalar, int Options>
356 template<typename S1, int O1, template<typename, int> class JointCollectionTpl>
357 ContactCholeskyDecompositionTpl<Scalar, Options>
358 1 ContactCholeskyDecompositionTpl<Scalar, Options>::getMassMatrixChoeslkyDecomposition(
359 const ModelTpl<S1, O1, JointCollectionTpl> & model) const
360 {
361 typedef ContactCholeskyDecompositionTpl<Scalar, Options> ReturnType;
362 1 ReturnType res(model);
363
364
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 res.D = D.tail(nv);
365
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 res.Dinv = Dinv.tail(nv);
366
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 res.U = U.bottomRightCorner(nv, nv);
367
368 1 return res;
369 }
370
371 namespace details
372 {
373 template<typename MatrixLike, int ColsAtCompileTime>
374 struct UvAlgo
375 {
376 template<typename Scalar, int Options>
377 4 static void run(
378 const ContactCholeskyDecompositionTpl<Scalar, Options> & chol,
379 const Eigen::MatrixBase<MatrixLike> & mat)
380 {
381 4 MatrixLike & mat_ = PINOCCHIO_EIGEN_CONST_CAST(MatrixLike, mat);
382
383
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4 PINOCCHIO_CHECK_INPUT_ARGUMENT(
384 mat.rows() == chol.size(), "The input matrix is of wrong size");
385
386
2/2
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 4 times.
84 for (Eigen::DenseIndex col_id = 0; col_id < mat_.cols(); ++col_id)
387
1/2
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
80 UvAlgo<typename MatrixLike::ColXpr>::run(chol, mat_.col(col_id));
388 4 }
389 };
390
391 template<typename VectorLike>
392 struct UvAlgo<VectorLike, 1>
393 {
394 template<typename Scalar, int Options>
395 84 static void run(
396 const ContactCholeskyDecompositionTpl<Scalar, Options> & chol,
397 const Eigen::MatrixBase<VectorLike> & vec)
398 {
399 EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorLike)
400 84 VectorLike & vec_ = PINOCCHIO_EIGEN_CONST_CAST(VectorLike, vec);
401
402
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
84 PINOCCHIO_CHECK_INPUT_ARGUMENT(
403 vec.size() == chol.size(), "The input vector is of wrong size");
404 84 const Eigen::DenseIndex num_total_constraints = chol.size() - chol.nv;
405
406 // TODO: exploit the Sparsity pattern of the first rows of U
407
2/2
✓ Branch 0 taken 945 times.
✓ Branch 1 taken 84 times.
1029 for (Eigen::DenseIndex k = 0; k < num_total_constraints; ++k)
408 {
409 945 const Eigen::DenseIndex slice_dim = chol.size() - k - 1;
410
4/8
✓ Branch 2 taken 945 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 945 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 945 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 945 times.
✗ Branch 12 not taken.
945 vec_[k] += chol.U.row(k).tail(slice_dim).dot(vec_.tail(slice_dim));
411 }
412
413
2/2
✓ Branch 1 taken 2604 times.
✓ Branch 2 taken 84 times.
2688 for (Eigen::DenseIndex k = num_total_constraints; k <= chol.size() - 2; ++k)
414 2604 vec_[k] += chol.U.row(k)
415
2/4
✓ Branch 1 taken 2604 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2604 times.
✗ Branch 5 not taken.
2604 .segment(k + 1, chol.nv_subtree_fromRow[k] - 1)
416
4/8
✓ Branch 1 taken 2604 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2604 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2604 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2604 times.
✗ Branch 11 not taken.
2604 .dot(vec_.segment(k + 1, chol.nv_subtree_fromRow[k] - 1));
417 84 }
418 };
419 } // namespace details
420
421 template<typename Scalar, int Options>
422 template<typename MatrixLike>
423 8 void ContactCholeskyDecompositionTpl<Scalar, Options>::Uv(
424 const Eigen::MatrixBase<MatrixLike> & mat) const
425 {
426 8 details::UvAlgo<MatrixLike>::run(*this, mat.const_cast_derived());
427 8 }
428
429 namespace details
430 {
431 template<typename MatrixLike, int ColsAtCompileTime>
432 struct UtvAlgo
433 {
434 template<typename Scalar, int Options>
435 4 static void run(
436 const ContactCholeskyDecompositionTpl<Scalar, Options> & chol,
437 const Eigen::MatrixBase<MatrixLike> & mat)
438 {
439 4 MatrixLike & mat_ = mat.const_cast_derived();
440
441
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4 PINOCCHIO_CHECK_INPUT_ARGUMENT(
442 mat.rows() == chol.size(), "The input matrix is of wrong size");
443
444
2/2
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 4 times.
84 for (Eigen::DenseIndex col_id = 0; col_id < mat_.cols(); ++col_id)
445
1/2
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
80 UtvAlgo<typename MatrixLike::ColXpr>::run(chol, mat_.col(col_id));
446 4 }
447 };
448
449 template<typename VectorLike>
450 struct UtvAlgo<VectorLike, 1>
451 {
452 template<typename Scalar, int Options>
453 84 static void run(
454 const ContactCholeskyDecompositionTpl<Scalar, Options> & chol,
455 const Eigen::MatrixBase<VectorLike> & vec)
456 {
457 EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorLike)
458 84 VectorLike & vec_ = vec.const_cast_derived();
459
460
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
84 PINOCCHIO_CHECK_INPUT_ARGUMENT(
461 vec.size() == chol.size(), "The input vector is of wrong size");
462 84 const Eigen::DenseIndex num_total_constraints = chol.constraintDim();
463
464
2/2
✓ Branch 1 taken 2604 times.
✓ Branch 2 taken 84 times.
2688 for (Eigen::DenseIndex k = chol.size() - 2; k >= num_total_constraints; --k)
465
4/8
✓ Branch 1 taken 2604 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2604 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2604 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2604 times.
✗ Branch 11 not taken.
2604 vec_.segment(k + 1, chol.nv_subtree_fromRow[k] - 1) +=
466
3/6
✓ Branch 3 taken 2604 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2604 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2604 times.
✗ Branch 10 not taken.
5208 chol.U.row(k).segment(k + 1, chol.nv_subtree_fromRow[k] - 1).transpose() * vec_[k];
467
468 // TODO: exploit the Sparsity pattern of the first rows of U
469
2/2
✓ Branch 0 taken 945 times.
✓ Branch 1 taken 84 times.
1029 for (Eigen::DenseIndex k = num_total_constraints - 1; k >= 0; --k)
470 {
471 945 const Eigen::DenseIndex slice_dim = chol.size() - k - 1;
472
5/10
✓ Branch 3 taken 945 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 945 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 945 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 945 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 945 times.
✗ Branch 16 not taken.
945 vec_.tail(slice_dim) += chol.U.row(k).tail(slice_dim).transpose() * vec_[k];
473 }
474 84 }
475 };
476 } // namespace details
477
478 template<typename Scalar, int Options>
479 template<typename MatrixLike>
480 8 void ContactCholeskyDecompositionTpl<Scalar, Options>::Utv(
481 const Eigen::MatrixBase<MatrixLike> & mat) const
482 {
483 8 details::UtvAlgo<MatrixLike>::run(*this, mat.const_cast_derived());
484 8 }
485
486 namespace details
487 {
488 template<typename MatrixLike, int ColsAtCompileTime>
489 struct UivAlgo
490 {
491 template<typename Scalar, int Options>
492 11 static void run(
493 const ContactCholeskyDecompositionTpl<Scalar, Options> & chol,
494 const Eigen::MatrixBase<MatrixLike> & mat)
495 {
496 11 MatrixLike & mat_ = mat.const_cast_derived();
497
498
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
11 PINOCCHIO_CHECK_INPUT_ARGUMENT(
499 mat.rows() == chol.size(), "The input matrix is of wrong size");
500
501
2/2
✓ Branch 1 taken 256 times.
✓ Branch 2 taken 11 times.
267 for (Eigen::DenseIndex col_id = 0; col_id < mat_.cols(); ++col_id)
502
1/2
✓ Branch 2 taken 256 times.
✗ Branch 3 not taken.
256 UivAlgo<typename MatrixLike::ColXpr>::run(chol, mat_.col(col_id));
503 11 }
504 };
505
506 template<typename VectorLike>
507 struct UivAlgo<VectorLike, 1>
508 {
509 template<typename Scalar, int Options>
510 3312 static void run(
511 const ContactCholeskyDecompositionTpl<Scalar, Options> & chol,
512 const Eigen::MatrixBase<VectorLike> & vec)
513 {
514 EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorLike)
515 3312 VectorLike & vec_ = vec.const_cast_derived();
516
517
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 3312 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
3312 PINOCCHIO_CHECK_INPUT_ARGUMENT(
518 vec.size() == chol.size(), "The input vector is of wrong size");
519
520 3312 const Eigen::DenseIndex num_total_constraints = chol.size() - chol.nv;
521
2/2
✓ Branch 1 taken 92090 times.
✓ Branch 2 taken 3312 times.
95402 for (Eigen::DenseIndex k = chol.size() - 2; k >= num_total_constraints; --k)
522
0/6
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
92090 vec_[k] -= chol.U.row(k)
523
2/4
✓ Branch 1 taken 92090 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 92090 times.
✗ Branch 5 not taken.
92090 .segment(k + 1, chol.nv_subtree_fromRow[k] - 1)
524
4/8
✓ Branch 1 taken 92090 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 92090 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 92090 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 92090 times.
✗ Branch 11 not taken.
92090 .dot(vec_.segment(k + 1, chol.nv_subtree_fromRow[k] - 1));
525
526 // TODO: exploit the Sparsity pattern of the first rows of U
527
2/2
✓ Branch 0 taken 19923 times.
✓ Branch 1 taken 3312 times.
23235 for (Eigen::DenseIndex k = num_total_constraints - 1; k >= 0; --k)
528 {
529 19923 const Eigen::DenseIndex slice_dim = chol.size() - k - 1;
530
4/10
✓ Branch 2 taken 19923 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 19923 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 19923 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 19923 times.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
19923 vec_[k] -= chol.U.row(k).tail(slice_dim).dot(vec_.tail(slice_dim));
531 }
532 3312 }
533 };
534 } // namespace details
535
536 template<typename Scalar, int Options>
537 template<typename MatrixLike>
538 3067 void ContactCholeskyDecompositionTpl<Scalar, Options>::Uiv(
539 const Eigen::MatrixBase<MatrixLike> & mat) const
540 {
541 3067 details::UivAlgo<MatrixLike>::run(*this, mat.const_cast_derived());
542 3067 }
543
544 namespace details
545 {
546 template<typename MatrixLike, int ColsAtCompileTime>
547 struct UtivAlgo
548 {
549 template<typename Scalar, int Options>
550 11 static void run(
551 const ContactCholeskyDecompositionTpl<Scalar, Options> & chol,
552 const Eigen::MatrixBase<MatrixLike> & mat)
553 {
554 11 MatrixLike & mat_ = mat.const_cast_derived();
555
556
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
11 PINOCCHIO_CHECK_INPUT_ARGUMENT(
557 mat.rows() == chol.size(), "The input matrix is of wrong size");
558
559
2/2
✓ Branch 1 taken 256 times.
✓ Branch 2 taken 11 times.
267 for (Eigen::DenseIndex col_id = 0; col_id < mat_.cols(); ++col_id)
560
1/2
✓ Branch 2 taken 256 times.
✗ Branch 3 not taken.
256 UtivAlgo<typename MatrixLike::ColXpr>::run(chol, mat_.col(col_id));
561 11 }
562 };
563
564 template<typename VectorLike>
565 struct UtivAlgo<VectorLike, 1>
566 {
567 template<typename Scalar, int Options>
568 3312 static void run(
569 const ContactCholeskyDecompositionTpl<Scalar, Options> & chol,
570 const Eigen::MatrixBase<VectorLike> & vec)
571 {
572 EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorLike)
573 3312 VectorLike & vec_ = vec.const_cast_derived();
574
575
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 3312 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
3312 PINOCCHIO_CHECK_INPUT_ARGUMENT(
576 vec.size() == chol.size(), "The input vector is of wrong size");
577 3312 const Eigen::DenseIndex num_total_constraints = chol.constraintDim();
578
579 // TODO: exploit the Sparsity pattern of the first rows of U
580
2/2
✓ Branch 0 taken 19923 times.
✓ Branch 1 taken 3312 times.
23235 for (Eigen::DenseIndex k = 0; k < num_total_constraints; ++k)
581 {
582 19923 const Eigen::DenseIndex slice_dim = chol.size() - k - 1;
583
5/10
✓ Branch 3 taken 19923 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 19923 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 19923 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 19923 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 19923 times.
✗ Branch 16 not taken.
19923 vec_.tail(slice_dim) -= chol.U.row(k).tail(slice_dim).transpose() * vec_[k];
584 }
585
586
2/2
✓ Branch 1 taken 92090 times.
✓ Branch 2 taken 3312 times.
95402 for (Eigen::DenseIndex k = num_total_constraints; k <= chol.size() - 2; ++k)
587
4/8
✓ Branch 1 taken 92090 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 92090 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 92090 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 92090 times.
✗ Branch 11 not taken.
92090 vec_.segment(k + 1, chol.nv_subtree_fromRow[k] - 1) -=
588
3/6
✓ Branch 3 taken 92090 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 92090 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 92090 times.
✗ Branch 10 not taken.
184180 chol.U.row(k).segment(k + 1, chol.nv_subtree_fromRow[k] - 1).transpose() * vec_[k];
589 3312 }
590 };
591 } // namespace details
592
593 template<typename Scalar, int Options>
594 template<typename MatrixLike>
595 3067 void ContactCholeskyDecompositionTpl<Scalar, Options>::Utiv(
596 const Eigen::MatrixBase<MatrixLike> & mat) const
597 {
598 3067 details::UtivAlgo<MatrixLike>::run(*this, PINOCCHIO_EIGEN_CONST_CAST(MatrixLike, mat));
599 3067 }
600
601 template<typename Scalar, int Options>
602 typename ContactCholeskyDecompositionTpl<Scalar, Options>::Matrix
603 53 ContactCholeskyDecompositionTpl<Scalar, Options>::matrix() const
604 {
605
2/4
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 53 times.
✗ Branch 6 not taken.
53 Matrix res(size(), size());
606
1/2
✓ Branch 1 taken 53 times.
✗ Branch 2 not taken.
53 matrix(res);
607 53 return res;
608 }
609
610 template<typename Scalar, int Options>
611 template<typename MatrixType>
612 57 void ContactCholeskyDecompositionTpl<Scalar, Options>::matrix(
613 const Eigen::MatrixBase<MatrixType> & res) const
614 {
615 57 MatrixType & res_ = PINOCCHIO_EIGEN_CONST_CAST(MatrixType, res);
616
5/10
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 57 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 57 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 57 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 57 times.
✗ Branch 15 not taken.
57 res_.noalias() = U * D.asDiagonal() * U.transpose();
617 57 }
618
619 template<typename Scalar, int Options>
620 typename ContactCholeskyDecompositionTpl<Scalar, Options>::Matrix
621 ContactCholeskyDecompositionTpl<Scalar, Options>::inverse() const
622 {
623 Matrix res(size(), size());
624 inverse(res);
625 return res;
626 }
627
628 template<typename Scalar, int Options>
629 template<typename S1, int O1>
630 3 bool ContactCholeskyDecompositionTpl<Scalar, Options>::operator==(
631 const ContactCholeskyDecompositionTpl<S1, O1> & other) const
632 {
633 3 bool is_same = true;
634
635
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3 if (nv != other.nv || num_contacts != other.num_contacts)
636 1 return false;
637
638 2 if (
639
2/4
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
4 D.size() != other.D.size() || Dinv.size() != other.Dinv.size() || U.rows() != other.U.rows()
640
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
4 || U.cols() != other.U.cols())
641 return false;
642
643 2 is_same &= (D == other.D);
644 2 is_same &= (Dinv == other.Dinv);
645 2 is_same &= (U == other.U);
646
647 2 is_same &= (parents_fromRow == other.parents_fromRow);
648 2 is_same &= (nv_subtree_fromRow == other.nv_subtree_fromRow);
649 2 is_same &= (last_child == other.last_child);
650 // is_same &= (rowise_sparsity_pattern == other.rowise_sparsity_pattern);
651
652 2 return is_same;
653 }
654
655 template<typename Scalar, int Options>
656 template<typename S1, int O1>
657 1 bool ContactCholeskyDecompositionTpl<Scalar, Options>::operator!=(
658 const ContactCholeskyDecompositionTpl<S1, O1> & other) const
659 {
660 1 return !(*this == other);
661 }
662
663 namespace details
664 {
665
666 template<typename Scalar, int Options, typename VectorLike>
667 598 EIGEN_DONT_INLINE VectorLike & inverseAlgo(
668 const ContactCholeskyDecompositionTpl<Scalar, Options> & chol,
669 const Eigen::DenseIndex col,
670 const Eigen::MatrixBase<VectorLike> & vec)
671 {
672 EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorLike);
673
674 typedef ContactCholeskyDecompositionTpl<Scalar, Options> ContactCholeskyDecomposition;
675 typedef typename ContactCholeskyDecomposition::RowMatrix RowMatrix;
676
677
1/2
✓ Branch 1 taken 299 times.
✗ Branch 2 not taken.
598 const Eigen::DenseIndex & chol_dim = chol.size();
678
2/6
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 299 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
598 PINOCCHIO_CHECK_INPUT_ARGUMENT(col < chol_dim && col >= 0);
679
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 299 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
598 PINOCCHIO_CHECK_INPUT_ARGUMENT(vec.size() == chol_dim);
680
681 598 const typename ContactCholeskyDecomposition::IndexVector & nvt = chol.nv_subtree_fromRow;
682 598 VectorLike & vec_ = PINOCCHIO_EIGEN_CONST_CAST(VectorLike, vec);
683
684 598 const Eigen::DenseIndex last_col =
685 598 std::min(col - 1, chol_dim - 2); // You can start from nv-2 (no child in nv-1)
686
1/2
✓ Branch 1 taken 299 times.
✗ Branch 2 not taken.
598 vec_[col] = Scalar(1);
687
2/4
✓ Branch 1 taken 299 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 299 times.
✗ Branch 5 not taken.
598 vec_.tail(chol_dim - col - 1).setZero();
688
689 // TODO: exploit the sparsity pattern of the first rows of U
690
2/2
✓ Branch 0 taken 6397 times.
✓ Branch 1 taken 299 times.
13392 for (Eigen::DenseIndex k = last_col; k >= 0; --k)
691 {
692
1/2
✓ Branch 1 taken 6397 times.
✗ Branch 2 not taken.
12794 const Eigen::DenseIndex nvt_max = std::min(col - k, nvt[k] - 1);
693
1/2
✓ Branch 1 taken 6397 times.
✗ Branch 2 not taken.
12794 const typename RowMatrix::ConstRowXpr U_row = chol.U.row(k);
694
4/8
✓ Branch 1 taken 6397 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6397 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6397 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 6397 times.
✗ Branch 11 not taken.
12794 vec_[k] = -U_row.segment(k + 1, nvt_max).dot(vec_.segment(k + 1, nvt_max));
695 // if(k >= chol_constraint_dim)
696 // {
697 // vec_[k] = -U_row.segment(k+1,nvt_max).dot(vec_.segment(k+1,nvt_max));
698 // }
699 // else
700 // {
701 // typedef typename ContactCholeskyDecomposition::SliceVector SliceVector;
702 // typedef typename ContactCholeskyDecomposition::Slice Slice;
703 // const SliceVector & slice_vector = chol.rowise_sparsity_pattern[(size_t)k];
704 //
705 // const Slice & slice_0 = slice_vector[0];
706 // assert(slice_0.first_index == k);
707 // Eigen::DenseIndex last_index1 = slice_0.first_index + slice_0.size;
708 // const Eigen::DenseIndex last_index2 = k + nvt_max;
709 // Eigen::DenseIndex slice_dim = std::min(last_index1,last_index2) - k;
710 // vec_[k] =
711 // -U_row.segment(slice_0.first_index+1,slice_dim-1).dot(vec_.segment(slice_0.first_index+1,slice_dim-1));
712 //
713 // typename SliceVector::const_iterator slice_it = slice_vector.begin()++;
714 // for(;slice_it != slice_vector.end(); ++slice_it)
715 // {
716 // const Slice & slice = *slice_it;
717 // last_index1 = slice.first_index + slice.size;
718 // slice_dim = std::min(last_index1,last_index2+1) - slice.first_index;
719 // if(slice_dim <= 0) break;
720 //
721 // vec_[k] -=
722 // U_row.segment(slice.first_index,slice_dim).dot(vec_.segment(slice.first_index,slice_dim));
723 // }
724 // }
725 }
726
727
5/10
✓ Branch 1 taken 299 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 299 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 299 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 299 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 299 times.
✗ Branch 14 not taken.
598 vec_.head(col + 1).array() *= chol.Dinv.head(col + 1).array();
728
729
2/2
✓ Branch 0 taken 6696 times.
✓ Branch 1 taken 299 times.
13990 for (Eigen::DenseIndex k = 0; k < col + 1; ++k) // You can stop one step before nv.
730 {
731
1/2
✓ Branch 1 taken 6696 times.
✗ Branch 2 not taken.
13392 const Eigen::DenseIndex nvt_max = nvt[k] - 1;
732
7/14
✓ Branch 1 taken 6696 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6696 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6696 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 6696 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 6696 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 6696 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 6696 times.
✗ Branch 20 not taken.
13392 vec_.segment(k + 1, nvt_max) -= chol.U.row(k).segment(k + 1, nvt_max).transpose() * vec_[k];
733 }
734
735 598 return vec_;
736 }
737 } // namespace details
738
739 template<typename Scalar, int Options>
740 template<typename MatrixType>
741 7 void ContactCholeskyDecompositionTpl<Scalar, Options>::inverse(
742 const Eigen::MatrixBase<MatrixType> & res) const
743 {
744
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7 PINOCCHIO_CHECK_INPUT_ARGUMENT(res.rows() == size());
745
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7 PINOCCHIO_CHECK_INPUT_ARGUMENT(res.cols() == size());
746
747 7 MatrixType & res_ = PINOCCHIO_EIGEN_CONST_CAST(MatrixType, res);
748
749
2/2
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 7 times.
306 for (Eigen::DenseIndex col_id = 0; col_id < size(); ++col_id)
750
1/2
✓ Branch 2 taken 299 times.
✗ Branch 3 not taken.
299 details::inverseAlgo(*this, col_id, res_.col(col_id));
751
752
2/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
7 res_.template triangularView<Eigen::StrictlyLower>() =
753
1/2
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 res_.transpose().template triangularView<Eigen::StrictlyLower>();
754 7 }
755
756 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
757 } // namespace pinocchio
758
759 #endif // ifndef __pinocchio_algorithm_contact_cholesky_hxx__
760