GCC Code Coverage Report


Directory: ./
File: include/pinocchio/algorithm/rnea-second-order-derivatives.hxx
Date: 2024-08-27 18:20:05
Exec Total Coverage
Lines: 0 212 0.0%
Branches: 0 1092 0.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2017-2020 CNRS INRIA
3
4 #ifndef __pinocchio_algorithm_rnea_second_order_derivatives_hxx__
5 #define __pinocchio_algorithm_rnea_second_order_derivatives_hxx__
6
7 #include "pinocchio/algorithm/check.hpp"
8 #include "pinocchio/multibody/visitor.hpp"
9
10 namespace pinocchio
11 {
12
13 template<
14 typename Scalar,
15 int Options,
16 template<typename, int>
17 class JointCollectionTpl,
18 typename ConfigVectorType,
19 typename TangentVectorType1,
20 typename TangentVectorType2>
21 struct ComputeRNEASecondOrderDerivativesForwardStep
22 : public fusion::JointUnaryVisitorBase<ComputeRNEASecondOrderDerivativesForwardStep<
23 Scalar,
24 Options,
25 JointCollectionTpl,
26 ConfigVectorType,
27 TangentVectorType1,
28 TangentVectorType2>>
29 {
30 typedef ModelTpl<Scalar, Options, JointCollectionTpl> Model;
31 typedef DataTpl<Scalar, Options, JointCollectionTpl> Data;
32
33 typedef boost::fusion::vector<
34 const Model &,
35 Data &,
36 const ConfigVectorType &,
37 const TangentVectorType1 &,
38 const TangentVectorType2 &>
39 ArgsType;
40
41 template<typename JointModel>
42 static void algo(
43 const JointModelBase<JointModel> & jmodel,
44 JointDataBase<typename JointModel::JointDataDerived> & jdata,
45 const Model & model,
46 Data & data,
47 const Eigen::MatrixBase<ConfigVectorType> & q,
48 const Eigen::MatrixBase<TangentVectorType1> & v,
49 const Eigen::MatrixBase<TangentVectorType2> & a)
50 {
51 typedef typename Model::JointIndex JointIndex;
52 typedef typename Data::Motion Motion;
53 typedef typename Data::Inertia Inertia;
54
55 const JointIndex i = jmodel.id();
56 const JointIndex parent = model.parents[i];
57 Motion & ov = data.ov[i];
58 Motion & oa = data.oa[i];
59 Motion & vJ = data.v[i];
60
61 jmodel.calc(jdata.derived(), q.derived(), v.derived());
62
63 data.liMi[i] = model.jointPlacements[i] * jdata.M();
64 if (parent > 0)
65 {
66 data.oMi[i] = data.oMi[parent] * data.liMi[i];
67 ov = data.ov[parent];
68 oa = data.oa[parent];
69 }
70 else
71 {
72 data.oMi[i] = data.liMi[i];
73 ov.setZero();
74 oa = -model.gravity;
75 }
76
77 typedef
78 typename SizeDepType<JointModel::NV>::template ColsReturn<typename Data::Matrix6x>::Type
79 ColsBlock;
80 ColsBlock J_cols =
81 jmodel.jointCols(data.J); // data.J has all the phi (in world frame) stacked in columns
82 ColsBlock psid_cols = jmodel.jointCols(data.psid); // psid_cols is the psi_dot in world frame
83 ColsBlock psidd_cols =
84 jmodel.jointCols(data.psidd); // psidd_cols is the psi_dotdot in world frame
85 ColsBlock dJ_cols = jmodel.jointCols(data.dJ); // This here is phi_dot in world frame
86
87 J_cols.noalias() =
88 data.oMi[i].act(jdata.S()); // J_cols is just the phi in world frame for a joint
89 vJ = data.oMi[i].act(jdata.v());
90 motionSet::motionAction(ov, J_cols, psid_cols); // This ov here is v(p(i)), psi_dot calcs
91 motionSet::motionAction(oa, J_cols, psidd_cols); // This oa here is a(p(i)) , psi_dotdot calcs
92 motionSet::motionAction<ADDTO>(
93 ov, psid_cols,
94 psidd_cols); // This ov here is v(p(i)) , psi_dotdot calcs
95 ov += vJ;
96 oa += (ov ^ vJ) + data.oMi[i].act(jdata.S() * jmodel.jointVelocitySelector(a) + jdata.c());
97 motionSet::motionAction(ov, J_cols, dJ_cols); // This here is phi_dot, here ov used is v(p(i))
98 // + vJ Composite rigid body inertia
99 Inertia & oY = data.oYcrb[i];
100
101 oY = data.oMi[i].act(model.inertias[i]);
102 data.oh[i] = oY * ov;
103
104 data.of[i] = oY * oa + oY.vxiv(ov); // f_i in world frame
105
106 data.doYcrb[i] = oY.variation(ov);
107 addForceCrossMatrix(data.oh[i], data.doYcrb[i]); // BC{i}
108 }
109 template<typename ForceDerived, typename M6>
110 static void
111 addForceCrossMatrix(const ForceDense<ForceDerived> & f, const Eigen::MatrixBase<M6> & mout)
112 {
113 M6 & mout_ = PINOCCHIO_EIGEN_CONST_CAST(M6, mout);
114 addSkew(-f.linear(), mout_.template block<3, 3>(ForceDerived::LINEAR, ForceDerived::ANGULAR));
115 addSkew(-f.linear(), mout_.template block<3, 3>(ForceDerived::ANGULAR, ForceDerived::LINEAR));
116 addSkew(
117 -f.angular(), mout_.template block<3, 3>(ForceDerived::ANGULAR, ForceDerived::ANGULAR));
118 }
119 };
120
121 template<
122 typename Scalar,
123 int Options,
124 template<typename, int>
125 class JointCollectionTpl,
126 typename Tensor1,
127 typename Tensor2,
128 typename Tensor3,
129 typename Tensor4>
130 struct ComputeRNEASecondOrderDerivativesBackwardStep
131 : public fusion::JointUnaryVisitorBase<ComputeRNEASecondOrderDerivativesBackwardStep<
132 Scalar,
133 Options,
134 JointCollectionTpl,
135 Tensor1,
136 Tensor2,
137 Tensor3,
138 Tensor4>>
139 {
140 typedef ModelTpl<Scalar, Options, JointCollectionTpl> Model;
141 typedef DataTpl<Scalar, Options, JointCollectionTpl> Data;
142
143 typedef boost::fusion::vector<
144 const Model &,
145 Data &,
146 const Tensor1 &,
147 const Tensor2 &,
148 const Tensor3 &,
149 const Tensor4 &>
150 ArgsType;
151
152 template<typename JointModel>
153 static void algo(
154 const JointModelBase<JointModel> & jmodel,
155 const Model & model,
156 Data & data,
157 const Tensor1 & d2tau_dqdq,
158 const Tensor2 & d2tau_dvdv,
159 const Tensor3 & dtau_dqdv,
160 const Tensor3 & dtau_dadq)
161 {
162 typedef typename Data::Motion Motion;
163 typedef typename Data::Force Force;
164 typedef typename Data::Inertia Inertia;
165 typedef typename Model::JointIndex JointIndex;
166 typedef typename Motion::ActionMatrixType ActionMatrixType;
167 typedef typename Data::Matrix6 Matrix6;
168 typedef typename Data::Vector6r Vector6r;
169 typedef typename Data::Vector6c Vector6c;
170
171 const JointIndex i = jmodel.id();
172 const JointIndex parent = model.parents[i];
173
174 const Inertia & oYcrb = data.oYcrb[i]; // IC{i}
175 const Matrix6 & oBcrb = data.doYcrb[i]; // BC{i}
176
177 Tensor1 & d2tau_dqdq_ = const_cast<Tensor1 &>(d2tau_dqdq);
178 Tensor2 & d2tau_dvdv_ = const_cast<Tensor2 &>(d2tau_dvdv);
179 Tensor3 & dtau_dqdv_ = const_cast<Tensor3 &>(dtau_dqdv);
180 Tensor4 & dtau_dadq_ = const_cast<Tensor4 &>(dtau_dadq);
181
182 Vector6r u1;
183 Vector6r u2;
184 Vector6c u3;
185 Vector6c u4;
186 Vector6c u5;
187 Vector6c u6;
188 Vector6c u7;
189 Vector6c u8;
190 Vector6c u9;
191 Vector6c u10;
192 Vector6r u11;
193 Vector6r u12;
194 Vector6c u13;
195
196 Matrix6 Bicphii;
197 Matrix6 oBicpsidot;
198
199 Scalar p1, p2, p3, p4, p5, p6;
200
201 Matrix6 r0, r1, r2, r3, r4, r5, r6, r7;
202
203 for (int p = 0; p < model.nvs[i]; p++)
204 {
205 const Eigen::DenseIndex ip = model.idx_vs[i] + p;
206
207 const MotionRef<typename Data::Matrix6x::ColXpr> S_i = data.J.col(ip); // S{i}(:,p)
208 const ActionMatrixType S_iA = S_i.toActionMatrix(); //(S{i}(:,p) )x matrix
209 const MotionRef<typename Data::Matrix6x::ColXpr> psid_dm =
210 data.psid.col(ip); // psi_dot for p DOF
211 const MotionRef<typename Data::Matrix6x::ColXpr> psidd_dm =
212 data.psidd.col(ip); // psi_ddot for p DOF
213 const MotionRef<typename Data::Matrix6x::ColXpr> phid_dm =
214 data.dJ.col(ip); // phi_dot for p DOF
215
216 r1 = Bicphii = oYcrb.variation(S_i); // S{i}(p)x*IC{i} - IC{i} S{i}(p)x
217 oBicpsidot = oYcrb.variation(psid_dm); // new Bicpsidot in world frame
218
219 Force f_tmp = oYcrb * S_i; // IC{i}S{i}(:,p)
220 ForceCrossMatrix(f_tmp, r0); // cmf_bar(IC{i}S{i}(:,p))
221 Bicphii += r0;
222
223 f_tmp = oYcrb * psid_dm; // IC{i}S{i}(:,p)
224 addForceCrossMatrix(f_tmp, oBicpsidot); // cmf_bar(IC{i}S{i}(:,p))
225
226 r2.noalias() = 2 * r0 - Bicphii;
227
228 r3.noalias() = oBicpsidot - S_iA.transpose() * oBcrb
229 - oBcrb * S_iA; // Bicpsidot + S{i}(p)x*BC{i}- BC {i}S{i}(p)x
230
231 // r4
232 f_tmp.toVector().noalias() = oBcrb.transpose() * S_i.toVector();
233 ForceCrossMatrix(f_tmp, r4); // cmf_bar(BC{i}.'S{i}(:,p))
234 // r5
235 f_tmp.toVector().noalias() = oBcrb * psid_dm.toVector();
236 f_tmp += S_i.cross(data.of[i]);
237 motionSet::inertiaAction<ADDTO>(oYcrb, psidd_dm.toVector(), f_tmp.toVector());
238 ForceCrossMatrix(
239 f_tmp,
240 r5); // cmf_bar(BC{i}psi_dot{i}(:,p)+IC{i}psi_ddot{i}(:,p)+S{i}(:,p)x*f{i})
241
242 // S{i}(:,p)x* IC{i} + r0
243 r6 = r0 + oYcrb.vxi(S_i);
244
245 // r7
246 f_tmp.toVector().noalias() = oBcrb * S_i.toVector();
247 f_tmp += oYcrb * (psid_dm + phid_dm);
248 ForceCrossMatrix(f_tmp, r7); // cmf_bar(BC{i}S{i}(:,p) +
249 // IC{i}(psi_dot{i}(:,p)+phi_dot{i}(:,p)))
250
251 JointIndex j = i;
252
253 while (j > 0)
254 {
255
256 for (int q = 0; q < model.nvs[j]; q++)
257 {
258 const Eigen::DenseIndex jq = model.idx_vs[j] + q;
259
260 const MotionRef<typename Data::Matrix6x::ColXpr> S_j = data.J.col(jq);
261 const MotionRef<typename Data::Matrix6x::ColXpr> psid_dm =
262 data.psid.col(jq); // psi_dot{j}(:,q)
263 const MotionRef<typename Data::Matrix6x::ColXpr> psidd_dm =
264 data.psidd.col(jq); // psi_ddot{j}(:,q)
265 const MotionRef<typename Data::Matrix6x::ColXpr> phid_dm =
266 data.dJ.col(jq); // phi_dot{j}(:,q)
267
268 u1.noalias() = S_j.toVector().transpose() * r3;
269 u2.noalias() = S_j.toVector().transpose() * r1;
270 u3.noalias() = r3 * psid_dm.toVector() + r1 * psidd_dm.toVector() + r5 * S_j.toVector();
271 u4.noalias() = r6 * S_j.toVector();
272 u5.noalias() = r2 * psid_dm.toVector();
273 u6.noalias() = Bicphii * psid_dm.toVector();
274 u6.noalias() += r7 * S_j.toVector();
275 u7.noalias() = r3 * S_j.toVector() + r1 * (psid_dm.toVector() + phid_dm.toVector());
276 u8.noalias() = r4 * S_j.toVector();
277 u9.noalias() = r0 * S_j.toVector();
278 u10.noalias() = Bicphii * S_j.toVector();
279 u11.noalias() = S_j.toVector().transpose() * Bicphii;
280 u12.noalias() = psid_dm.toVector().transpose() * Bicphii;
281 u13.noalias() = r1 * S_j.toVector();
282
283 JointIndex k = j;
284
285 while (k > 0)
286 {
287
288 for (int r = 0; r < model.nvs[k]; r++)
289 {
290 const Eigen::DenseIndex kr = model.idx_vs[k] + r;
291
292 const MotionRef<typename Data::Matrix6x::ColXpr> S_k(data.J.col(kr));
293 const MotionRef<typename Data::Matrix6x::ColXpr> psid_dm =
294 data.psid.col(kr); // psi_dot{k}(:,r)
295 const MotionRef<typename Data::Matrix6x::ColXpr> psidd_dm =
296 data.psidd.col(kr); // psi_ddot{k}(:,r)
297 const MotionRef<typename Data::Matrix6x::ColXpr> phid_dm =
298 data.dJ.col(kr); // phi_dot{k}(:,r)
299
300 p1 = u11 * psid_dm.toVector();
301 p2 = u9.dot(psidd_dm.toVector());
302 p2 += (-u12 + u8.transpose()) * psid_dm.toVector();
303
304 d2tau_dqdq_(ip, jq, kr) = p2;
305 dtau_dqdv_(ip, kr, jq) = -p1;
306
307 if (j != i)
308 {
309 p3 = -u11 * S_k.toVector();
310 p4 = S_k.toVector().dot(u13);
311 d2tau_dqdq_(jq, kr, ip) = u1 * psid_dm.toVector();
312 d2tau_dqdq_(jq, kr, ip) += u2 * psidd_dm.toVector();
313 d2tau_dqdq_(jq, ip, kr) = d2tau_dqdq_(jq, kr, ip);
314 dtau_dqdv_(jq, kr, ip) = p1;
315 dtau_dqdv_(jq, ip, kr) = u1 * S_k.toVector();
316 dtau_dqdv_(jq, ip, kr) += u2 * (psid_dm.toVector() + phid_dm.toVector());
317 d2tau_dvdv_(jq, kr, ip) = -p3;
318 d2tau_dvdv_(jq, ip, kr) = -p3;
319 dtau_dadq_(kr, jq, ip) = p4;
320 dtau_dadq_(jq, kr, ip) = p4;
321 }
322
323 if (k != j)
324 {
325 p3 = -u11 * S_k.toVector();
326 p5 = S_k.toVector().dot(u9);
327 d2tau_dqdq_(ip, kr, jq) = p2;
328 d2tau_dqdq_(kr, ip, jq) = S_k.toVector().dot(u3);
329 d2tau_dvdv_(ip, jq, kr) = p3;
330 d2tau_dvdv_(ip, kr, jq) = p3;
331 dtau_dqdv_(ip, jq, kr) = S_k.toVector().dot(u5 + u8);
332 dtau_dqdv_(ip, jq, kr) += u9.dot(psid_dm.toVector() + phid_dm.toVector());
333 dtau_dqdv_(kr, jq, ip) = S_k.toVector().dot(u6);
334 dtau_dadq_(kr, ip, jq) = p5;
335 dtau_dadq_(ip, kr, jq) = p5;
336 if (j != i)
337 {
338 p6 = S_k.toVector().dot(u10);
339 d2tau_dqdq_(kr, jq, ip) = d2tau_dqdq_(kr, ip, jq);
340 d2tau_dvdv_(kr, ip, jq) = p6;
341 d2tau_dvdv_(kr, jq, ip) = p6;
342 dtau_dqdv_(kr, ip, jq) = S_k.toVector().dot(u7);
343 }
344 else
345 {
346 d2tau_dvdv_(kr, jq, ip) = S_k.toVector().dot(u4);
347 }
348 }
349 else
350 {
351 d2tau_dvdv_(ip, jq, kr) = -u2 * S_k.toVector();
352 }
353 }
354
355 k = model.parents[k];
356 }
357 }
358 j = model.parents[j];
359 }
360 }
361
362 if (parent > 0)
363 {
364 data.oYcrb[parent] += data.oYcrb[i];
365 data.doYcrb[parent] += data.doYcrb[i];
366 data.of[parent] += data.of[i];
367 }
368 }
369
370 // Function for cmf_bar operator
371 template<typename ForceDerived, typename M6>
372 static void
373 ForceCrossMatrix(const ForceDense<ForceDerived> & f, const Eigen::MatrixBase<M6> & mout)
374 {
375 M6 & mout_ = PINOCCHIO_EIGEN_CONST_CAST(M6, mout);
376 mout_.template block<3, 3>(ForceDerived::LINEAR, ForceDerived::LINEAR).setZero();
377 mout_.template block<3, 3>(ForceDerived::LINEAR, ForceDerived::ANGULAR) =
378 mout_.template block<3, 3>(ForceDerived::ANGULAR, ForceDerived::LINEAR) = skew(-f.linear());
379 mout_.template block<3, 3>(ForceDerived::ANGULAR, ForceDerived::ANGULAR) = skew(-f.angular());
380 }
381 template<typename ForceDerived, typename M6>
382
383 static void
384 addForceCrossMatrix(const ForceDense<ForceDerived> & f, const Eigen::MatrixBase<M6> & mout)
385 {
386 M6 & mout_ = PINOCCHIO_EIGEN_CONST_CAST(M6, mout);
387 addSkew(-f.linear(), mout_.template block<3, 3>(ForceDerived::LINEAR, ForceDerived::ANGULAR));
388 addSkew(-f.linear(), mout_.template block<3, 3>(ForceDerived::ANGULAR, ForceDerived::LINEAR));
389 addSkew(
390 -f.angular(), mout_.template block<3, 3>(ForceDerived::ANGULAR, ForceDerived::ANGULAR));
391 }
392 };
393
394 template<
395 typename Scalar,
396 int Options,
397 template<typename, int>
398 class JointCollectionTpl,
399 typename ConfigVectorType,
400 typename TangentVectorType1,
401 typename TangentVectorType2,
402 typename Tensor1,
403 typename Tensor2,
404 typename Tensor3,
405 typename Tensor4>
406 inline void ComputeRNEASecondOrderDerivatives(
407 const ModelTpl<Scalar, Options, JointCollectionTpl> & model,
408 DataTpl<Scalar, Options, JointCollectionTpl> & data,
409 const Eigen::MatrixBase<ConfigVectorType> & q,
410 const Eigen::MatrixBase<TangentVectorType1> & v,
411 const Eigen::MatrixBase<TangentVectorType2> & a,
412 const Tensor1 & d2tau_dqdq,
413 const Tensor2 & d2tau_dvdv,
414 const Tensor3 & dtau_dqdv,
415 const Tensor4 & dtau_dadq)
416 {
417 // Extra safety here
418 PINOCCHIO_CHECK_ARGUMENT_SIZE(
419 q.size(), model.nq, "The joint configuration vector is not of right size");
420 PINOCCHIO_CHECK_ARGUMENT_SIZE(
421 v.size(), model.nv, "The joint velocity vector is not of right size");
422 PINOCCHIO_CHECK_ARGUMENT_SIZE(
423 a.size(), model.nv, "The joint acceleration vector is not of right size");
424 PINOCCHIO_CHECK_ARGUMENT_SIZE(d2tau_dqdq.dimension(0), model.nv);
425 PINOCCHIO_CHECK_ARGUMENT_SIZE(d2tau_dqdq.dimension(1), model.nv);
426 PINOCCHIO_CHECK_ARGUMENT_SIZE(d2tau_dqdq.dimension(2), model.nv);
427 PINOCCHIO_CHECK_ARGUMENT_SIZE(d2tau_dvdv.dimension(0), model.nv);
428 PINOCCHIO_CHECK_ARGUMENT_SIZE(d2tau_dvdv.dimension(1), model.nv);
429 PINOCCHIO_CHECK_ARGUMENT_SIZE(d2tau_dvdv.dimension(2), model.nv);
430 PINOCCHIO_CHECK_ARGUMENT_SIZE(dtau_dqdv.dimension(0), model.nv);
431 PINOCCHIO_CHECK_ARGUMENT_SIZE(dtau_dqdv.dimension(1), model.nv);
432 PINOCCHIO_CHECK_ARGUMENT_SIZE(dtau_dqdv.dimension(2), model.nv);
433 PINOCCHIO_CHECK_ARGUMENT_SIZE(dtau_dadq.dimension(0), model.nv);
434 PINOCCHIO_CHECK_ARGUMENT_SIZE(dtau_dadq.dimension(1), model.nv);
435 PINOCCHIO_CHECK_ARGUMENT_SIZE(dtau_dadq.dimension(2), model.nv);
436 assert(model.check(data) && "data is not consistent with model.");
437
438 typedef ModelTpl<Scalar, Options, JointCollectionTpl> Model;
439 typedef typename Model::JointIndex JointIndex;
440
441 typedef ComputeRNEASecondOrderDerivativesForwardStep<
442 Scalar, Options, JointCollectionTpl, ConfigVectorType, TangentVectorType1, TangentVectorType2>
443 Pass1;
444 for (JointIndex i = 1; i < (JointIndex)model.njoints; ++i)
445 {
446 Pass1::run(
447 model.joints[i], data.joints[i],
448 typename Pass1::ArgsType(model, data, q.derived(), v.derived(), a.derived()));
449 }
450
451 typedef ComputeRNEASecondOrderDerivativesBackwardStep<
452 Scalar, Options, JointCollectionTpl, Tensor1, Tensor2, Tensor3, Tensor4>
453 Pass2;
454 for (JointIndex i = (JointIndex)(model.njoints - 1); i > 0; --i)
455 {
456 Pass2::run(
457 model.joints[i],
458 typename Pass2::ArgsType(
459 model, data, const_cast<Tensor1 &>(d2tau_dqdq), const_cast<Tensor2 &>(d2tau_dvdv),
460 const_cast<Tensor3 &>(dtau_dqdv), const_cast<Tensor4 &>(dtau_dadq)));
461 }
462 }
463
464 } // namespace pinocchio
465
466 #endif // ifndef __pinocchio_algorithm_rnea_second_order_derivatives_hxx__
467