pinocchio  1.2.6-7-g6de3e-dirty
inertia.hpp
1 //
2 // Copyright (c) 2015-2017 CNRS
3 // Copyright (c) 2016 Wandercraft, 86 rue de Paris 91400 Orsay, France.
4 //
5 // This file is part of Pinocchio
6 // Pinocchio is free software: you can redistribute it
7 // and/or modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation, either version
9 // 3 of the License, or (at your option) any later version.
10 //
11 // Pinocchio is distributed in the hope that it will be
12 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Lesser Public License for more details. You should have
15 // received a copy of the GNU Lesser General Public License along with
16 // Pinocchio If not, see
17 // <http://www.gnu.org/licenses/>.
18 
19 #ifndef __se3_inertia_hpp__
20 #define __se3_inertia_hpp__
21 
22 #include <Eigen/Core>
23 #include <iostream>
24 
25 #include "pinocchio/spatial/symmetric3.hpp"
26 #include "pinocchio/spatial/force.hpp"
27 #include "pinocchio/spatial/motion.hpp"
28 #include "pinocchio/spatial/skew.hpp"
29 
30 namespace se3
31 {
32 
33  template< class Derived>
35  {
36  protected:
37 
38  typedef Derived Derived_t;
39  SPATIAL_TYPEDEF_TEMPLATE(Derived_t);
40 
41  public:
42  Derived_t & derived() { return *static_cast<Derived_t*>(this); }
43  const Derived_t & derived() const { return *static_cast<const Derived_t*>(this); }
44 
45  Scalar mass() const { return static_cast<const Derived_t*>(this)->mass(); }
46  Scalar & mass() { return static_cast<const Derived_t*>(this)->mass(); }
47  const Vector3 & lever() const { return static_cast<const Derived_t*>(this)->lever(); }
48  Vector3 & lever() { return static_cast<const Derived_t*>(this)->lever(); }
49  const Symmetric3 & inertia() const { return static_cast<const Derived_t*>(this)->inertia(); }
50  Symmetric3 & inertia() { return static_cast<const Derived_t*>(this)->inertia(); }
51 
52  Matrix6 matrix() const { return derived().matrix_impl(); }
53  operator Matrix6 () const { return matrix(); }
54 
55  Derived_t& operator= (const Derived_t& clone){return derived().__equl__(clone);}
56  bool operator==(const Derived_t & other) const {return derived().isEqual(other);}
57  bool operator!=(const Derived_t & other) const { return !(*this == other); }
58 
59  Derived_t& operator+= (const Derived_t & Yb) { return derived().__pequ__(Yb); }
60  Derived_t operator+(const Derived_t & Yb) const { return derived().__plus__(Yb); }
61  Force operator*(const Motion & v) const { return derived().__mult__(v); }
62 
63  Scalar vtiv(const Motion & v) const { return derived().vtiv_impl(v); }
64  Matrix6 variation(const Motion & v) const { return derived().variation_impl(v); }
65 
66  void setZero() { derived().setZero(); }
67  void setIdentity() { derived().setIdentity(); }
68  void setRandom() { derived().setRandom(); }
69 
70  bool isApprox (const Derived & other, const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision()) const
71  { return derived().isApprox_impl(other, prec); }
72 
74  Derived_t se3Action(const SE3 & M) const { return derived().se3Action_impl(M); }
75 
77  Derived_t se3ActionInverse(const SE3 & M) const { return derived().se3ActionInverse_impl(M); }
78 
79  void disp(std::ostream & os) const { static_cast<const Derived_t*>(this)->disp_impl(os); }
80  friend std::ostream & operator << (std::ostream & os,const InertiaBase<Derived_t> & X)
81  {
82  X.disp(os);
83  return os;
84  }
85 
86  }; // class InertiaBase
87 
88 
89  template<typename T, int U>
90  struct traits< InertiaTpl<T, U> >
91  {
92  typedef T Scalar;
93  typedef Eigen::Matrix<T,3,1,U> Vector3;
94  typedef Eigen::Matrix<T,4,1,U> Vector4;
95  typedef Eigen::Matrix<T,6,1,U> Vector6;
96  typedef Eigen::Matrix<T,3,3,U> Matrix3;
97  typedef Eigen::Matrix<T,4,4,U> Matrix4;
98  typedef Eigen::Matrix<T,6,6,U> Matrix6;
99  typedef Matrix6 ActionMatrix_t;
100  typedef Vector3 Angular_t;
101  typedef Vector3 Linear_t;
102  typedef const Vector3 ConstAngular_t;
103  typedef const Vector3 ConstLinear_t;
104  typedef Eigen::Quaternion<T,U> Quaternion_t;
105  typedef SE3Tpl<T,U> SE3;
106  typedef ForceTpl<T,U> Force;
107  typedef MotionTpl<T,U> Motion;
109  enum {
110  LINEAR = 0,
111  ANGULAR = 3
112  };
113  }; // traits InertiaTpl
114 
115  template<typename _Scalar, int _Options>
116  class InertiaTpl : public InertiaBase< InertiaTpl< _Scalar, _Options > >
117  {
118  public:
119  friend class InertiaBase< InertiaTpl< _Scalar, _Options > >;
120  SPATIAL_TYPEDEF_TEMPLATE(InertiaTpl);
121  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
122 
123  typedef typename Symmetric3::AlphaSkewSquare AlphaSkewSquare;
124 
125  public:
126  // Constructors
127  InertiaTpl() : m(), c(), I() {}
128 
129  InertiaTpl(const Scalar m_, const Vector3 &c_, const Matrix3 &I_)
130  : m(m_), c(c_), I(I_)
131  {}
132 
133  InertiaTpl(const Matrix6 & I6)
134  {
135  assert((I6 - I6.transpose()).isMuchSmallerThan(I6));
136  m = I6(LINEAR, LINEAR);
137  const Matrix3 & mc_cross = I6.template block <3,3> (ANGULAR,LINEAR);
138  c = unSkew(mc_cross);
139  c /= m;
140 
141  Matrix3 I3 (mc_cross * mc_cross);
142  I3 /= m;
143  I3 += I6.template block<3,3>(ANGULAR,ANGULAR);
144  I = Symmetric3(I3);
145  }
146 
147  InertiaTpl(Scalar _m,
148  const Vector3 &_c,
149  const Symmetric3 &_I)
150  : m(_m),
151  c(_c),
152  I(_I)
153  {
154 
155  }
156  InertiaTpl(const InertiaTpl & clone) // Clone constructor for std::vector
157  : m(clone.m),
158  c(clone.c),
159  I(clone.I)
160  {
161 
162  }
163 
164  template<typename S2,int O2>
165  InertiaTpl( const InertiaTpl<S2,O2> & clone )
166  : m(clone.mass()),
167  c(clone.lever()),
168  I(clone.inertia().matrix())
169  {
170 
171  }
172 
173  // Initializers
174  static InertiaTpl Zero()
175  {
176  return InertiaTpl(0.,
177  Vector3::Zero(),
178  Symmetric3::Zero());
179  }
180 
181  void setZero() { m = 0.; c.setZero(); I.setZero(); }
182 
183  static InertiaTpl Identity()
184  {
185  return InertiaTpl(1.,
186  Vector3::Zero(),
187  Symmetric3::Identity());
188  }
189 
190  void setIdentity () { m = 1.; c.setZero(); I.setIdentity(); }
191 
192  static InertiaTpl Random()
193  {
194  // We have to shoot "I" definite positive and not only symmetric.
195  return InertiaTpl(Eigen::internal::random<Scalar>()+1,
196  Vector3::Random(),
197  Symmetric3::RandomPositive());
198  }
199 
200  static InertiaTpl FromEllipsoid(
201  const Scalar m, const Scalar x, const Scalar y, const Scalar z)
202  {
203  Scalar a = m * (y*y + z*z) / 5;
204  Scalar b = m * (x*x + z*z) / 5;
205  Scalar c = m * (y*y + x*x) / 5;
206  return InertiaTpl(m, Vector3::Zero(), Symmetric3(a, 0, b, 0, 0, c));
207  }
208 
209  static InertiaTpl FromCylinder(
210  const Scalar m, const Scalar r, const Scalar l)
211  {
212  Scalar a = m * (r*r / 4 + l*l / 12);
213  Scalar c = m * (r*r / 2);
214  return InertiaTpl(m, Vector3::Zero(), Symmetric3(a, 0, a, 0, 0, c));
215  }
216 
217  static InertiaTpl FromBox(
218  const Scalar m, const Scalar x, const Scalar y, const Scalar z)
219  {
220  Scalar a = m * (y*y + z*z) / 12;
221  Scalar b = m * (x*x + z*z) / 12;
222  Scalar c = m * (y*y + x*x) / 12;
223  return InertiaTpl(m, Vector3::Zero(), Symmetric3(a, 0, b, 0, 0, c));
224  }
225 
226 
227  void setRandom()
228  {
229  m = static_cast<Scalar> (std::rand()) / static_cast<Scalar> (RAND_MAX);
230  c.setRandom(); I.setRandom();
231  }
232 
233  Matrix6 matrix_impl() const
234  {
235  Matrix6 M;
236 
237  M.template block<3,3>(LINEAR, LINEAR ).setZero ();
238  M.template block<3,3>(LINEAR, LINEAR ).diagonal ().fill (m);
239  M.template block<3,3>(ANGULAR,LINEAR ) = alphaSkew(m,c);
240  M.template block<3,3>(LINEAR, ANGULAR) = -M.template block<3,3> (ANGULAR, LINEAR);
241  M.template block<3,3>(ANGULAR,ANGULAR) = (I - AlphaSkewSquare(m,c)).matrix();
242 
243  return M;
244  }
245 
246  // Arithmetic operators
247  InertiaTpl& __equl__ (const InertiaTpl& clone)
248  {
249  m=clone.m; c=clone.c; I=clone.I;
250  return *this;
251  }
252 
253  // Requiered by std::vector boost::python bindings.
254  bool isEqual( const InertiaTpl& Y2 ) const
255  {
256  return (m==Y2.m) && (c==Y2.c) && (I==Y2.I);
257  }
258 
259  bool isApprox_impl(const InertiaTpl & other, const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision()) const
260  {
261  using std::fabs;
262  return fabs(m - other.m) <= prec
263  && c.isApprox(other.c,prec)
264  && I.isApprox(other.I,prec);
265  }
266 
267  InertiaTpl __plus__(const InertiaTpl &Yb) const
268  {
269  /* Y_{a+b} = ( m_a+m_b,
270  * (m_a*c_a + m_b*c_b ) / (m_a + m_b),
271  * I_a + I_b - (m_a*m_b)/(m_a+m_b) * AB_x * AB_x )
272  */
273 
274  const double & mab = m+Yb.m;
275  const Vector3 & AB = (c-Yb.c).eval();
276  return InertiaTpl( mab,
277  (m*c+Yb.m*Yb.c)/mab,
278  I+Yb.I - (m*Yb.m/mab)* typename Symmetric3::SkewSquare(AB));
279  }
280 
281  InertiaTpl& __pequ__(const InertiaTpl &Yb)
282  {
283  const InertiaTpl& Ya = *this;
284  const double & mab = Ya.m+Yb.m;
285  const Vector3 & AB = (Ya.c-Yb.c).eval();
286  c *= m; c += Yb.m*Yb.c; c /= mab;
287  I += Yb.I; I -= (Ya.m*Yb.m/mab)* typename Symmetric3::SkewSquare(AB);
288  m = mab;
289  return *this;
290  }
291 
292  Force __mult__(const Motion &v) const
293  {
294  Force f;
295  f.linear() = m*(v.linear() - c.cross(v.angular()));
296  f.angular() = c.cross(f.linear()) + I*v.angular();
297  return f;
298  }
299 
300  Scalar vtiv_impl(const Motion & v) const
301  {
302  const Vector3 cxw (c.cross(v.angular()));
303  Scalar res = m * (v.linear().squaredNorm() - 2.*v.linear().dot(cxw));
304  const Vector3 mcxcxw (-m*c.cross(cxw));
305  res += v.angular().dot(mcxcxw);
306  res += I.vtiv(v.angular());
307 
308  return res;
309  }
310 
311  Matrix6 variation(const Motion & v) const
312  {
313  Matrix6 res;
314  const Motion mv(v*m);
315 
316  res.template block<3,3>(LINEAR,ANGULAR) = -skew(mv.linear()) - skewSquare(mv.angular(),c) + skewSquare(c,mv.angular());
317  res.template block<3,3>(ANGULAR,LINEAR) = res.template block<3,3>(LINEAR,ANGULAR).transpose();
318 
319  res.template block<3,3>(LINEAR,LINEAR) = mv.linear()*c.transpose(); // use as temporary variable
320  res.template block<3,3>(ANGULAR,ANGULAR) = res.template block<3,3>(LINEAR,LINEAR) - res.template block<3,3>(LINEAR,LINEAR).transpose();
321  res.template block<3,3>(ANGULAR,ANGULAR) = -skewSquare(mv.linear(),c) - skewSquare(c,mv.linear());
322 
323  res.template block<3,3>(LINEAR,LINEAR) = (I - AlphaSkewSquare(m,c)).matrix();
324 
325  res.template block<3,3>(ANGULAR,ANGULAR) -= res.template block<3,3>(LINEAR,LINEAR) * skew(v.angular());
326  res.template block<3,3>(ANGULAR,ANGULAR) += cross(v.angular(),res.template block<3,3>(LINEAR,LINEAR));
327 
328  res.template block<3,3>(LINEAR,LINEAR).setZero();
329  return res;
330  }
331 
332  // Getters
333  Scalar mass() const { return m; }
334  const Vector3 & lever() const { return c; }
335  const Symmetric3 & inertia() const { return I; }
336 
337  Scalar & mass() { return m; }
338  Vector3 & lever() { return c; }
339  Symmetric3 & inertia() { return I; }
340 
342  InertiaTpl se3Action_impl(const SE3 & M) const
343  {
344  /* The multiplication RIR' has a particular form that could be used, however it
345  * does not seems to be more efficient, see http://stackoverflow.com/questions/
346  * 13215467/eigen-best-way-to-evaluate-asa-transpose-and-store-the-result-in-a-symmetric .*/
347  return InertiaTpl( m,
348  M.translation()+M.rotation()*c,
349  I.rotate(M.rotation()) );
350  }
351 
353  InertiaTpl se3ActionInverse_impl(const SE3 & M) const
354  {
355  return InertiaTpl(m,
356  M.rotation().transpose()*(c-M.translation()),
357  I.rotate(M.rotation().transpose()) );
358  }
359 
360  Force vxiv( const Motion& v ) const
361  {
362  const Vector3 & mcxw = m*c.cross(v.angular());
363  const Vector3 & mv_mcxw = m*v.linear()-mcxw;
364  return Force( v.angular().cross(mv_mcxw),
365  v.angular().cross(c.cross(mv_mcxw)+I*v.angular())-v.linear().cross(mcxw) );
366  }
367 
368  void disp_impl(std::ostream & os) const
369  {
370  os << " m = " << m << "\n"
371  << " c = " << c.transpose() << "\n"
372  << " I = \n" << I.matrix() << "";
373  }
374 
375  protected:
376  Scalar m;
377  Vector3 c;
378  Symmetric3 I;
379 
380  }; // class InertiaTpl
381 
382 } // namespace se3
383 
384 #endif // ifndef __se3_inertia_hpp__
Concreate Class representing a force.
Definition: force.hpp:243
InertiaTpl se3Action_impl(const SE3 &M) const
aI = aXb.act(bI)
Definition: inertia.hpp:342
ConstAngular_t angular() const
Return the angular part of the force vector.
Definition: force.hpp:64
InertiaTpl se3ActionInverse_impl(const SE3 &M) const
bI = aXb.actInv(aI)
Definition: inertia.hpp:353
Derived_t se3ActionInverse(const SE3 &M) const
bI = aXb.actInv(aI)
Definition: inertia.hpp:77
ConstLinear_t linear() const
Return the linear part of the force vector.
Definition: force.hpp:71
Derived_t se3Action(const SE3 &M) const
aI = aXb.act(bI)
Definition: inertia.hpp:74