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 |