6 #ifndef __pinocchio_inertia_hpp__ 7 #define __pinocchio_inertia_hpp__ 11 #include "pinocchio/math/fwd.hpp" 12 #include "pinocchio/spatial/symmetric3.hpp" 13 #include "pinocchio/spatial/force.hpp" 14 #include "pinocchio/spatial/motion.hpp" 15 #include "pinocchio/spatial/skew.hpp" 20 template<
class Derived>
25 typedef Derived Derived_t;
26 SPATIAL_TYPEDEF_TEMPLATE(Derived_t);
29 Derived_t & derived() {
return *
static_cast<Derived_t*
>(
this); }
30 const Derived_t & derived()
const {
return *
static_cast<const Derived_t*
>(
this); }
32 Scalar mass()
const {
return static_cast<const Derived_t*
>(
this)->mass(); }
33 Scalar & mass() {
return static_cast<const Derived_t*
>(
this)->mass(); }
34 const Vector3 & lever()
const {
return static_cast<const Derived_t*
>(
this)->lever(); }
35 Vector3 & lever() {
return static_cast<const Derived_t*
>(
this)->lever(); }
36 const Symmetric3 & inertia()
const {
return static_cast<const Derived_t*
>(
this)->inertia(); }
37 Symmetric3 & inertia() {
return static_cast<const Derived_t*
>(
this)->inertia(); }
39 Matrix6 matrix()
const {
return derived().matrix_impl(); }
40 operator Matrix6 ()
const {
return matrix(); }
42 Derived_t& operator= (
const Derived_t& clone){
return derived().__equl__(clone);}
43 bool operator==(
const Derived_t & other)
const {
return derived().isEqual(other);}
44 bool operator!=(
const Derived_t & other)
const {
return !(*
this == other); }
46 Derived_t& operator+= (
const Derived_t & Yb) {
return derived().__pequ__(Yb); }
47 Derived_t operator+(
const Derived_t & Yb)
const {
return derived().__plus__(Yb); }
49 template<
typename MotionDerived>
52 {
return derived().__mult__(v); }
54 Scalar vtiv(
const Motion & v)
const {
return derived().vtiv_impl(v); }
55 Matrix6 variation(
const Motion & v)
const {
return derived().variation_impl(v); }
65 static void vxi(
const Motion & v,
const Derived & I,
const Eigen::MatrixBase<M6> & Iout)
67 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(M6, Matrix6);
68 Derived::vxi_impl(v,I,Iout);
74 vxi(v,derived(),Iout);
86 static void ivx(
const Motion & v,
const Derived & I,
const Eigen::MatrixBase<M6> & Iout)
88 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(M6, Matrix6);
89 Derived::ivx_impl(v,I,Iout);
95 ivx(v,derived(),Iout);
99 void setZero() { derived().setZero(); }
100 void setIdentity() { derived().setIdentity(); }
101 void setRandom() { derived().setRandom(); }
103 bool isApprox (
const Derived & other,
const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision())
const 104 {
return derived().isApprox_impl(other, prec); }
107 Derived_t
se3Action(
const SE3 & M)
const {
return derived().se3Action_impl(M); }
112 void disp(std::ostream & os)
const {
static_cast<const Derived_t*
>(
this)->disp_impl(os); }
113 friend std::ostream & operator << (std::ostream & os,const InertiaBase<Derived_t> & X)
122 template<
typename T,
int U>
126 typedef Eigen::Matrix<T,3,1,U> Vector3;
127 typedef Eigen::Matrix<T,4,1,U> Vector4;
128 typedef Eigen::Matrix<T,6,1,U> Vector6;
129 typedef Eigen::Matrix<T,3,3,U> Matrix3;
130 typedef Eigen::Matrix<T,4,4,U> Matrix4;
131 typedef Eigen::Matrix<T,6,6,U> Matrix6;
132 typedef Matrix6 ActionMatrix_t;
133 typedef Vector3 Angular_t;
134 typedef Vector3 Linear_t;
135 typedef const Vector3 ConstAngular_t;
136 typedef const Vector3 ConstLinear_t;
137 typedef Eigen::Quaternion<T,U> Quaternion_t;
148 template<
typename _Scalar,
int _Options>
152 friend class InertiaBase< InertiaTpl< _Scalar, _Options > >;
153 SPATIAL_TYPEDEF_TEMPLATE(InertiaTpl);
154 enum { Options = _Options };
155 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
164 InertiaTpl(
const Scalar mass,
const Vector3 & com,
const Matrix3 & rotational_inertia)
165 : m_mass(mass), m_com(com), m_inertia(rotational_inertia)
168 InertiaTpl(
const Matrix6 & I6)
170 assert((I6 - I6.transpose()).isMuchSmallerThan(I6));
171 mass() = I6(LINEAR, LINEAR);
172 const Matrix3 & mc_cross = I6.template block <3,3> (ANGULAR,LINEAR);
173 lever() =
unSkew(mc_cross);
176 Matrix3 I3 (mc_cross * mc_cross);
178 I3 += I6.template block<3,3>(ANGULAR,ANGULAR);
182 InertiaTpl(Scalar mass,
const Vector3 & com,
const Symmetric3 & rotational_inertia)
183 : m_mass(mass), m_com(com), m_inertia(rotational_inertia)
186 InertiaTpl(
const InertiaTpl & clone)
187 : m_mass(clone.mass()), m_com(clone.lever()), m_inertia(clone.inertia())
192 : m_mass(clone.mass())
193 , m_com(clone.lever())
194 , m_inertia(clone.inertia().matrix())
198 static InertiaTpl Zero()
200 return InertiaTpl(0.,
205 void setZero() { mass() = 0.; lever().setZero(); inertia().setZero(); }
207 static InertiaTpl Identity()
209 return InertiaTpl(1.,
211 Symmetric3::Identity());
214 void setIdentity () { mass() = 1.; lever().setZero(); inertia().setIdentity(); }
216 static InertiaTpl Random()
219 return InertiaTpl(Eigen::internal::random<Scalar>()+1,
221 Symmetric3::RandomPositive());
224 static InertiaTpl FromEllipsoid(
225 const Scalar m,
const Scalar x,
const Scalar y,
const Scalar z)
227 Scalar a = m * (y*y + z*z) / 5;
228 Scalar b = m * (x*x + z*z) / 5;
229 Scalar c = m * (y*y + x*x) / 5;
230 return InertiaTpl(m, Vector3::Zero(),
Symmetric3(a, 0, b, 0, 0, c));
233 static InertiaTpl FromCylinder(
234 const Scalar m,
const Scalar r,
const Scalar l)
236 Scalar a = m * (r*r / 4 + l*l / 12);
237 Scalar c = m * (r*r / 2);
238 return InertiaTpl(m, Vector3::Zero(),
Symmetric3(a, 0, a, 0, 0, c));
241 static InertiaTpl FromBox(
242 const Scalar m,
const Scalar x,
const Scalar y,
const Scalar z)
244 Scalar a = m * (y*y + z*z) / 12;
245 Scalar b = m * (x*x + z*z) / 12;
246 Scalar c = m * (y*y + x*x) / 12;
247 return InertiaTpl(m, Vector3::Zero(),
Symmetric3(a, 0, b, 0, 0, c));
252 mass() =
static_cast<Scalar
>(std::rand())/static_cast<Scalar>(RAND_MAX);
253 lever().setRandom(); inertia().setRandom();
256 Matrix6 matrix_impl()
const 260 M.template block<3,3>(LINEAR, LINEAR ).setZero();
261 M.template block<3,3>(LINEAR, LINEAR ).diagonal().fill (mass());
262 M.template block<3,3>(ANGULAR,LINEAR ) =
alphaSkew(mass(),lever());
263 M.template block<3,3>(LINEAR, ANGULAR) = -M.template block<3,3>(ANGULAR, LINEAR);
264 M.template block<3,3>(ANGULAR,ANGULAR) = (inertia() - AlphaSkewSquare(mass(),lever())).matrix();
270 InertiaTpl & __equl__(
const InertiaTpl & clone)
272 mass()=clone.mass(); lever()=clone.lever(); inertia()=clone.inertia();
277 bool isEqual(
const InertiaTpl& Y2 )
const 279 return (mass()==Y2.mass()) && (lever()==Y2.lever()) && (inertia()==Y2.inertia());
282 bool isApprox_impl(
const InertiaTpl & other,
const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision())
const 285 return fabs(mass() - other.mass()) <= prec
286 && lever().isApprox(other.lever(),prec)
287 && inertia().isApprox(other.inertia(),prec);
290 InertiaTpl __plus__(
const InertiaTpl & Yb)
const 297 const Scalar & mab = mass()+Yb.mass();
298 const Scalar mab_inv = 1./mab;
299 const Vector3 & AB = (lever()-Yb.lever()).eval();
300 return InertiaTpl(mab,
301 (mass()*lever()+Yb.mass()*Yb.lever())*mab_inv,
305 InertiaTpl& __pequ__(
const InertiaTpl & Yb)
307 const InertiaTpl& Ya = *
this;
308 const Scalar & mab = Ya.mass()+Yb.mass();
309 const Scalar mab_inv = 1./mab;
310 const Vector3 & AB = (Ya.lever()-Yb.lever()).eval();
311 lever() *= (mass()*mab_inv); lever() += (Yb.mass()*mab_inv)*Yb.lever();
312 inertia() += Yb.inertia(); inertia() -= (Ya.mass()*Yb.mass()*mab_inv)*
typename Symmetric3::SkewSquare(AB);
317 template<
typename MotionDerived>
327 template<
typename MotionDerived,
typename ForceDerived>
330 f.
linear().noalias() = mass()*(v.linear() - lever().cross(v.angular()));
331 Symmetric3::rhsMult(inertia(),v.angular(),f.
angular());
336 Scalar vtiv_impl(
const Motion & v)
const 338 const Vector3 cxw (lever().
cross(v.angular()));
339 Scalar res = mass() * (v.linear().squaredNorm() - 2.*v.linear().dot(cxw));
340 const Vector3 mcxcxw (-mass()*lever().
cross(cxw));
341 res += v.angular().dot(mcxcxw);
342 res += inertia().vtiv(v.angular());
347 Matrix6 variation(
const Motion & v)
const 350 const Motion mv(v*mass());
352 res.template block<3,3>(LINEAR,ANGULAR) = -
skew(mv.linear()) -
skewSquare(mv.angular(),lever()) +
skewSquare(lever(),mv.angular());
353 res.template block<3,3>(ANGULAR,LINEAR) = res.template block<3,3>(LINEAR,ANGULAR).transpose();
357 res.template block<3,3>(ANGULAR,ANGULAR) = -
skewSquare(mv.linear(),lever()) -
skewSquare(lever(),mv.linear());
359 res.template block<3,3>(LINEAR,LINEAR) = (inertia() - AlphaSkewSquare(mass(),lever())).matrix();
361 res.template block<3,3>(ANGULAR,ANGULAR) -= res.template block<3,3>(LINEAR,LINEAR) *
skew(v.angular());
362 res.template block<3,3>(ANGULAR,ANGULAR) +=
cross(v.angular(),res.template block<3,3>(LINEAR,LINEAR));
364 res.template block<3,3>(LINEAR,LINEAR).setZero();
368 template<
typename M6>
369 static void vxi_impl(
const Motion & v,
const InertiaTpl & I,
const Eigen::MatrixBase<M6> & Iout)
371 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(M6,6,6);
372 M6 & Iout_ =
const_cast<Eigen::MatrixBase<M6> &
>(Iout).derived();
375 alphaSkew(I.mass(),v.angular(),Iout_.template block<3,3>(LINEAR,LINEAR));
377 const Vector3 mc(I.mass()*I.lever());
380 skewSquare(-v.angular(),mc,Iout_.template block<3,3>(LINEAR,ANGULAR));
384 alphaSkew(I.mass(),v.linear(),Iout_.template block<3,3>(ANGULAR,LINEAR));
385 Iout_.template block<3,3>(ANGULAR,LINEAR) -= Iout_.template block<3,3>(LINEAR,ANGULAR);
388 skewSquare(-v.linear(),mc,Iout_.template block<3,3>(ANGULAR,ANGULAR));
396 Iout_.template block<3,3>(ANGULAR,ANGULAR) += I.inertia().
vxs(v.angular());
397 Iout_.template block<3,3>(ANGULAR,ANGULAR) -= mcxcx.
vxs(v.angular());
401 template<
typename M6>
402 static void ivx_impl(
const Motion & v,
const InertiaTpl & I,
const Eigen::MatrixBase<M6> & Iout)
404 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(M6,6,6);
405 M6 & Iout_ =
const_cast<Eigen::MatrixBase<M6> &
>(Iout).derived();
408 alphaSkew(I.mass(),v.angular(),Iout_.template block<3,3>(LINEAR,LINEAR));
411 const Vector3 mc(I.mass()*I.lever());
412 skewSquare(mc,v.angular(),Iout_.template block<3,3>(ANGULAR,LINEAR));
415 alphaSkew(I.mass(),v.linear(),Iout_.template block<3,3>(LINEAR,ANGULAR));
418 cross(-I.lever(),Iout_.template block<3,3>(ANGULAR,LINEAR),Iout_.template block<3,3>(ANGULAR,ANGULAR));
419 Iout_.template block<3,3>(ANGULAR,ANGULAR) += I.inertia().
svx(v.angular());
420 for(
int k = 0; k < 3; ++k)
421 Iout_.template block<3,3>(ANGULAR,ANGULAR).col(k) += I.lever().cross(Iout_.template block<3,3>(LINEAR,ANGULAR).col(k));
424 Iout_.template block<3,3>(LINEAR,ANGULAR) -= Iout_.template block<3,3>(ANGULAR,LINEAR);
429 Scalar mass()
const {
return m_mass; }
430 const Vector3 & lever()
const {
return m_com; }
431 const Symmetric3 & inertia()
const {
return m_inertia; }
433 Scalar & mass() {
return m_mass; }
434 Vector3 & lever() {
return m_com; }
443 return InertiaTpl(mass(),
444 M.translation()+M.rotation()*lever(),
445 inertia().rotate(M.rotation()));
451 return InertiaTpl(mass(),
452 M.rotation().transpose()*(lever()-M.translation()),
453 inertia().rotate(M.rotation().transpose()) );
458 const Vector3 & mcxw = mass()*lever().cross(v.angular());
459 const Vector3 & mv_mcxw = mass()*v.linear()-mcxw;
460 return Force( v.angular().cross(mv_mcxw),
461 v.angular().cross(lever().
cross(mv_mcxw)+inertia()*v.angular())-v.linear().cross(mcxw) );
464 void disp_impl(std::ostream & os)
const 467 <<
" m = " << mass() <<
"\n" 468 <<
" c = " << lever().transpose() <<
"\n" 469 <<
" I = \n" << inertia().matrix() <<
"";
473 template<
typename NewScalar>
477 lever().template cast<NewScalar>(),
478 inertia().template cast<NewScalar>());
490 #endif // ifndef __pinocchio_inertia_hpp__ void unSkew(const Eigen::MatrixBase< Matrix3 > &M, const Eigen::MatrixBase< Vector3 > &v)
Inverse of skew operator. From a given skew-symmetric matrix M of dimension 3x3, it extracts the supp...
Derived_t se3Action(const SE3 &M) const
aI = aXb.act(bI)
InertiaTpl< NewScalar, Options > cast() const
static void vxi(const Motion &v, const Derived &I, const Eigen::MatrixBase< M6 > &Iout)
Time variation operator. It computes the time derivative of an inertia I corresponding to the formula...
InertiaTpl se3ActionInverse_impl(const SE3 &M) const
bI = aXb.actInv(aI)
static void ivx(const Motion &v, const Derived &I, const Eigen::MatrixBase< M6 > &Iout)
Time variation operator. It computes the time derivative of an inertia I corresponding to the formula...
void cross(const Eigen::MatrixBase< Vector3 > &v, const Eigen::MatrixBase< Matrix3xIn > &Min, const Eigen::MatrixBase< Matrix3xOut > &Mout)
Applies the cross product onto the columns of M.
ConstAngularType angular() const
Return the angular part of the force vector.
static void vxs(const Eigen::MatrixBase< Vector3 > &v, const Symmetric3Tpl &S3, const Eigen::MatrixBase< Matrix3 > &M)
Performs the operation . This operation is equivalent to applying the cross product of v on each colu...
void skewSquare(const Eigen::MatrixBase< V1 > &u, const Eigen::MatrixBase< V2 > &v, const Eigen::MatrixBase< Matrix3 > &C)
Computes the square cross product linear operator C(u,v) such that for any vector w...
Main pinocchio namespace.
static void svx(const Eigen::MatrixBase< Vector3 > &v, const Symmetric3Tpl &S3, const Eigen::MatrixBase< Matrix3 > &M)
Performs the operation .
InertiaTpl se3Action_impl(const SE3 &M) const
aI = aXb.act(bI)
void alphaSkew(const Scalar alpha, const Eigen::MatrixBase< Vector3 > &v, const Eigen::MatrixBase< Matrix3 > &M)
Computes the skew representation of a given 3d vector multiplied by a given scalar. i.e. the antisymmetric matrix representation of the cross product operator ( )
Common traits structure to fully define base classes for CRTP.
Derived_t se3ActionInverse(const SE3 &M) const
bI = aXb.actInv(aI)
void skew(const Eigen::MatrixBase< Vector3 > &v, const Eigen::MatrixBase< Matrix3 > &M)
Computes the skew representation of a given 3d vector, i.e. the antisymmetric matrix representation o...
ConstLinearType linear() const
Return the linear part of the force vector.