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