pinocchio  2.1.3
explog-quaternion.hpp
1 //
2 // Copyright (c) 2018 CNRS, INRIA
3 //
4 
5 #ifndef __pinocchio_spatial_explog_quaternion_hpp__
6 #define __pinocchio_spatial_explog_quaternion_hpp__
7 
8 #include "pinocchio/math/quaternion.hpp"
9 
10 namespace pinocchio
11 {
12  namespace quaternion
13  {
14 
23  template<typename Vector3Like, typename QuaternionLike>
24  void exp3(const Eigen::MatrixBase<Vector3Like> & v,
25  Eigen::QuaternionBase<QuaternionLike> & quat_out)
26  {
27  EIGEN_STATIC_ASSERT_VECTOR_ONLY(Vector3Like);
28  assert(v.size() == 3);
29 
30  typedef typename Vector3Like::Scalar Scalar;
31 
32  const Scalar t2 = v.squaredNorm();
33 
34  static const Scalar ts_prec = math::sqrt(Eigen::NumTraits<Scalar>::epsilon()); // Precision for the Taylor series expansion.
35  if(t2 > ts_prec)
36  {
37  const Scalar t = math::sqrt(t2);
38  Eigen::AngleAxis<Scalar> aa(t,v/t);
39  quat_out = aa;
40  }
41  else
42  {
43  quat_out.vec().noalias() = (Scalar(1)/Scalar(2) - t2/48) * v;
44  quat_out.w() = Scalar(1) - t2/8;
45  }
46 
47  }
48 
56  template<typename Vector3Like>
57  Eigen::Quaternion<typename Vector3Like::Scalar, PINOCCHIO_EIGEN_PLAIN_TYPE(Vector3Like)::Options>
58  exp3(const Eigen::MatrixBase<Vector3Like> & v)
59  {
60  typedef Eigen::Quaternion<typename Vector3Like::Scalar, PINOCCHIO_EIGEN_PLAIN_TYPE(Vector3Like)::Options> ReturnType;
61  ReturnType res; exp3(v,res);
62  return res;
63  }
64 
73  template<typename QuaternionLike>
74  Eigen::Matrix<typename QuaternionLike::Scalar,3,1,PINOCCHIO_EIGEN_PLAIN_TYPE(typename QuaternionLike::Vector3)::Options>
75  log3(const Eigen::QuaternionBase<QuaternionLike> & quat,
76  typename QuaternionLike::Scalar & theta)
77  {
78  typedef typename QuaternionLike::Scalar Scalar;
79  typedef Eigen::Matrix<Scalar,3,1,PINOCCHIO_EIGEN_PLAIN_TYPE(typename QuaternionLike::Vector3)::Options> Vector3;
80 
81  Vector3 res;
82  const Scalar norm_squared = quat.vec().squaredNorm();
83  const Scalar norm = math::sqrt(norm_squared);
84  static const Scalar ts_prec = math::sqrt(Eigen::NumTraits<Scalar>::epsilon());
85  if(norm_squared < ts_prec)
86  {
87  const Scalar y_x = norm / quat.w();
88  theta = (1 - y_x * y_x / 3) * y_x;
89  res.noalias() = (Scalar(1) + norm_squared / (6 * quat.w() * quat.w())) * quat.vec();
90  }
91  else
92  {
93  static const Scalar PI_value = PI<Scalar>();
94  Scalar theta_2;
95  // Here, y is always positive
96  if(quat.w() >= 0.) // x >= 0. in atan2(y,x)
97  {
98  theta_2 = math::atan2(norm,quat.w());
99  theta = 2.*theta_2;
100  res.noalias() = (theta / math::sin(theta_2)) * quat.vec();
101  }
102  else
103  { // We take here the oposite as we want to have theta in [-pi;pi];
104  theta_2 = PI_value - math::atan2(norm,quat.w());
105  theta = 2.*theta_2;
106  res.noalias() = -(theta / math::sin(theta_2)) * quat.vec();
107  }
108  }
109 
110  return res;
111  }
112 
122  template<typename QuaternionLike>
123  Eigen::Matrix<typename QuaternionLike::Scalar,3,1,PINOCCHIO_EIGEN_PLAIN_TYPE(typename QuaternionLike::Vector3)::Options>
124  log3(const Eigen::QuaternionBase<QuaternionLike> & quat)
125  {
126  typename QuaternionLike::Scalar theta;
127  return log3(quat.derived(),theta);
128  }
129 
136  template<typename Vector3Like, typename Matrix43Like>
137  void Jexp3CoeffWise(const Eigen::MatrixBase<Vector3Like> & v,
138  const Eigen::MatrixBase<Matrix43Like> & Jexp)
139  {
140 // EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix43Like,4,3);
141  assert(Jexp.rows() == 4 && Jexp.cols() == 3 && "Jexp does have the right size.");
142  Matrix43Like & Jout = PINOCCHIO_EIGEN_CONST_CAST(Matrix43Like,Jexp);
143 
144  typedef typename Vector3Like::Scalar Scalar;
145 
146  const Scalar n2 = v.squaredNorm();
147  const Scalar n = math::sqrt(n2);
148  const Scalar theta = Scalar(0.5) * n;
149  const Scalar theta2 = Scalar(0.25) * n2;
150 
151  if(n2 > math::sqrt(Eigen::NumTraits<Scalar>::epsilon()))
152  {
153  Scalar c, s;
154  SINCOS(theta,&s,&c);
155  Jout.template topRows<3>().noalias() = ((0.5/n2) * (c - 2*s/n)) * v * v.transpose();
156  Jout.template topRows<3>().diagonal().array() += s/n;
157  Jout.template bottomRows<1>().noalias() = -s/(2*n) * v.transpose();
158  }
159  else
160  {
161  Jout.template topRows<3>().noalias() = (-1./12. + n2/480.) * v * v.transpose();
162  Jout.template topRows<3>().diagonal().array() += Scalar(0.5) * (1 - theta2/6);
163  Jout.template bottomRows<1>().noalias() = (Scalar(-0.25) * (1 - theta2/6)) * v.transpose();
164 
165  }
166  }
167 
174  template<typename QuaternionLike, typename Matrix3Like>
175  void Jlog3(const Eigen::QuaternionBase<QuaternionLike> & quat,
176  const Eigen::MatrixBase<Matrix3Like> & Jlog)
177  {
178  typedef typename QuaternionLike::Scalar Scalar;
179  typedef Eigen::Matrix<Scalar,3,1,PINOCCHIO_EIGEN_PLAIN_TYPE(typename QuaternionLike::Coefficients)::Options> Vector3;
180 
181  Scalar t;
182  Vector3 w(log3(quat,t));
183  pinocchio::Jlog3(t,w,Jlog);
184  }
185  } // namespace quaternion
186 }
187 
188 #endif // ifndef __pinocchio_spatial_explog_quaternion_hpp__
Eigen::Matrix< typename QuaternionLike::Scalar, 3, 1, typename QuaternionLike::Vector3::Options > log3(const Eigen::QuaternionBase< QuaternionLike > &quat, typename QuaternionLike::Scalar &theta)
Same as log3 but with a unit quaternion as input.
void Jlog3(const Eigen::QuaternionBase< QuaternionLike > &quat, const Eigen::MatrixBase< Matrix3Like > &Jlog)
Computes the Jacobian of log3 operator for a unit quaternion.
void exp3(const Eigen::MatrixBase< Vector3Like > &v, Eigen::QuaternionBase< QuaternionLike > &quat_out)
Exp: so3 -> SO3 (quaternion)
void SINCOS(const Scalar &a, Scalar *sa, Scalar *ca)
Computes sin/cos values of a given input scalar.
Definition: sincos.hpp:28
void Jexp3CoeffWise(const Eigen::MatrixBase< Vector3Like > &v, const Eigen::MatrixBase< Matrix43Like > &Jexp)
Derivative of where is a small perturbation of at identity.
Main pinocchio namespace.
Definition: treeview.dox:24