pinocchio  2.4.4
A fast and flexible implementation of Rigid Body Dynamics algorithms and their analytical derivatives
symmetric3.hpp
1 //
2 // Copyright (c) 2014-2019 CNRS INRIA
3 //
4 
5 #ifndef __pinocchio_symmetric3_hpp__
6 #define __pinocchio_symmetric3_hpp__
7 
8 #include "pinocchio/macros.hpp"
9 #include "pinocchio/math/matrix.hpp"
10 
11 namespace pinocchio
12 {
13 
14  template<typename _Scalar, int _Options>
15  class Symmetric3Tpl
16  {
17  public:
18  typedef _Scalar Scalar;
19  enum { Options = _Options };
20  typedef Eigen::Matrix<Scalar,3,1,Options> Vector3;
21  typedef Eigen::Matrix<Scalar,6,1,Options> Vector6;
22  typedef Eigen::Matrix<Scalar,3,3,Options> Matrix3;
23  typedef Eigen::Matrix<Scalar,2,2,Options> Matrix2;
24  typedef Eigen::Matrix<Scalar,3,2,Options> Matrix32;
25 
26  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
27 
28  public:
29  Symmetric3Tpl(): m_data() {}
30 
31  template<typename Sc,int N,int Opt>
32  explicit Symmetric3Tpl(const Eigen::Matrix<Sc,N,N,Opt> & I)
33  {
34  EIGEN_STATIC_ASSERT(N==3,THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE)
35  assert( (I-I.transpose()).isMuchSmallerThan(I) );
36  m_data(0) = I(0,0);
37  m_data(1) = I(1,0); m_data(2) = I(1,1);
38  m_data(3) = I(2,0); m_data(4) = I(2,1); m_data(5) = I(2,2);
39  }
40 
41  explicit Symmetric3Tpl(const Vector6 & I) : m_data(I) {}
42 
43  Symmetric3Tpl(const Scalar & a0, const Scalar & a1, const Scalar & a2,
44  const Scalar & a3, const Scalar & a4, const Scalar & a5)
45  { m_data << a0,a1,a2,a3,a4,a5; }
46 
47  static Symmetric3Tpl Zero() { return Symmetric3Tpl(Vector6::Zero()); }
48  void setZero() { m_data.setZero(); }
49 
50  static Symmetric3Tpl Random() { return RandomPositive(); }
51  void setRandom()
52  {
53  Scalar
54  a = Scalar(std::rand())/RAND_MAX*2.0-1.0,
55  b = Scalar(std::rand())/RAND_MAX*2.0-1.0,
56  c = Scalar(std::rand())/RAND_MAX*2.0-1.0,
57  d = Scalar(std::rand())/RAND_MAX*2.0-1.0,
58  e = Scalar(std::rand())/RAND_MAX*2.0-1.0,
59  f = Scalar(std::rand())/RAND_MAX*2.0-1.0;
60 
61  m_data << a, b, c, d, e, f;
62  }
63 
64  static Symmetric3Tpl Identity() { return Symmetric3Tpl(1, 0, 1, 0, 0, 1); }
65  void setIdentity() { m_data << 1, 0, 1, 0, 0, 1; }
66 
67  /* Required by Inertia::operator== */
68  bool operator==(const Symmetric3Tpl & other) const
69  { return m_data == other.m_data; }
70 
71  bool operator!=(const Symmetric3Tpl & other) const
72  { return !(*this == other); }
73 
74  bool isApprox(const Symmetric3Tpl & other,
75  const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision()) const
76  { return m_data.isApprox(other.m_data,prec); }
77 
78  bool isZero(const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision()) const
79  { return m_data.isZero(prec); }
80 
81  void fill(const Scalar value) { m_data.fill(value); }
82 
83  struct SkewSquare
84  {
85  const Vector3 & v;
86  SkewSquare( const Vector3 & v ) : v(v) {}
87  operator Symmetric3Tpl () const
88  {
89  const Scalar & x = v[0], & y = v[1], & z = v[2];
90  return Symmetric3Tpl( -y*y-z*z,
91  x*y , -x*x-z*z,
92  x*z , y*z , -x*x-y*y );
93  }
94  }; // struct SkewSquare
95 
96  Symmetric3Tpl operator- (const SkewSquare & v) const
97  {
98  const Scalar & x = v.v[0], & y = v.v[1], & z = v.v[2];
99  return Symmetric3Tpl(m_data[0]+y*y+z*z,
100  m_data[1]-x*y,m_data[2]+x*x+z*z,
101  m_data[3]-x*z,m_data[4]-y*z,m_data[5]+x*x+y*y);
102  }
103 
104  Symmetric3Tpl& operator-= (const SkewSquare & v)
105  {
106  const Scalar & x = v.v[0], & y = v.v[1], & z = v.v[2];
107  m_data[0]+=y*y+z*z;
108  m_data[1]-=x*y; m_data[2]+=x*x+z*z;
109  m_data[3]-=x*z; m_data[4]-=y*z; m_data[5]+=x*x+y*y;
110  return *this;
111  }
112 
113  template<typename D>
114  friend Matrix3 operator- (const Symmetric3Tpl & S, const Eigen::MatrixBase <D> & M)
115  {
116  EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(D,3,3);
117  Matrix3 result (S.matrix());
118  result -= M;
119 
120  return result;
121  }
122 
124  {
125  const Scalar & m;
126  const Vector3 & v;
127 
128  AlphaSkewSquare(const Scalar & m, const SkewSquare & v) : m(m),v(v.v) {}
129  AlphaSkewSquare(const Scalar & m, const Vector3 & v) : m(m),v(v) {}
130 
131  operator Symmetric3Tpl () const
132  {
133  const Scalar & x = v[0], & y = v[1], & z = v[2];
134  return Symmetric3Tpl(-m*(y*y+z*z),
135  m* x*y,-m*(x*x+z*z),
136  m* x*z,m* y*z,-m*(x*x+y*y));
137  }
138  };
139 
140  friend AlphaSkewSquare operator* (const Scalar & m, const SkewSquare & sk)
141  { return AlphaSkewSquare(m,sk); }
142 
143  Symmetric3Tpl operator- (const AlphaSkewSquare & v) const
144  {
145  const Scalar & x = v.v[0], & y = v.v[1], & z = v.v[2];
146  return Symmetric3Tpl(m_data[0]+v.m*(y*y+z*z),
147  m_data[1]-v.m* x*y, m_data[2]+v.m*(x*x+z*z),
148  m_data[3]-v.m* x*z, m_data[4]-v.m* y*z,
149  m_data[5]+v.m*(x*x+y*y));
150  }
151 
152  Symmetric3Tpl& operator-= (const AlphaSkewSquare & v)
153  {
154  const Scalar & x = v.v[0], & y = v.v[1], & z = v.v[2];
155  m_data[0]+=v.m*(y*y+z*z);
156  m_data[1]-=v.m* x*y; m_data[2]+=v.m*(x*x+z*z);
157  m_data[3]-=v.m* x*z; m_data[4]-=v.m* y*z; m_data[5]+=v.m*(x*x+y*y);
158  return *this;
159  }
160 
161  const Vector6 & data () const {return m_data;}
162  Vector6 & data () {return m_data;}
163 
164  // static Symmetric3Tpl SkewSq( const Vector3 & v )
165  // {
166  // const Scalar & x = v[0], & y = v[1], & z = v[2];
167  // return Symmetric3Tpl(-y*y-z*z,
168  // x*y, -x*x-z*z,
169  // x*z, y*z, -x*x-y*y );
170  // }
171 
172  /* Shoot a positive definite matrix. */
173  static Symmetric3Tpl RandomPositive()
174  {
175  Scalar
176  a = Scalar(std::rand())/RAND_MAX*2.0-1.0,
177  b = Scalar(std::rand())/RAND_MAX*2.0-1.0,
178  c = Scalar(std::rand())/RAND_MAX*2.0-1.0,
179  d = Scalar(std::rand())/RAND_MAX*2.0-1.0,
180  e = Scalar(std::rand())/RAND_MAX*2.0-1.0,
181  f = Scalar(std::rand())/RAND_MAX*2.0-1.0;
182  return Symmetric3Tpl(a*a+b*b+d*d,
183  a*b+b*c+d*e, b*b+c*c+e*e,
184  a*d+b*e+d*f, b*d+c*e+e*f, d*d+e*e+f*f );
185  }
186 
187  Matrix3 matrix() const
188  {
189  Matrix3 res;
190  res(0,0) = m_data(0); res(0,1) = m_data(1); res(0,2) = m_data(3);
191  res(1,0) = m_data(1); res(1,1) = m_data(2); res(1,2) = m_data(4);
192  res(2,0) = m_data(3); res(2,1) = m_data(4); res(2,2) = m_data(5);
193  return res;
194  }
195  operator Matrix3 () const { return matrix(); }
196 
197  Scalar vtiv (const Vector3 & v) const
198  {
199  const Scalar & x = v[0];
200  const Scalar & y = v[1];
201  const Scalar & z = v[2];
202 
203  const Scalar xx = x*x;
204  const Scalar xy = x*y;
205  const Scalar xz = x*z;
206  const Scalar yy = y*y;
207  const Scalar yz = y*z;
208  const Scalar zz = z*z;
209 
210  return m_data(0)*xx + m_data(2)*yy + m_data(5)*zz + 2.*(m_data(1)*xy + m_data(3)*xz + m_data(4)*yz);
211  }
212 
223  template<typename Vector3, typename Matrix3>
224  static void vxs(const Eigen::MatrixBase<Vector3> & v,
225  const Symmetric3Tpl & S3,
226  const Eigen::MatrixBase<Matrix3> & M)
227  {
228  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector3,3);
229  EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix3,3,3);
230 
231  const Scalar & a = S3.data()[0];
232  const Scalar & b = S3.data()[1];
233  const Scalar & c = S3.data()[2];
234  const Scalar & d = S3.data()[3];
235  const Scalar & e = S3.data()[4];
236  const Scalar & f = S3.data()[5];
237 
238 
239  const typename Vector3::RealScalar & v0 = v[0];
240  const typename Vector3::RealScalar & v1 = v[1];
241  const typename Vector3::RealScalar & v2 = v[2];
242 
243  Matrix3 & M_ = PINOCCHIO_EIGEN_CONST_CAST(Matrix3,M);
244  M_(0,0) = d * v1 - b * v2;
245  M_(1,0) = a * v2 - d * v0;
246  M_(2,0) = b * v0 - a * v1;
247 
248  M_(0,1) = e * v1 - c * v2;
249  M_(1,1) = b * v2 - e * v0;
250  M_(2,1) = c * v0 - b * v1;
251 
252  M_(0,2) = f * v1 - e * v2;
253  M_(1,2) = d * v2 - f * v0;
254  M_(2,2) = e * v0 - d * v1;
255  }
256 
267  template<typename Vector3>
268  Matrix3 vxs(const Eigen::MatrixBase<Vector3> & v) const
269  {
270  Matrix3 M;
271  vxs(v,*this,M);
272  return M;
273  }
274 
284  template<typename Vector3, typename Matrix3>
285  static void svx(const Eigen::MatrixBase<Vector3> & v,
286  const Symmetric3Tpl & S3,
287  const Eigen::MatrixBase<Matrix3> & M)
288  {
289  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector3,3);
290  EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix3,3,3);
291 
292  const Scalar & a = S3.data()[0];
293  const Scalar & b = S3.data()[1];
294  const Scalar & c = S3.data()[2];
295  const Scalar & d = S3.data()[3];
296  const Scalar & e = S3.data()[4];
297  const Scalar & f = S3.data()[5];
298 
299  const typename Vector3::RealScalar & v0 = v[0];
300  const typename Vector3::RealScalar & v1 = v[1];
301  const typename Vector3::RealScalar & v2 = v[2];
302 
303  Matrix3 & M_ = PINOCCHIO_EIGEN_CONST_CAST(Matrix3,M);
304  M_(0,0) = b * v2 - d * v1;
305  M_(1,0) = c * v2 - e * v1;
306  M_(2,0) = e * v2 - f * v1;
307 
308  M_(0,1) = d * v0 - a * v2;
309  M_(1,1) = e * v0 - b * v2;
310  M_(2,1) = f * v0 - d * v2;
311 
312  M_(0,2) = a * v1 - b * v0;
313  M_(1,2) = b * v1 - c * v0;
314  M_(2,2) = d * v1 - e * v0;
315  }
316 
325  template<typename Vector3>
326  Matrix3 svx(const Eigen::MatrixBase<Vector3> & v) const
327  {
328  Matrix3 M;
329  svx(v,*this,M);
330  return M;
331  }
332 
333  Symmetric3Tpl operator+(const Symmetric3Tpl & s2) const
334  {
335  return Symmetric3Tpl((m_data+s2.m_data).eval());
336  }
337 
338  Symmetric3Tpl & operator+=(const Symmetric3Tpl & s2)
339  {
340  m_data += s2.m_data; return *this;
341  }
342 
343  template<typename V3in, typename V3out>
344  static void rhsMult(const Symmetric3Tpl & S3,
345  const Eigen::MatrixBase<V3in> & vin,
346  const Eigen::MatrixBase<V3out> & vout)
347  {
348  EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(V3in,Vector3);
349  EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(V3out,Vector3);
350 
351  V3out & vout_ = PINOCCHIO_EIGEN_CONST_CAST(V3out,vout);
352 
353  vout_[0] = S3.m_data(0) * vin[0] + S3.m_data(1) * vin[1] + S3.m_data(3) * vin[2];
354  vout_[1] = S3.m_data(1) * vin[0] + S3.m_data(2) * vin[1] + S3.m_data(4) * vin[2];
355  vout_[2] = S3.m_data(3) * vin[0] + S3.m_data(4) * vin[1] + S3.m_data(5) * vin[2];
356  }
357 
358  template<typename V3>
359  Vector3 operator*(const Eigen::MatrixBase<V3> & v) const
360  {
361  Vector3 res;
362  rhsMult(*this,v,res);
363  return res;
364  }
365 
366  // Matrix3 operator*(const Matrix3 &a) const
367  // {
368  // Matrix3 r;
369  // for(unsigned int i=0; i<3; ++i)
370  // {
371  // r(0,i) = m_data(0) * a(0,i) + m_data(1) * a(1,i) + m_data(3) * a(2,i);
372  // r(1,i) = m_data(1) * a(0,i) + m_data(2) * a(1,i) + m_data(4) * a(2,i);
373  // r(2,i) = m_data(3) * a(0,i) + m_data(4) * a(1,i) + m_data(5) * a(2,i);
374  // }
375  // return r;
376  // }
377 
378  const Scalar& operator()(const int &i,const int &j) const
379  {
380  return ((i!=2)&&(j!=2)) ? m_data[i+j] : m_data[i+j+1];
381  }
382 
383  Symmetric3Tpl operator-(const Matrix3 &S) const
384  {
385  assert( (S-S.transpose()).isMuchSmallerThan(S) );
386  return Symmetric3Tpl( m_data(0)-S(0,0),
387  m_data(1)-S(1,0), m_data(2)-S(1,1),
388  m_data(3)-S(2,0), m_data(4)-S(2,1), m_data(5)-S(2,2) );
389  }
390 
391  Symmetric3Tpl operator+(const Matrix3 &S) const
392  {
393  assert( (S-S.transpose()).isMuchSmallerThan(S) );
394  return Symmetric3Tpl( m_data(0)+S(0,0),
395  m_data(1)+S(1,0), m_data(2)+S(1,1),
396  m_data(3)+S(2,0), m_data(4)+S(2,1), m_data(5)+S(2,2) );
397  }
398 
399  /* --- Symmetric R*S*R' and R'*S*R products --- */
400  public: //private:
401 
404  Matrix32 decomposeltI() const
405  {
406  Matrix32 L;
407  L <<
408  m_data(0) - m_data(5), m_data(1),
409  m_data(1), m_data(2) - m_data(5),
410  2*m_data(3), m_data(4) + m_data(4);
411  return L;
412  }
413 
414  /* R*S*R' */
415  template<typename D>
416  Symmetric3Tpl rotate(const Eigen::MatrixBase<D> & R) const
417  {
418  EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(D,3,3);
419  assert(isUnitary(R.transpose()*R) && "R is not a Unitary matrix");
420 
421  Symmetric3Tpl Sres;
422 
423  // 4 a
424  const Matrix32 L( decomposeltI() );
425 
426  // Y = R' L ===> (12 m + 8 a)
427  const Matrix2 Y( R.template block<2,3>(1,0) * L );
428 
429  // Sres= Y R ===> (16 m + 8a)
430  Sres.m_data(1) = Y(0,0)*R(0,0) + Y(0,1)*R(0,1);
431  Sres.m_data(2) = Y(0,0)*R(1,0) + Y(0,1)*R(1,1);
432  Sres.m_data(3) = Y(1,0)*R(0,0) + Y(1,1)*R(0,1);
433  Sres.m_data(4) = Y(1,0)*R(1,0) + Y(1,1)*R(1,1);
434  Sres.m_data(5) = Y(1,0)*R(2,0) + Y(1,1)*R(2,1);
435 
436  // r=R' v ( 6m + 3a)
437  const Vector3 r(-R(0,0)*m_data(4) + R(0,1)*m_data(3),
438  -R(1,0)*m_data(4) + R(1,1)*m_data(3),
439  -R(2,0)*m_data(4) + R(2,1)*m_data(3));
440 
441  // Sres_11 (3a)
442  Sres.m_data(0) = L(0,0) + L(1,1) - Sres.m_data(2) - Sres.m_data(5);
443 
444  // Sres + D + (Ev)x ( 9a)
445  Sres.m_data(0) += m_data(5);
446  Sres.m_data(1) += r(2); Sres.m_data(2)+= m_data(5);
447  Sres.m_data(3) +=-r(1); Sres.m_data(4)+= r(0); Sres.m_data(5) += m_data(5);
448 
449  return Sres;
450  }
451 
453  template<typename NewScalar>
455  {
456  return Symmetric3Tpl<NewScalar,Options>(m_data.template cast<NewScalar>());
457  }
458 
459  protected:
460  Vector6 m_data;
461 
462  };
463 
464 } // namespace pinocchio
465 
466 #endif // ifndef __pinocchio_symmetric3_hpp__
467 
Matrix32 decomposeltI() const
Computes L for a symmetric matrix A.
Definition: symmetric3.hpp:404
bool isUnitary(const Eigen::MatrixBase< MatrixLike > &mat, const typename MatrixLike::RealScalar &prec=Eigen::NumTraits< typename MatrixLike::Scalar >::dummy_precision())
Check whether the input matrix is Unitary within the given precision.
Definition: matrix.hpp:100
Matrix3 vxs(const Eigen::MatrixBase< Vector3 > &v) const
Performs the operation . This operation is equivalent to applying the cross product of v on each colu...
Definition: symmetric3.hpp:268
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...
Definition: symmetric3.hpp:224
Main pinocchio namespace.
Definition: treeview.dox:24
static void svx(const Eigen::MatrixBase< Vector3 > &v, const Symmetric3Tpl &S3, const Eigen::MatrixBase< Matrix3 > &M)
Performs the operation .
Definition: symmetric3.hpp:285
Matrix3 svx(const Eigen::MatrixBase< Vector3 > &v) const
Performs the operation .
Definition: symmetric3.hpp:326
Symmetric3Tpl< NewScalar, Options > cast() const
Definition: symmetric3.hpp:454
MultiplicationOp< InertiaTpl< Scalar, Options >, ConstraintDerived >::ReturnType operator*(const InertiaTpl< Scalar, Options > &Y, const ConstraintBase< ConstraintDerived > &constraint)
 .