5 #ifndef __pinocchio_spatial_symmetric3__
6 #define __pinocchio_spatial_symmetric3__
8 #include "pinocchio/spatial/fwd.hpp"
10 #include "pinocchio/math/matrix.hpp"
14 template<
typename _Scalar,
int _Options>
17 typedef _Scalar Scalar;
20 template<
typename _Scalar,
int _Options>
24 typedef _Scalar Scalar;
29 typedef Eigen::Matrix<Scalar, 3, 1, Options> Vector3;
30 typedef Eigen::Matrix<Scalar, 6, 1, Options> Vector6;
31 typedef Eigen::Matrix<Scalar, 3, 3, Options> Matrix3;
32 typedef Eigen::Matrix<Scalar, 2, 2, Options> Matrix2;
33 typedef Eigen::Matrix<Scalar, 3, 2, Options> Matrix32;
35 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
42 template<
typename Sc,
int Opt>
43 explicit Symmetric3Tpl(
const Eigen::Matrix<Sc, 3, 3, Opt> & I)
45 assert(check_expression_if_real<Scalar>(pinocchio::isZero((I - I.transpose()))));
64 template<
typename S2,
int O2>
67 *
this = other.template cast<Scalar>();
77 m_data = clone.m_data;
89 m_data << a0, a1, a2, a3, a4, a5;
92 static Symmetric3Tpl Zero()
94 return Symmetric3Tpl(Vector6::Zero());
101 static Symmetric3Tpl Random()
103 return RandomPositive();
107 Scalar a = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0,
108 b = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0,
109 c = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0,
110 d = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0,
111 e = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0,
112 f = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0;
114 m_data << a, b, c, d, e, f;
117 static Symmetric3Tpl Identity()
119 return Symmetric3Tpl(Scalar(1), Scalar(0), Scalar(1), Scalar(0), Scalar(0), Scalar(1));
123 m_data << Scalar(1), Scalar(0), Scalar(1), Scalar(0), Scalar(0), Scalar(1);
126 template<
typename Vector3Like>
127 void setDiagonal(
const Eigen::MatrixBase<Vector3Like> & diag)
129 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector3Like, 3);
136 bool operator==(
const Symmetric3Tpl & other)
const
138 return m_data == other.m_data;
141 bool operator!=(
const Symmetric3Tpl & other)
const
143 return !(*
this == other);
147 const Symmetric3Tpl & other,
148 const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision())
const
150 return m_data.isApprox(other.m_data, prec);
153 bool isZero(
const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision())
const
155 return m_data.isZero(prec);
158 void fill(
const Scalar value)
163 template<
typename Matrix3Like>
164 void inverse(
const Eigen::MatrixBase<Matrix3Like> & res_)
const
166 Matrix3Like & res = res_.const_cast_derived();
167 const Scalar &a11 = m_data[0], a21 = m_data[1], a22 = m_data[2], a31 = m_data[3],
168 a32 = m_data[4], a33 = m_data[5];
170 res(0, 0) = a33 * a22 - a32 * a32;
171 res(1, 0) = res(0, 1) = -(a33 * a21 - a32 * a31);
172 res(2, 0) = res(0, 2) = a32 * a21 - a22 * a31;
173 res(1, 1) = a33 * a11 - a31 * a31;
174 res(2, 1) = res(1, 2) = -(a32 * a11 - a21 * a31);
175 res(2, 2) = a22 * a11 - a21 * a21;
177 const Scalar det = a11 * res(0, 0) + a21 * res(0, 1) + a31 * res(0, 2);
181 Matrix3 inverse()
const
197 const Scalar &x = v[0], &y = v[1], &z = v[2];
198 return Symmetric3Tpl(-y * y - z * z, x * y, -x * x - z * z, x * z, y * z, -x * x - y * y);
204 const Scalar &x = v.v[0], &y = v.v[1], &z = v.v[2];
206 m_data[0] + y * y + z * z, m_data[1] - x * y, m_data[2] + x * x + z * z, m_data[3] - x * z,
207 m_data[4] - y * z, m_data[5] + x * x + y * y);
212 const Scalar &x = v.v[0], &y = v.v[1], &z = v.v[2];
213 m_data[0] += y * y + z * z;
215 m_data[2] += x * x + z * z;
218 m_data[5] += x * x + y * y;
240 const Scalar &x = v[0], &y = v[1], &z = v[2];
242 -m * (y * y + z * z), m * x * y, -m * (x * x + z * z), m * x * z, m * y * z,
243 -m * (x * x + y * y));
254 const Scalar &x = v.v[0], &y = v.v[1], &z = v.v[2];
256 m_data[0] + v.m * (y * y + z * z), m_data[1] - v.m * x * y,
257 m_data[2] + v.m * (x * x + z * z), m_data[3] - v.m * x * z, m_data[4] - v.m * y * z,
258 m_data[5] + v.m * (x * x + y * y));
261 Symmetric3Tpl & operator-=(
const AlphaSkewSquare & v)
263 const Scalar &x = v.v[0], &y = v.v[1], &z = v.v[2];
264 m_data[0] += v.m * (y * y + z * z);
265 m_data[1] -= v.m * x * y;
266 m_data[2] += v.m * (x * x + z * z);
267 m_data[3] -= v.m * x * z;
268 m_data[4] -= v.m * y * z;
269 m_data[5] += v.m * (x * x + y * y);
273 const Vector6 & data()
const
291 static Symmetric3Tpl RandomPositive()
293 Scalar a = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0,
294 b = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0,
295 c = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0,
296 d = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0,
297 e = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0,
298 f = Scalar(std::rand()) / RAND_MAX * 2.0 - 1.0;
299 return Symmetric3Tpl(
300 a * a + b * b + d * d, a * b + b * c + d * e, b * b + c * c + e * e, a * d + b * e + d * f,
301 b * d + c * e + e * f, d * d + e * e + f * f);
304 Matrix3 matrix()
const
307 res(0, 0) = m_data(0);
308 res(0, 1) = m_data(1);
309 res(0, 2) = m_data(3);
310 res(1, 0) = m_data(1);
311 res(1, 1) = m_data(2);
312 res(1, 2) = m_data(4);
313 res(2, 0) = m_data(3);
314 res(2, 1) = m_data(4);
315 res(2, 2) = m_data(5);
318 operator Matrix3()
const
323 Scalar vtiv(
const Vector3 & v)
const
325 const Scalar &
x = v[0];
326 const Scalar & y = v[1];
327 const Scalar & z = v[2];
329 const Scalar xx =
x *
x;
330 const Scalar xy =
x * y;
331 const Scalar xz =
x * z;
332 const Scalar yy = y * y;
333 const Scalar yz = y * z;
334 const Scalar zz = z * z;
336 return m_data(0) * xx + m_data(2) * yy + m_data(5) * zz
337 + 2. * (m_data(1) * xy + m_data(3) * xz + m_data(4) * yz);
350 template<
typename Vector3,
typename Matrix3>
352 const Eigen::MatrixBase<Vector3> & v,
354 const Eigen::MatrixBase<Matrix3> & M)
356 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector3, 3);
357 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix3, 3, 3);
359 const Scalar & a = S3.data()[0];
360 const Scalar & b = S3.data()[1];
361 const Scalar & c = S3.data()[2];
362 const Scalar & d = S3.data()[3];
363 const Scalar & e = S3.data()[4];
364 const Scalar & f = S3.data()[5];
366 const typename Vector3::RealScalar & v0 = v[0];
367 const typename Vector3::RealScalar & v1 = v[1];
368 const typename Vector3::RealScalar & v2 = v[2];
370 Matrix3 & M_ = PINOCCHIO_EIGEN_CONST_CAST(Matrix3, M);
371 M_(0, 0) = d * v1 - b * v2;
372 M_(1, 0) = a * v2 - d * v0;
373 M_(2, 0) = b * v0 - a * v1;
375 M_(0, 1) = e * v1 - c * v2;
376 M_(1, 1) = b * v2 - e * v0;
377 M_(2, 1) = c * v0 - b * v1;
379 M_(0, 2) = f * v1 - e * v2;
380 M_(1, 2) = d * v2 - f * v0;
381 M_(2, 2) = e * v0 - d * v1;
394 template<
typename Vector3>
395 Matrix3
vxs(
const Eigen::MatrixBase<Vector3> & v)
const
411 template<
typename Vector3,
typename Matrix3>
413 const Eigen::MatrixBase<Vector3> & v,
415 const Eigen::MatrixBase<Matrix3> & M)
417 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector3, 3);
418 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix3, 3, 3);
420 const Scalar & a = S3.data()[0];
421 const Scalar & b = S3.data()[1];
422 const Scalar & c = S3.data()[2];
423 const Scalar & d = S3.data()[3];
424 const Scalar & e = S3.data()[4];
425 const Scalar & f = S3.data()[5];
427 const typename Vector3::RealScalar & v0 = v[0];
428 const typename Vector3::RealScalar & v1 = v[1];
429 const typename Vector3::RealScalar & v2 = v[2];
431 Matrix3 & M_ = PINOCCHIO_EIGEN_CONST_CAST(Matrix3, M);
432 M_(0, 0) = b * v2 - d * v1;
433 M_(1, 0) = c * v2 - e * v1;
434 M_(2, 0) = e * v2 - f * v1;
436 M_(0, 1) = d * v0 - a * v2;
437 M_(1, 1) = e * v0 - b * v2;
438 M_(2, 1) = f * v0 - d * v2;
440 M_(0, 2) = a * v1 - b * v0;
441 M_(1, 2) = b * v1 - c * v0;
442 M_(2, 2) = d * v1 - e * v0;
453 template<
typename Vector3>
454 Matrix3
svx(
const Eigen::MatrixBase<Vector3> & v)
const
466 Symmetric3Tpl operator-(
const Symmetric3Tpl & s2)
const
468 return Symmetric3Tpl(m_data - s2.m_data);
471 Symmetric3Tpl & operator+=(
const Symmetric3Tpl & s2)
477 Symmetric3Tpl & operator-=(
const Symmetric3Tpl & s2)
483 Symmetric3Tpl & operator*=(
const Scalar s)
489 template<
typename V3in,
typename V3out>
491 const Symmetric3Tpl & S3,
492 const Eigen::MatrixBase<V3in> & vin,
493 const Eigen::MatrixBase<V3out> & vout)
495 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(V3in, Vector3);
496 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(V3out, Vector3);
498 V3out & vout_ = PINOCCHIO_EIGEN_CONST_CAST(V3out, vout);
500 vout_[0] = S3.m_data(0) * vin[0] + S3.m_data(1) * vin[1] + S3.m_data(3) * vin[2];
501 vout_[1] = S3.m_data(1) * vin[0] + S3.m_data(2) * vin[1] + S3.m_data(4) * vin[2];
502 vout_[2] = S3.m_data(3) * vin[0] + S3.m_data(4) * vin[1] + S3.m_data(5) * vin[2];
505 template<
typename V3>
506 Vector3 operator*(
const Eigen::MatrixBase<V3> & v)
const
509 rhsMult(*
this, v, res);
525 const Scalar & operator()(
const int i,
const int j)
const
527 return ((i != 2) && (j != 2)) ? m_data[i + j] : m_data[i + j + 1];
530 template<
typename Matrix3Like>
531 Symmetric3Tpl operator-(
const Eigen::MatrixBase<Matrix3Like> & S)
const
533 assert(check_expression_if_real<Scalar>(pinocchio::isZero(S - S.transpose())));
534 return Symmetric3Tpl(
535 m_data(0) - S(0, 0), m_data(1) - S(1, 0), m_data(2) - S(1, 1), m_data(3) - S(2, 0),
536 m_data(4) - S(2, 1), m_data(5) - S(2, 2));
539 template<
typename Matrix3Like>
540 Symmetric3Tpl operator+(
const Eigen::MatrixBase<Matrix3Like> & S)
const
542 assert(check_expression_if_real<Scalar>(pinocchio::isZero(S - S.transpose())));
543 return Symmetric3Tpl(
544 m_data(0) + S(0, 0), m_data(1) + S(1, 0), m_data(2) + S(1, 1), m_data(3) + S(2, 0),
545 m_data(4) + S(2, 1), m_data(5) + S(2, 2));
555 L << m_data(0) - m_data(5), m_data(1), m_data(1), m_data(2) - m_data(5), 2 * m_data(3),
556 m_data(4) + m_data(4);
564 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(D, 3, 3);
566 check_expression_if_real<Scalar>(
isUnitary(R.transpose() * R))
567 &&
"R is not a Unitary matrix");
575 const Matrix2 Y(R.template block<2, 3>(1, 0) * L);
578 Sres.m_data(1) = Y(0, 0) * R(0, 0) + Y(0, 1) * R(0, 1);
579 Sres.m_data(2) = Y(0, 0) * R(1, 0) + Y(0, 1) * R(1, 1);
580 Sres.m_data(3) = Y(1, 0) * R(0, 0) + Y(1, 1) * R(0, 1);
581 Sres.m_data(4) = Y(1, 0) * R(1, 0) + Y(1, 1) * R(1, 1);
582 Sres.m_data(5) = Y(1, 0) * R(2, 0) + Y(1, 1) * R(2, 1);
586 -R(0, 0) * m_data(4) + R(0, 1) * m_data(3), -R(1, 0) * m_data(4) + R(1, 1) * m_data(3),
587 -R(2, 0) * m_data(4) + R(2, 1) * m_data(3));
590 Sres.m_data(0) = L(0, 0) + L(1, 1) - Sres.m_data(2) - Sres.m_data(5);
593 Sres.m_data(0) += m_data(5);
594 Sres.m_data(1) += r(2);
595 Sres.m_data(2) += m_data(5);
596 Sres.m_data(3) -= r(1);
597 Sres.m_data(4) += r(0);
598 Sres.m_data(5) += m_data(5);
604 template<
typename NewScalar>
612 os <<
"m_data: " << S3.m_data.transpose() <<
"\n";
Symmetric3Tpl & operator=(const Symmetric3Tpl &clone)
Copy assignment operator.
Symmetric3Tpl< NewScalar, Options > cast() const
Matrix3 svx(const Eigen::MatrixBase< Vector3 > &v) const
Performs the operation .
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...
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...
Matrix32 decomposeltI() const
Computes L for a symmetric matrix A.
static void svx(const Eigen::MatrixBase< Vector3 > &v, const Symmetric3Tpl &S3, const Eigen::MatrixBase< Matrix3 > &M)
Performs the operation .
Main pinocchio namespace.
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.
Common traits structure to fully define base classes for CRTP.