Directory: | ./ |
---|---|
File: | include/pinocchio/spatial/inertia.hpp |
Date: | 2024-08-27 18:20:05 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 188 | 318 | 59.1% |
Branches: | 180 | 732 | 24.6% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | // | ||
2 | // Copyright (c) 2015-2021 CNRS INRIA | ||
3 | // Copyright (c) 2016 Wandercraft, 86 rue de Paris 91400 Orsay, France. | ||
4 | // | ||
5 | |||
6 | #ifndef __pinocchio_spatial_inertia_hpp__ | ||
7 | #define __pinocchio_spatial_inertia_hpp__ | ||
8 | |||
9 | #include "pinocchio/math/fwd.hpp" | ||
10 | #include "pinocchio/spatial/symmetric3.hpp" | ||
11 | #include "pinocchio/spatial/force.hpp" | ||
12 | #include "pinocchio/spatial/motion.hpp" | ||
13 | #include "pinocchio/spatial/skew.hpp" | ||
14 | |||
15 | namespace pinocchio | ||
16 | { | ||
17 | |||
18 | template<class Derived> | ||
19 | struct InertiaBase : NumericalBase<Derived> | ||
20 | { | ||
21 | SPATIAL_TYPEDEF_TEMPLATE(Derived); | ||
22 | |||
23 | 77822 | Derived & derived() | |
24 | { | ||
25 | 77822 | return *static_cast<Derived *>(this); | |
26 | } | ||
27 | 162666 | const Derived & derived() const | |
28 | { | ||
29 | 162666 | return *static_cast<const Derived *>(this); | |
30 | } | ||
31 | |||
32 | Derived & const_cast_derived() const | ||
33 | { | ||
34 | return *const_cast<Derived *>(&derived()); | ||
35 | } | ||
36 | |||
37 | Scalar mass() const | ||
38 | { | ||
39 | return static_cast<const Derived *>(this)->mass(); | ||
40 | } | ||
41 | Scalar & mass() | ||
42 | { | ||
43 | return static_cast<const Derived *>(this)->mass(); | ||
44 | } | ||
45 | const Vector3 & lever() const | ||
46 | { | ||
47 | return static_cast<const Derived *>(this)->lever(); | ||
48 | } | ||
49 | Vector3 & lever() | ||
50 | { | ||
51 | return static_cast<const Derived *>(this)->lever(); | ||
52 | } | ||
53 | const Symmetric3 & inertia() const | ||
54 | { | ||
55 | return static_cast<const Derived *>(this)->inertia(); | ||
56 | } | ||
57 | Symmetric3 & inertia() | ||
58 | { | ||
59 | return static_cast<const Derived *>(this)->inertia(); | ||
60 | } | ||
61 | |||
62 | template<typename Matrix6Like> | ||
63 | void matrix(const Eigen::MatrixBase<Matrix6Like> & mat) const | ||
64 | { | ||
65 | derived().matrix_impl(mat); | ||
66 | } | ||
67 | 875 | Matrix6 matrix() const | |
68 | { | ||
69 | 875 | return derived().matrix_impl(); | |
70 | } | ||
71 | 697 | operator Matrix6() const | |
72 | { | ||
73 | 697 | return matrix(); | |
74 | } | ||
75 | |||
76 | template<typename Matrix6Like> | ||
77 | void inverse(const Eigen::MatrixBase<Matrix6Like> & mat) const | ||
78 | { | ||
79 | derived().inverse_impl(mat); | ||
80 | } | ||
81 | ✗ | Matrix6 inverse() const | |
82 | { | ||
83 | ✗ | return derived().inverse_impl(); | |
84 | } | ||
85 | |||
86 | Derived & operator=(const Derived & clone) | ||
87 | { | ||
88 | return derived().__equl__(clone); | ||
89 | } | ||
90 | 106 | bool operator==(const Derived & other) const | |
91 | { | ||
92 | 106 | return derived().isEqual(other); | |
93 | } | ||
94 | 648 | bool operator!=(const Derived & other) const | |
95 | { | ||
96 | 648 | return !(*this == other); | |
97 | } | ||
98 | |||
99 | 77820 | Derived & operator+=(const Derived & Yb) | |
100 | { | ||
101 | 77820 | return derived().__pequ__(Yb); | |
102 | } | ||
103 | ✗ | Derived operator+(const Derived & Yb) const | |
104 | { | ||
105 | ✗ | return derived().__plus__(Yb); | |
106 | } | ||
107 | 2 | Derived & operator-=(const Derived & Yb) | |
108 | { | ||
109 | 2 | return derived().__mequ__(Yb); | |
110 | } | ||
111 | ✗ | Derived operator-(const Derived & Yb) const | |
112 | { | ||
113 | ✗ | return derived().__minus__(Yb); | |
114 | } | ||
115 | |||
116 | template<typename MotionDerived> | ||
117 | ForceTpl<typename traits<MotionDerived>::Scalar, traits<MotionDerived>::Options> | ||
118 | 119681 | operator*(const MotionDense<MotionDerived> & v) const | |
119 | { | ||
120 | 119681 | return derived().__mult__(v); | |
121 | } | ||
122 | |||
123 | template<typename MotionDerived> | ||
124 | 7222 | Scalar vtiv(const MotionDense<MotionDerived> & v) const | |
125 | { | ||
126 | 7222 | return derived().vtiv_impl(v); | |
127 | } | ||
128 | |||
129 | template<typename MotionDerived> | ||
130 | Matrix6 variation(const MotionDense<MotionDerived> & v) const | ||
131 | { | ||
132 | return derived().variation_impl(v); | ||
133 | } | ||
134 | |||
135 | /// \brief Time variation operator. | ||
136 | /// It computes the time derivative of an inertia I corresponding to the formula \f$ | ||
137 | /// \dot{I} = v \times^{*} I \f$. | ||
138 | /// | ||
139 | /// \param[in] v The spatial velocity of the frame supporting the inertia. | ||
140 | /// \param[in] I The spatial inertia in motion. | ||
141 | /// \param[out] Iout The time derivative of the inertia I. | ||
142 | /// | ||
143 | template<typename MotionDerived, typename M6> | ||
144 | static void | ||
145 | ✗ | vxi(const MotionDense<MotionDerived> & v, const Derived & I, const Eigen::MatrixBase<M6> & Iout) | |
146 | { | ||
147 | EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(M6, Matrix6); | ||
148 | ✗ | Derived::vxi_impl(v, I, Iout); | |
149 | } | ||
150 | |||
151 | template<typename MotionDerived> | ||
152 | ✗ | Matrix6 vxi(const MotionDense<MotionDerived> & v) const | |
153 | { | ||
154 | ✗ | Matrix6 Iout; | |
155 | ✗ | vxi(v, derived(), Iout); | |
156 | ✗ | return Iout; | |
157 | } | ||
158 | |||
159 | /// \brief Time variation operator. | ||
160 | /// It computes the time derivative of an inertia I corresponding to the formula \f$ | ||
161 | /// \dot{I} = v \times^{*} I \f$. | ||
162 | /// | ||
163 | /// \param[in] v The spatial velocity of the frame supporting the inertia. | ||
164 | /// \param[in] I The spatial inertia in motion. | ||
165 | /// \param[out] Iout The time derivative of the inertia I. | ||
166 | /// | ||
167 | template<typename MotionDerived, typename M6> | ||
168 | static void | ||
169 | ✗ | ivx(const MotionDense<MotionDerived> & v, const Derived & I, const Eigen::MatrixBase<M6> & Iout) | |
170 | { | ||
171 | EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(M6, Matrix6); | ||
172 | ✗ | Derived::ivx_impl(v, I, Iout); | |
173 | } | ||
174 | |||
175 | template<typename MotionDerived> | ||
176 | ✗ | Matrix6 ivx(const MotionDense<MotionDerived> & v) const | |
177 | { | ||
178 | ✗ | Matrix6 Iout; | |
179 | ✗ | ivx(v, derived(), Iout); | |
180 | ✗ | return Iout; | |
181 | } | ||
182 | |||
183 | void setZero() | ||
184 | { | ||
185 | derived().setZero(); | ||
186 | } | ||
187 | void setIdentity() | ||
188 | { | ||
189 | derived().setIdentity(); | ||
190 | } | ||
191 | void setRandom() | ||
192 | { | ||
193 | derived().setRandom(); | ||
194 | } | ||
195 | |||
196 | 43 | bool isApprox( | |
197 | const Derived & other, | ||
198 | const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision()) const | ||
199 | { | ||
200 | 43 | return derived().isApprox_impl(other, prec); | |
201 | } | ||
202 | |||
203 | 341 | bool isZero(const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision()) const | |
204 | { | ||
205 | 341 | return derived().isZero_impl(prec); | |
206 | } | ||
207 | |||
208 | /// aI = aXb.act(bI) | ||
209 | template<typename S2, int O2> | ||
210 | 63156 | Derived se3Action(const SE3Tpl<S2, O2> & M) const | |
211 | { | ||
212 | 63156 | return derived().se3Action_impl(M); | |
213 | } | ||
214 | |||
215 | /// bI = aXb.actInv(aI) | ||
216 | template<typename S2, int O2> | ||
217 | ✗ | Derived se3ActionInverse(const SE3Tpl<S2, O2> & M) const | |
218 | { | ||
219 | ✗ | return derived().se3ActionInverse_impl(M); | |
220 | } | ||
221 | |||
222 | ✗ | void disp(std::ostream & os) const | |
223 | { | ||
224 | ✗ | static_cast<const Derived *>(this)->disp_impl(os); | |
225 | } | ||
226 | ✗ | friend std::ostream & operator<<(std::ostream & os, const InertiaBase<Derived> & X) | |
227 | { | ||
228 | ✗ | X.disp(os); | |
229 | ✗ | return os; | |
230 | } | ||
231 | |||
232 | }; // class InertiaBase | ||
233 | |||
234 | template<typename T, int U> | ||
235 | struct traits<InertiaTpl<T, U>> | ||
236 | { | ||
237 | typedef T Scalar; | ||
238 | typedef Eigen::Matrix<T, 3, 1, U> Vector3; | ||
239 | typedef Eigen::Matrix<T, 4, 1, U> Vector4; | ||
240 | typedef Eigen::Matrix<T, 6, 1, U> Vector6; | ||
241 | typedef Eigen::Matrix<T, 3, 3, U> Matrix3; | ||
242 | typedef Eigen::Matrix<T, 4, 4, U> Matrix4; | ||
243 | typedef Eigen::Matrix<T, 6, 6, U> Matrix6; | ||
244 | typedef Matrix6 ActionMatrix_t; | ||
245 | typedef Vector3 Angular_t; | ||
246 | typedef Vector3 Linear_t; | ||
247 | typedef const Vector3 ConstAngular_t; | ||
248 | typedef const Vector3 ConstLinear_t; | ||
249 | typedef Eigen::Quaternion<T, U> Quaternion_t; | ||
250 | typedef SE3Tpl<T, U> SE3; | ||
251 | typedef ForceTpl<T, U> Force; | ||
252 | typedef MotionTpl<T, U> Motion; | ||
253 | typedef Symmetric3Tpl<T, U> Symmetric3; | ||
254 | enum | ||
255 | { | ||
256 | LINEAR = 0, | ||
257 | ANGULAR = 3 | ||
258 | }; | ||
259 | }; // traits InertiaTpl | ||
260 | |||
261 | template<typename _Scalar, int _Options> | ||
262 | struct InertiaTpl : public InertiaBase<InertiaTpl<_Scalar, _Options>> | ||
263 | { | ||
264 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW | ||
265 | |||
266 | SPATIAL_TYPEDEF_TEMPLATE(InertiaTpl); | ||
267 | enum | ||
268 | { | ||
269 | Options = _Options | ||
270 | }; | ||
271 | |||
272 | typedef typename Symmetric3::AlphaSkewSquare AlphaSkewSquare; | ||
273 | typedef typename Eigen::Matrix<Scalar, 10, 1, Options> Vector10; | ||
274 | |||
275 | // Constructors | ||
276 | ✗ | InertiaTpl() | |
277 | { | ||
278 | } | ||
279 | |||
280 | 1621 | InertiaTpl(const Scalar & mass, const Vector3 & com, const Matrix3 & rotational_inertia) | |
281 | 1621 | : m_mass(mass) | |
282 | 1621 | , m_com(com) | |
283 | 1621 | , m_inertia(rotational_inertia) | |
284 | { | ||
285 | 1621 | } | |
286 | |||
287 | ✗ | explicit InertiaTpl(const Matrix6 & I6) | |
288 | { | ||
289 | ✗ | assert(check_expression_if_real<Scalar>(pinocchio::isZero(I6 - I6.transpose()))); | |
290 | ✗ | mass() = I6(LINEAR, LINEAR); | |
291 | const typename Matrix6::template ConstFixedBlockXpr<3, 3>::Type mc_cross = | ||
292 | ✗ | I6.template block<3, 3>(ANGULAR, LINEAR); | |
293 | ✗ | lever() = unSkew(mc_cross); | |
294 | ✗ | lever() /= mass(); | |
295 | |||
296 | ✗ | Matrix3 I3(mc_cross * mc_cross); | |
297 | ✗ | I3 /= mass(); | |
298 | ✗ | I3 += I6.template block<3, 3>(ANGULAR, ANGULAR); | |
299 | ✗ | const Symmetric3 S3(I3); | |
300 | ✗ | inertia() = S3; | |
301 | } | ||
302 | |||
303 | 70985 | InertiaTpl(const Scalar & mass, const Vector3 & com, const Symmetric3 & rotational_inertia) | |
304 | 70985 | : m_mass(mass) | |
305 | 70985 | , m_com(com) | |
306 | 70985 | , m_inertia(rotational_inertia) | |
307 | { | ||
308 | 70985 | } | |
309 | |||
310 | 72261 | InertiaTpl(const InertiaTpl & clone) // Copy constructor | |
311 | 72261 | : m_mass(clone.mass()) | |
312 | 72261 | , m_com(clone.lever()) | |
313 | 72261 | , m_inertia(clone.inertia()) | |
314 | { | ||
315 | 72261 | } | |
316 | |||
317 | 92807 | InertiaTpl & operator=(const InertiaTpl & clone) // Copy assignment operator | |
318 | { | ||
319 | 92807 | m_mass = clone.mass(); | |
320 | 92807 | m_com = clone.lever(); | |
321 | 92807 | m_inertia = clone.inertia(); | |
322 | 92807 | return *this; | |
323 | } | ||
324 | |||
325 | template<typename S2, int O2> | ||
326 | ✗ | explicit InertiaTpl(const InertiaTpl<S2, O2> & clone) | |
327 | { | ||
328 | ✗ | *this = clone.template cast<Scalar>(); | |
329 | } | ||
330 | |||
331 | // Initializers | ||
332 | 23092 | static InertiaTpl Zero() | |
333 | { | ||
334 |
3/6✓ Branch 2 taken 23092 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 23092 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 23092 times.
✗ Branch 9 not taken.
|
46184 | return InertiaTpl(Scalar(0), Vector3::Zero(), Symmetric3::Zero()); |
335 | } | ||
336 | |||
337 | 2201 | void setZero() | |
338 | { | ||
339 | 2201 | mass() = Scalar(0); | |
340 | 2201 | lever().setZero(); | |
341 | 2201 | inertia().setZero(); | |
342 | 2201 | } | |
343 | |||
344 | 137 | static InertiaTpl Identity() | |
345 | { | ||
346 |
3/6✓ Branch 2 taken 137 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 137 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 137 times.
✗ Branch 9 not taken.
|
274 | return InertiaTpl(Scalar(1), Vector3::Zero(), Symmetric3::Identity()); |
347 | } | ||
348 | |||
349 | ✗ | void setIdentity() | |
350 | { | ||
351 | ✗ | mass() = Scalar(1); | |
352 | ✗ | lever().setZero(); | |
353 | ✗ | inertia().setIdentity(); | |
354 | } | ||
355 | |||
356 | 7539 | static InertiaTpl Random() | |
357 | { | ||
358 | // We have to shoot "I" definite positive and not only symmetric. | ||
359 | return InertiaTpl( | ||
360 |
4/8✓ Branch 2 taken 7539 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 7539 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 7539 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 7539 times.
✗ Branch 12 not taken.
|
15078 | Eigen::internal::random<Scalar>() + 1, Vector3::Random(), Symmetric3::RandomPositive()); |
361 | } | ||
362 | |||
363 | /// | ||
364 | /// \brief Computes the Inertia of a sphere defined by its mass and its radius. | ||
365 | /// | ||
366 | /// \param[in] mass of the sphere. | ||
367 | /// \param[in] radius of the sphere. | ||
368 | /// | ||
369 | 6 | static InertiaTpl FromSphere(const Scalar mass, const Scalar radius) | |
370 | { | ||
371 | 6 | return FromEllipsoid(mass, radius, radius, radius); | |
372 | } | ||
373 | |||
374 | /// | ||
375 | /// \brief Computes the Inertia of an ellipsoid defined by its mass and main semi-axis | ||
376 | /// dimensions (x,y,z). | ||
377 | /// | ||
378 | /// \param[in] mass of the ellipsoid. | ||
379 | /// \param[in] x semi-axis dimension along the local X axis. | ||
380 | /// \param[in] y semi-axis dimension along the local Y axis. | ||
381 | /// \param[in] z semi-axis dimension along the local Z axis. | ||
382 | /// | ||
383 | static InertiaTpl | ||
384 | 11 | FromEllipsoid(const Scalar mass, const Scalar x, const Scalar y, const Scalar z) | |
385 | { | ||
386 | 11 | const Scalar a = mass * (y * y + z * z) / Scalar(5); | |
387 | 11 | const Scalar b = mass * (x * x + z * z) / Scalar(5); | |
388 | 11 | const Scalar c = mass * (y * y + x * x) / Scalar(5); | |
389 | return InertiaTpl( | ||
390 |
4/8✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 11 not taken.
|
11 | mass, Vector3::Zero(), Symmetric3(a, Scalar(0), b, Scalar(0), Scalar(0), c)); |
391 | } | ||
392 | |||
393 | /// | ||
394 | /// \brief Computes the Inertia of a cylinder defined by its mass, radius and length along the Z | ||
395 | /// axis. | ||
396 | /// | ||
397 | /// \param[in] mass of the cylinder. | ||
398 | /// \param[in] radius of the cylinder. | ||
399 | /// \param[in] length of the cylinder. | ||
400 | /// | ||
401 | 7 | static InertiaTpl FromCylinder(const Scalar mass, const Scalar radius, const Scalar length) | |
402 | { | ||
403 | 7 | const Scalar radius_square = radius * radius; | |
404 | 7 | const Scalar a = mass * (radius_square / Scalar(4) + length * length / Scalar(12)); | |
405 | 7 | const Scalar c = mass * (radius_square / Scalar(2)); | |
406 | return InertiaTpl( | ||
407 |
4/8✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 11 not taken.
|
7 | mass, Vector3::Zero(), Symmetric3(a, Scalar(0), a, Scalar(0), Scalar(0), c)); |
408 | } | ||
409 | |||
410 | /// | ||
411 | /// \brief Computes the Inertia of a box defined by its mass and main dimensions (x,y,z). | ||
412 | /// | ||
413 | /// \param[in] mass of the box. | ||
414 | /// \param[in] x dimension along the local X axis. | ||
415 | /// \param[in] y dimension along the local Y axis. | ||
416 | /// \param[in] z dimension along the local Z axis. | ||
417 | /// | ||
418 | 10 | static InertiaTpl FromBox(const Scalar mass, const Scalar x, const Scalar y, const Scalar z) | |
419 | { | ||
420 | 10 | const Scalar a = mass * (y * y + z * z) / Scalar(12); | |
421 | 10 | const Scalar b = mass * (x * x + z * z) / Scalar(12); | |
422 | 10 | const Scalar c = mass * (y * y + x * x) / Scalar(12); | |
423 | return InertiaTpl( | ||
424 |
4/8✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 10 times.
✗ Branch 11 not taken.
|
10 | mass, Vector3::Zero(), Symmetric3(a, Scalar(0), b, Scalar(0), Scalar(0), c)); |
425 | } | ||
426 | |||
427 | /// | ||
428 | /// \brief Computes the Inertia of a capsule defined by its mass, radius and length along the Z | ||
429 | /// axis. Assumes a uniform density. | ||
430 | /// | ||
431 | /// \param[in] mass of the capsule. | ||
432 | /// \param[in] radius of the capsule. | ||
433 | /// \param[in] height of the capsule. | ||
434 | 7 | static InertiaTpl FromCapsule(const Scalar mass, const Scalar radius, const Scalar height) | |
435 | { | ||
436 | 7 | const Scalar pi = boost::math::constants::pi<Scalar>(); | |
437 | |||
438 | // first need to compute mass repartition between cylinder and halfsphere | ||
439 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | const Scalar v_cyl = pi * math::pow(radius, 2) * height; |
440 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | const Scalar v_hs = Scalar(2) / Scalar(3) * math::pow(radius, 3) * pi; |
441 | 7 | const Scalar total_v = v_cyl + Scalar(2) * v_hs; | |
442 | |||
443 | 7 | const Scalar m_cyl = mass * (v_cyl / total_v); | |
444 | 7 | const Scalar m_hs = mass * (v_hs / total_v); | |
445 | |||
446 | // Then Distance between halfSphere center and cylindere center. | ||
447 | 7 | const Scalar dist_hc_cyl = height / Scalar(2) + Scalar(0.375) * radius; | |
448 | |||
449 | // Computes inertia terms | ||
450 | 7 | const Scalar ix_c = | |
451 |
2/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
7 | m_cyl * (math::pow(height, 2) / Scalar(12) + math::pow(radius, 2) / Scalar(4)); |
452 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | const Scalar iz_c = m_cyl * math::pow(radius, 2) / Scalar(2); |
453 | |||
454 | // For halfsphere inertia see, "Dynamics: Theory and Applications" McGraw-Hill, New York, | ||
455 | // 1985, by T.R. Kane and D.A. Levinson, Appendix 23. | ||
456 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | const Scalar ix_hs = m_hs * math::pow(radius, 2) * Scalar(0.259375); |
457 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | const Scalar iz_hs = m_hs * math::pow(radius, 2) * Scalar(0.4); |
458 | |||
459 | // Put everything together using the parallel axis theorem | ||
460 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | const Scalar ix = ix_c + Scalar(2) * (ix_hs + m_hs * math::pow(dist_hc_cyl, 2)); |
461 | 7 | const Scalar iz = iz_c + Scalar(2) * iz_hs; | |
462 | |||
463 | return InertiaTpl( | ||
464 |
4/8✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 11 not taken.
|
7 | mass, Vector3::Zero(), Symmetric3(ix, Scalar(0), ix, Scalar(0), Scalar(0), iz)); |
465 | } | ||
466 | |||
467 | ✗ | void setRandom() | |
468 | { | ||
469 | ✗ | mass() = static_cast<Scalar>(std::rand()) / static_cast<Scalar>(RAND_MAX); | |
470 | ✗ | lever().setRandom(); | |
471 | ✗ | inertia().setRandom(); | |
472 | } | ||
473 | |||
474 | template<typename Matrix6Like> | ||
475 | 875 | void matrix_impl(const Eigen::MatrixBase<Matrix6Like> & M_) const | |
476 | { | ||
477 | 875 | Matrix6Like & M = M_.const_cast_derived(); | |
478 | |||
479 |
1/2✓ Branch 2 taken 875 times.
✗ Branch 3 not taken.
|
875 | M.template block<3, 3>(LINEAR, LINEAR).setZero(); |
480 |
2/4✓ Branch 2 taken 875 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 875 times.
✗ Branch 7 not taken.
|
875 | M.template block<3, 3>(LINEAR, LINEAR).diagonal().fill(mass()); |
481 |
2/4✓ Branch 4 taken 875 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 875 times.
✗ Branch 8 not taken.
|
875 | M.template block<3, 3>(ANGULAR, LINEAR) = alphaSkew(mass(), lever()); |
482 |
3/6✓ Branch 2 taken 875 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 875 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 875 times.
✗ Branch 9 not taken.
|
875 | M.template block<3, 3>(LINEAR, ANGULAR) = -M.template block<3, 3>(ANGULAR, LINEAR); |
483 |
4/8✓ Branch 1 taken 875 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 875 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 875 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 875 times.
✗ Branch 11 not taken.
|
875 | M.template block<3, 3>(ANGULAR, ANGULAR) = |
484 | 875 | (inertia() - AlphaSkewSquare(mass(), lever())).matrix(); | |
485 | 875 | } | |
486 | |||
487 | 875 | Matrix6 matrix_impl() const | |
488 | { | ||
489 | 875 | Matrix6 M; | |
490 | 875 | matrix_impl(M); | |
491 | 875 | return M; | |
492 | } | ||
493 | |||
494 | template<typename Matrix6Like> | ||
495 | ✗ | void inverse_impl(const Eigen::MatrixBase<Matrix6Like> & M_) const | |
496 | { | ||
497 | ✗ | Matrix6Like & M = M_.const_cast_derived(); | |
498 | ✗ | inertia().inverse(M.template block<3, 3>(ANGULAR, ANGULAR)); | |
499 | |||
500 | ✗ | M.template block<3, 3>(LINEAR, ANGULAR).noalias() = | |
501 | ✗ | -M.template block<3, 3>(ANGULAR, ANGULAR).colwise().cross(lever()); | |
502 | ✗ | M.template block<3, 3>(ANGULAR, LINEAR) = M.template block<3, 3>(LINEAR, ANGULAR).transpose(); | |
503 | |||
504 | ✗ | const Scalar &cx = lever()[0], cy = lever()[1], cz = lever()[2]; | |
505 | |||
506 | ✗ | M.template block<3, 3>(LINEAR, LINEAR).col(0).noalias() = | |
507 | ✗ | cy * M.template block<3, 3>(LINEAR, ANGULAR).col(2) | |
508 | ✗ | - cz * M.template block<3, 3>(LINEAR, ANGULAR).col(1); | |
509 | |||
510 | ✗ | M.template block<3, 3>(LINEAR, LINEAR).col(1).noalias() = | |
511 | ✗ | cz * M.template block<3, 3>(LINEAR, ANGULAR).col(0) | |
512 | ✗ | - cx * M.template block<3, 3>(LINEAR, ANGULAR).col(2); | |
513 | |||
514 | ✗ | M.template block<3, 3>(LINEAR, LINEAR).col(2).noalias() = | |
515 | ✗ | cx * M.template block<3, 3>(LINEAR, ANGULAR).col(1) | |
516 | ✗ | - cy * M.template block<3, 3>(LINEAR, ANGULAR).col(0); | |
517 | |||
518 | ✗ | const Scalar m_inv = Scalar(1) / mass(); | |
519 | ✗ | M.template block<3, 3>(LINEAR, LINEAR).diagonal().array() += m_inv; | |
520 | } | ||
521 | |||
522 | ✗ | Matrix6 inverse_impl() const | |
523 | { | ||
524 | ✗ | Matrix6 res; | |
525 | ✗ | inverse_impl(res); | |
526 | ✗ | return res; | |
527 | } | ||
528 | |||
529 | /** Returns the representation of the matrix as a vector of dynamic parameters. | ||
530 | * The parameters are given as | ||
531 | * \f$ v = [m, mc_x, mc_y, mc_z, I_{xx}, I_{xy}, I_{yy}, I_{xz}, I_{yz}, I_{zz}]^T \f$ | ||
532 | * where \f$ c \f$ is the center of mass, \f$ I = I_C + mS^T(c)S(c) \f$ and \f$ I_C \f$ has its | ||
533 | * origin at the barycenter and \f$ S(c) \f$ is the the skew matrix representation of the cross | ||
534 | * product operator. | ||
535 | */ | ||
536 | ✗ | Vector10 toDynamicParameters() const | |
537 | { | ||
538 | ✗ | Vector10 v; | |
539 | |||
540 | ✗ | v[0] = mass(); | |
541 | ✗ | v.template segment<3>(1).noalias() = mass() * lever(); | |
542 | ✗ | v.template segment<6>(4) = (inertia() - AlphaSkewSquare(mass(), lever())).data(); | |
543 | |||
544 | ✗ | return v; | |
545 | } | ||
546 | |||
547 | /** Builds and inertia matrix from a vector of dynamic parameters. | ||
548 | * | ||
549 | * @param[in] params The dynamic parameters. | ||
550 | * | ||
551 | * The parameters are given as | ||
552 | * \f$ v = [m, mc_x, mc_y, mc_z, I_{xx}, I_{xy}, I_{yy}, I_{xz}, I_{yz}, I_{zz}]^T \f$ | ||
553 | * where \f$ I = I_C + mS^T(c)S(c) \f$ and \f$ I_C \f$ has its origin at the barycenter. | ||
554 | */ | ||
555 | template<typename Vector10Like> | ||
556 | ✗ | static InertiaTpl FromDynamicParameters(const Eigen::MatrixBase<Vector10Like> & params) | |
557 | { | ||
558 | ✗ | PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE(Vector10Like, params, 10, 1); | |
559 | |||
560 | ✗ | const Scalar & mass = params[0]; | |
561 | ✗ | Vector3 lever = params.template segment<3>(1); | |
562 | ✗ | lever /= mass; | |
563 | |||
564 | return InertiaTpl( | ||
565 | ✗ | mass, lever, Symmetric3(params.template segment<6>(4)) + AlphaSkewSquare(mass, lever)); | |
566 | } | ||
567 | |||
568 | // Arithmetic operators | ||
569 | InertiaTpl & __equl__(const InertiaTpl & clone) | ||
570 | { | ||
571 | mass() = clone.mass(); | ||
572 | lever() = clone.lever(); | ||
573 | inertia() = clone.inertia(); | ||
574 | return *this; | ||
575 | } | ||
576 | |||
577 | // Required by std::vector boost::python bindings. | ||
578 | 107 | bool isEqual(const InertiaTpl & Y2) const | |
579 | { | ||
580 |
4/6✓ Branch 2 taken 106 times.
✓ Branch 3 taken 1 times.
✓ Branch 7 taken 106 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 106 times.
✗ Branch 13 not taken.
|
107 | return (mass() == Y2.mass()) && (lever() == Y2.lever()) && (inertia() == Y2.inertia()); |
581 | } | ||
582 | |||
583 | 43 | bool isApprox_impl( | |
584 | const InertiaTpl & other, | ||
585 | const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision()) const | ||
586 | { | ||
587 | using math::fabs; | ||
588 | 43 | return fabs(static_cast<Scalar>(mass() - other.mass())) <= prec | |
589 |
5/10✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 5 taken 43 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 43 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 43 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 43 times.
✗ Branch 15 not taken.
|
43 | && lever().isApprox(other.lever(), prec) && inertia().isApprox(other.inertia(), prec); |
590 | } | ||
591 | |||
592 | 341 | bool isZero_impl(const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision()) const | |
593 | { | ||
594 | using math::fabs; | ||
595 |
6/10✓ Branch 2 taken 20 times.
✓ Branch 3 taken 321 times.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 20 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 20 times.
✗ Branch 15 not taken.
|
341 | return fabs(mass()) <= prec && lever().isZero(prec) && inertia().isZero(prec); |
596 | } | ||
597 | |||
598 | ✗ | InertiaTpl __plus__(const InertiaTpl & Yb) const | |
599 | { | ||
600 | /* Y_{a+b} = ( m_a+m_b, | ||
601 | * (m_a*c_a + m_b*c_b ) / (m_a + m_b), | ||
602 | * I_a + I_b - (m_a*m_b)/(m_a+m_b) * AB_x * AB_x ) | ||
603 | */ | ||
604 | |||
605 | ✗ | const Scalar eps = ::Eigen::NumTraits<Scalar>::epsilon(); | |
606 | |||
607 | ✗ | const Scalar & mab = mass() + Yb.mass(); | |
608 | ✗ | const Scalar mab_inv = Scalar(1) / math::max(mab, eps); | |
609 | ✗ | const Vector3 & AB = (lever() - Yb.lever()).eval(); | |
610 | return InertiaTpl( | ||
611 | ✗ | mab, (mass() * lever() + Yb.mass() * Yb.lever()) * mab_inv, | |
612 | ✗ | inertia() + Yb.inertia() | |
613 | ✗ | - (mass() * Yb.mass() * mab_inv) * typename Symmetric3::SkewSquare(AB)); | |
614 | } | ||
615 | |||
616 | 77820 | InertiaTpl & __pequ__(const InertiaTpl & Yb) | |
617 | { | ||
618 | static const Scalar eps = ::Eigen::NumTraits<Scalar>::epsilon(); | ||
619 | |||
620 | 77820 | const InertiaTpl & Ya = *this; | |
621 | 77820 | const Scalar & mab = mass() + Yb.mass(); | |
622 |
1/2✓ Branch 1 taken 77820 times.
✗ Branch 2 not taken.
|
77820 | const Scalar mab_inv = Scalar(1) / math::max(mab, eps); |
623 |
2/4✓ Branch 3 taken 77820 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 77820 times.
✗ Branch 7 not taken.
|
77820 | const Vector3 & AB = (Ya.lever() - Yb.lever()).eval(); |
624 |
1/2✓ Branch 3 taken 77820 times.
✗ Branch 4 not taken.
|
77820 | lever() *= (mass() * mab_inv); |
625 |
2/4✓ Branch 3 taken 77820 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 77820 times.
✗ Branch 8 not taken.
|
77820 | lever() += (Yb.mass() * mab_inv) * Yb.lever(); // c *= mab_inv; |
626 |
1/2✓ Branch 3 taken 77820 times.
✗ Branch 4 not taken.
|
77820 | inertia() += Yb.inertia(); |
627 |
2/4✓ Branch 4 taken 77820 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 77820 times.
✗ Branch 9 not taken.
|
77820 | inertia() -= (Ya.mass() * Yb.mass() * mab_inv) * typename Symmetric3::SkewSquare(AB); |
628 | 77820 | mass() = mab; | |
629 | 77820 | return *this; | |
630 | } | ||
631 | |||
632 | ✗ | InertiaTpl __minus__(const InertiaTpl & Yb) const | |
633 | { | ||
634 | /* Y_{a} = ( m_{a+b}+m_b, | ||
635 | * (m_{a+b}*c_{a+b} - m_b*c_b ) / (m_a), | ||
636 | * I_{a+b} - I_b + (m_a*m_b)/(m_a+m_b) * AB_x * AB_x ) | ||
637 | */ | ||
638 | |||
639 | ✗ | const Scalar eps = ::Eigen::NumTraits<Scalar>::epsilon(); | |
640 | |||
641 | ✗ | const Scalar ma = mass() - Yb.mass(); | |
642 | ✗ | assert(check_expression_if_real<Scalar>(ma >= Scalar(0))); | |
643 | |||
644 | ✗ | const Scalar ma_inv = Scalar(1) / math::max(ma, eps); | |
645 | ✗ | const Vector3 c_a((mass() * lever() - Yb.mass() * Yb.lever()) * ma_inv); | |
646 | |||
647 | ✗ | const Vector3 AB = c_a - Yb.lever(); | |
648 | |||
649 | return InertiaTpl( | ||
650 | ma, c_a, | ||
651 | ✗ | inertia() - Yb.inertia() + (ma * Yb.mass() / mass()) * typename Symmetric3::SkewSquare(AB)); | |
652 | } | ||
653 | |||
654 | 2 | InertiaTpl & __mequ__(const InertiaTpl & Yb) | |
655 | { | ||
656 | static const Scalar eps = ::Eigen::NumTraits<Scalar>::epsilon(); | ||
657 | |||
658 | 2 | const Scalar ma = mass() - Yb.mass(); | |
659 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | assert(check_expression_if_real<Scalar>(ma >= Scalar(0))); |
660 | |||
661 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | const Scalar ma_inv = Scalar(1) / math::max(ma, eps); |
662 | |||
663 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
2 | lever() *= (mass() * ma_inv); |
664 |
3/6✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
2 | lever().noalias() -= (Yb.mass() * ma_inv) * Yb.lever(); |
665 | |||
666 |
2/4✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
2 | const Vector3 AB = lever() - Yb.lever(); |
667 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
2 | inertia() -= Yb.inertia(); |
668 |
3/6✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
|
2 | inertia() += (ma * Yb.mass() / mass()) * typename Symmetric3::SkewSquare(AB); |
669 | 2 | mass() = ma; | |
670 | |||
671 | 2 | return *this; | |
672 | } | ||
673 | |||
674 | template<typename MotionDerived> | ||
675 | ForceTpl<typename traits<MotionDerived>::Scalar, traits<MotionDerived>::Options> | ||
676 | 119681 | __mult__(const MotionDense<MotionDerived> & v) const | |
677 | { | ||
678 | typedef ForceTpl<typename traits<MotionDerived>::Scalar, traits<MotionDerived>::Options> | ||
679 | ReturnType; | ||
680 | 119681 | ReturnType f; | |
681 | 119681 | __mult__(v, f); | |
682 | 119681 | return f; | |
683 | } | ||
684 | |||
685 | template<typename MotionDerived, typename ForceDerived> | ||
686 | 288350 | void __mult__(const MotionDense<MotionDerived> & v, ForceDense<ForceDerived> & f) const | |
687 | { | ||
688 |
7/14✓ Branch 3 taken 200125 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 200125 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 200125 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 200125 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 200125 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 200125 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 200125 times.
✗ Branch 23 not taken.
|
288350 | f.linear().noalias() = mass() * (v.linear() - lever().cross(v.angular())); |
689 |
2/4✓ Branch 2 taken 200125 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 200125 times.
✗ Branch 7 not taken.
|
288350 | Symmetric3::rhsMult(inertia(), v.angular(), f.angular()); |
690 |
3/6✓ Branch 3 taken 200125 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 200125 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 200125 times.
✗ Branch 10 not taken.
|
288350 | f.angular() += lever().cross(f.linear()); |
691 | // f.angular().noalias() = c.cross(f.linear()) + I*v.angular(); | ||
692 | 288350 | } | |
693 | |||
694 | template<typename MotionDerived> | ||
695 | 7222 | Scalar vtiv_impl(const MotionDense<MotionDerived> & v) const | |
696 | { | ||
697 |
2/4✓ Branch 2 taken 7222 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 7222 times.
✗ Branch 6 not taken.
|
7222 | const Vector3 cxw(lever().cross(v.angular())); |
698 |
4/8✓ Branch 2 taken 7222 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 7222 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 7222 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 7222 times.
✗ Branch 12 not taken.
|
7222 | Scalar res = mass() * (v.linear().squaredNorm() - Scalar(2) * v.linear().dot(cxw)); |
699 |
3/6✓ Branch 2 taken 7222 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 7222 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7222 times.
✗ Branch 10 not taken.
|
7222 | const Vector3 mcxcxw(-mass() * lever().cross(cxw)); |
700 |
2/4✓ Branch 1 taken 7222 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7222 times.
✗ Branch 5 not taken.
|
7222 | res += v.angular().dot(mcxcxw); |
701 |
3/6✓ Branch 2 taken 7222 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 7222 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 7222 times.
✗ Branch 9 not taken.
|
7222 | res += inertia().vtiv(v.angular()); |
702 | |||
703 | 7222 | return res; | |
704 | } | ||
705 | |||
706 | template<typename MotionDerived> | ||
707 | 10414 | Matrix6 variation(const MotionDense<MotionDerived> & v) const | |
708 | { | ||
709 |
1/2✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
|
10414 | Matrix6 res; |
710 |
1/2✓ Branch 2 taken 10414 times.
✗ Branch 3 not taken.
|
10414 | const Motion mv(v * mass()); |
711 | |||
712 |
8/16✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10414 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10414 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 10414 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 10414 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 10414 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 10414 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 10414 times.
✗ Branch 23 not taken.
|
31242 | res.template block<3, 3>(LINEAR, ANGULAR) = |
713 |
3/6✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 10414 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 10414 times.
✗ Branch 10 not taken.
|
31242 | -skew(mv.linear()) - skewSquare(mv.angular(), lever()) + skewSquare(lever(), mv.angular()); |
714 |
2/4✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10414 times.
✗ Branch 5 not taken.
|
10414 | res.template block<3, 3>(ANGULAR, LINEAR) = |
715 |
2/4✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10414 times.
✗ Branch 5 not taken.
|
10414 | res.template block<3, 3>(LINEAR, ANGULAR).transpose(); |
716 | |||
717 | // res.template block<3,3>(LINEAR,LINEAR) = mv.linear()*c.transpose(); // use as | ||
718 | // temporary variable res.template block<3,3>(ANGULAR,ANGULAR) = res.template | ||
719 | // block<3,3>(LINEAR,LINEAR) - res.template block<3,3>(LINEAR,LINEAR).transpose(); | ||
720 |
6/12✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10414 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10414 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 10414 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 10414 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 10414 times.
✗ Branch 17 not taken.
|
20828 | res.template block<3, 3>(ANGULAR, ANGULAR) = |
721 |
2/4✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 10414 times.
✗ Branch 7 not taken.
|
20828 | -skewSquare(mv.linear(), lever()) - skewSquare(lever(), mv.linear()); |
722 | |||
723 |
4/8✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10414 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10414 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 10414 times.
✗ Branch 11 not taken.
|
10414 | res.template block<3, 3>(LINEAR, LINEAR) = |
724 | 10414 | (inertia() - AlphaSkewSquare(mass(), lever())).matrix(); | |
725 | |||
726 |
2/4✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10414 times.
✗ Branch 5 not taken.
|
10414 | res.template block<3, 3>(ANGULAR, ANGULAR) -= |
727 |
4/8✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10414 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10414 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 10414 times.
✗ Branch 11 not taken.
|
10414 | res.template block<3, 3>(LINEAR, LINEAR) * skew(v.angular()); |
728 |
3/6✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10414 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10414 times.
✗ Branch 8 not taken.
|
10414 | res.template block<3, 3>(ANGULAR, ANGULAR) += |
729 |
2/4✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10414 times.
✗ Branch 5 not taken.
|
10414 | cross(v.angular(), res.template block<3, 3>(LINEAR, LINEAR)); |
730 | |||
731 |
2/4✓ Branch 1 taken 10414 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10414 times.
✗ Branch 5 not taken.
|
10414 | res.template block<3, 3>(LINEAR, LINEAR).setZero(); |
732 | 20828 | return res; | |
733 | } | ||
734 | |||
735 | template<typename MotionDerived, typename M6> | ||
736 | ✗ | static void vxi_impl( | |
737 | const MotionDense<MotionDerived> & v, | ||
738 | const InertiaTpl & I, | ||
739 | const Eigen::MatrixBase<M6> & Iout) | ||
740 | { | ||
741 | EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(M6, 6, 6); | ||
742 | ✗ | M6 & Iout_ = PINOCCHIO_EIGEN_CONST_CAST(M6, Iout); | |
743 | |||
744 | // Block 1,1 | ||
745 | ✗ | alphaSkew(I.mass(), v.angular(), Iout_.template block<3, 3>(LINEAR, LINEAR)); | |
746 | // Iout_.template block<3,3>(LINEAR,LINEAR) = alphaSkew(I.mass(),v.angular()); | ||
747 | ✗ | const Vector3 mc(I.mass() * I.lever()); | |
748 | |||
749 | // Block 1,2 | ||
750 | ✗ | skewSquare(-v.angular(), mc, Iout_.template block<3, 3>(LINEAR, ANGULAR)); | |
751 | |||
752 | //// Block 2,1 | ||
753 | ✗ | alphaSkew(I.mass(), v.linear(), Iout_.template block<3, 3>(ANGULAR, LINEAR)); | |
754 | ✗ | Iout_.template block<3, 3>(ANGULAR, LINEAR) -= Iout_.template block<3, 3>(LINEAR, ANGULAR); | |
755 | |||
756 | //// Block 2,2 | ||
757 | ✗ | skewSquare(-v.linear(), mc, Iout_.template block<3, 3>(ANGULAR, ANGULAR)); | |
758 | |||
759 | // TODO: I do not why, but depending on the CPU, these three lines can give | ||
760 | // wrong output. | ||
761 | // typename Symmetric3::AlphaSkewSquare mcxcx(I.mass(),I.lever()); | ||
762 | // const Symmetric3 I_mcxcx(I.inertia() - mcxcx); | ||
763 | // Iout_.template block<3,3>(ANGULAR,ANGULAR) += I_mcxcx.vxs(v.angular()); | ||
764 | ✗ | Symmetric3 mcxcx(typename Symmetric3::AlphaSkewSquare(I.mass(), I.lever())); | |
765 | ✗ | Iout_.template block<3, 3>(ANGULAR, ANGULAR) += I.inertia().vxs(v.angular()); | |
766 | ✗ | Iout_.template block<3, 3>(ANGULAR, ANGULAR) -= mcxcx.vxs(v.angular()); | |
767 | } | ||
768 | |||
769 | template<typename MotionDerived, typename M6> | ||
770 | ✗ | static void ivx_impl( | |
771 | const MotionDense<MotionDerived> & v, | ||
772 | const InertiaTpl & I, | ||
773 | const Eigen::MatrixBase<M6> & Iout) | ||
774 | { | ||
775 | EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(M6, 6, 6); | ||
776 | ✗ | M6 & Iout_ = PINOCCHIO_EIGEN_CONST_CAST(M6, Iout); | |
777 | |||
778 | // Block 1,1 | ||
779 | ✗ | alphaSkew(I.mass(), v.angular(), Iout_.template block<3, 3>(LINEAR, LINEAR)); | |
780 | |||
781 | // Block 2,1 | ||
782 | ✗ | const Vector3 mc(I.mass() * I.lever()); | |
783 | ✗ | skewSquare(mc, v.angular(), Iout_.template block<3, 3>(ANGULAR, LINEAR)); | |
784 | |||
785 | // Block 1,2 | ||
786 | ✗ | alphaSkew(I.mass(), v.linear(), Iout_.template block<3, 3>(LINEAR, ANGULAR)); | |
787 | |||
788 | // Block 2,2 | ||
789 | ✗ | cross( | |
790 | ✗ | -I.lever(), Iout_.template block<3, 3>(ANGULAR, LINEAR), | |
791 | ✗ | Iout_.template block<3, 3>(ANGULAR, ANGULAR)); | |
792 | ✗ | Iout_.template block<3, 3>(ANGULAR, ANGULAR) += I.inertia().svx(v.angular()); | |
793 | ✗ | for (int k = 0; k < 3; ++k) | |
794 | ✗ | Iout_.template block<3, 3>(ANGULAR, ANGULAR).col(k) += | |
795 | ✗ | I.lever().cross(Iout_.template block<3, 3>(LINEAR, ANGULAR).col(k)); | |
796 | |||
797 | // Block 1,2 | ||
798 | ✗ | Iout_.template block<3, 3>(LINEAR, ANGULAR) -= Iout_.template block<3, 3>(ANGULAR, LINEAR); | |
799 | } | ||
800 | |||
801 | // Getters | ||
802 | 620090 | Scalar mass() const | |
803 | { | ||
804 | 620090 | return m_mass; | |
805 | } | ||
806 | 743584 | const Vector3 & lever() const | |
807 | { | ||
808 | 743584 | return m_com; | |
809 | } | ||
810 | 429881 | const Symmetric3 & inertia() const | |
811 | { | ||
812 | 429881 | return m_inertia; | |
813 | } | ||
814 | |||
815 | 203821 | Scalar & mass() | |
816 | { | ||
817 | 203821 | return m_mass; | |
818 | } | ||
819 | 132247 | Vector3 & lever() | |
820 | { | ||
821 | 132247 | return m_com; | |
822 | } | ||
823 | 124197 | Symmetric3 & inertia() | |
824 | { | ||
825 | 124197 | return m_inertia; | |
826 | } | ||
827 | |||
828 | /// aI = aXb.act(bI) | ||
829 | template<typename S2, int O2> | ||
830 | 63156 | InertiaTpl se3Action_impl(const SE3Tpl<S2, O2> & M) const | |
831 | { | ||
832 | /* The multiplication RIR' has a particular form that could be used, however it | ||
833 | * does not seems to be more efficient, see http://stackoverflow.m_comom/questions/ | ||
834 | * 13215467/eigen-best-way-to-evaluate-asa-transpose-and-store-the-result-in-a-symmetric .*/ | ||
835 | return InertiaTpl( | ||
836 |
6/12✓ Branch 5 taken 63156 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 63156 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 63156 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 63156 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 63156 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 63156 times.
✗ Branch 22 not taken.
|
126312 | mass(), M.translation() + M.rotation() * lever(), inertia().rotate(M.rotation())); |
837 | } | ||
838 | |||
839 | /// bI = aXb.actInv(aI) | ||
840 | template<typename S2, int O2> | ||
841 | ✗ | InertiaTpl se3ActionInverse_impl(const SE3Tpl<S2, O2> & M) const | |
842 | { | ||
843 | return InertiaTpl( | ||
844 | ✗ | mass(), M.rotation().transpose() * (lever() - M.translation()), | |
845 | ✗ | inertia().rotate(M.rotation().transpose())); | |
846 | } | ||
847 | |||
848 | template<typename MotionDerived> | ||
849 | 513 | Force vxiv(const MotionDense<MotionDerived> & v) const | |
850 | { | ||
851 |
4/8✓ Branch 2 taken 513 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 513 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 513 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 513 times.
✗ Branch 13 not taken.
|
513 | const Vector3 & mcxw = mass() * lever().cross(v.angular()); |
852 |
4/8✓ Branch 1 taken 513 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 513 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 513 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 513 times.
✗ Branch 12 not taken.
|
513 | const Vector3 & mv_mcxw = mass() * v.linear() - mcxw; |
853 | return Force( | ||
854 |
1/2✓ Branch 1 taken 513 times.
✗ Branch 2 not taken.
|
513 | v.angular().cross(mv_mcxw), |
855 |
2/4✓ Branch 1 taken 513 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 513 times.
✗ Branch 5 not taken.
|
1026 | v.angular().cross(lever().cross(mv_mcxw) + inertia() * v.angular()) |
856 |
9/18✓ Branch 1 taken 513 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 513 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 513 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 513 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 513 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 513 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 513 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 513 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 513 times.
✗ Branch 26 not taken.
|
2052 | - v.linear().cross(mcxw)); |
857 | } | ||
858 | |||
859 | ✗ | void disp_impl(std::ostream & os) const | |
860 | { | ||
861 | ✗ | os << " m = " << mass() << "\n" | |
862 | ✗ | << " c = " << lever().transpose() << "\n" | |
863 | ✗ | << " I = \n" | |
864 | ✗ | << inertia().matrix() << ""; | |
865 | } | ||
866 | |||
867 | /// \returns An expression of *this with the Scalar type casted to NewScalar. | ||
868 | template<typename NewScalar> | ||
869 | 1146 | InertiaTpl<NewScalar, Options> cast() const | |
870 | { | ||
871 | return InertiaTpl<NewScalar, Options>( | ||
872 |
2/6✓ Branch 2 taken 1146 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1146 times.
✗ Branch 7 not taken.
|
1146 | pinocchio::cast<NewScalar>(mass()), lever().template cast<NewScalar>(), |
873 |
1/2✓ Branch 3 taken 1146 times.
✗ Branch 4 not taken.
|
3438 | inertia().template cast<NewScalar>()); |
874 | } | ||
875 | |||
876 | // TODO: adjust code | ||
877 | // /// \brief Check whether *this is a valid inertia, resulting from a positive mass | ||
878 | // distribution bool isValid() const | ||
879 | // { | ||
880 | // return | ||
881 | // (m_mass > Scalar(0) && m_inertia.isValid()) | ||
882 | // || (m_mass == Scalar(0) && (m_inertia.data().array() == Scalar(0)).all()); | ||
883 | // } | ||
884 | |||
885 | protected: | ||
886 | Scalar m_mass; | ||
887 | Vector3 m_com; | ||
888 | Symmetric3 m_inertia; | ||
889 | |||
890 | }; // class InertiaTpl | ||
891 | |||
892 | } // namespace pinocchio | ||
893 | |||
894 | #endif // ifndef __pinocchio_spatial_inertia_hpp__ | ||
895 |