pinocchio  2.1.3
special-euclidean.hpp
1 //
2 // Copyright (c) 2016-2018 CNRS
3 //
4 
5 #ifndef __pinocchio_special_euclidean_operation_hpp__
6 #define __pinocchio_special_euclidean_operation_hpp__
7 
8 #include <limits>
9 
10 #include <pinocchio/macros.hpp>
11 #include "pinocchio/spatial/fwd.hpp"
12 #include "pinocchio/spatial/se3.hpp"
13 #include "pinocchio/multibody/liegroup/liegroup-base.hpp"
14 
15 #include "pinocchio/multibody/liegroup/vector-space.hpp"
16 #include "pinocchio/multibody/liegroup/cartesian-product.hpp"
17 #include "pinocchio/multibody/liegroup/special-orthogonal.hpp"
18 
19 namespace pinocchio
20 {
21  template<int Dim, typename Scalar, int Options = 0>
23  {};
24 
25  template<int Dim, typename Scalar, int Options>
26  struct traits< SpecialEuclideanOperationTpl<Dim,Scalar,Options> >
27  {};
28 
29  template<typename _Scalar, int _Options>
30  struct traits< SpecialEuclideanOperationTpl<2,_Scalar,_Options> >
31  {
32  typedef _Scalar Scalar;
33  enum
34  {
35  Options = _Options,
36  NQ = 4,
37  NV = 3
38  };
39  };
40 
41  // SE(2)
42  template<typename _Scalar, int _Options>
43  struct SpecialEuclideanOperationTpl<2,_Scalar,_Options>
44  : public LieGroupBase <SpecialEuclideanOperationTpl<2,_Scalar,_Options> >
45  {
46  PINOCCHIO_LIE_GROUP_TPL_PUBLIC_INTERFACE(SpecialEuclideanOperationTpl);
47 
51 
52  typedef Eigen::Matrix<Scalar,2,2,Options> Matrix2;
53  typedef Eigen::Matrix<Scalar,2,1,Options> Vector2;
54 
55  template<typename TangentVector, typename Matrix2Like, typename Vector2Like>
56  static void exp(const Eigen::MatrixBase<TangentVector> & v,
57  const Eigen::MatrixBase<Matrix2Like> & R,
58  const Eigen::MatrixBase<Vector2Like> & t)
59  {
60  EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(TangentVector_t,TangentVector);
61  EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like, 2, 2);
62  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2Like, 2);
63 
64  typedef typename Matrix2Like::Scalar Scalar;
65  const Scalar omega = v(2);
66  Scalar cv,sv; SINCOS(omega, &sv, &cv);
67  const_cast<Matrix2Like &>(R.derived()) << cv, -sv, sv, cv;
68 
69  if (math::fabs(omega) > 1e-14)
70  {
71  typename PINOCCHIO_EIGEN_PLAIN_TYPE(Vector2Like) vcross(-v(1), v(0));
72  vcross /= omega;
73  PINOCCHIO_EIGEN_CONST_CAST(Vector2Like,t).noalias() = vcross - R * vcross;
74  }
75  else
76  {
77  PINOCCHIO_EIGEN_CONST_CAST(Vector2Like,t) = v.template head<2>();
78  }
79  }
80 
81  template<typename Matrix2Like, typename Vector2Like, typename Matrix3Like>
82  static void toInverseActionMatrix(const Eigen::MatrixBase<Matrix2Like> & R,
83  const Eigen::MatrixBase<Vector2Like> & t,
84  const Eigen::MatrixBase<Matrix3Like> & M)
85  {
86  EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like, 2, 2);
87  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2Like, 2);
88  EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix3Like, 3, 3);
89 
90  typedef typename Matrix3Like::Scalar Scalar;
91 
92  Matrix3Like & Mout = PINOCCHIO_EIGEN_CONST_CAST(Matrix3Like,M);
93  Mout.template topLeftCorner<2,2>() = R.transpose();
94  typename PINOCCHIO_EIGEN_PLAIN_TYPE(Vector2Like) tinv(R.transpose() * t);
95  Mout.template topRightCorner<2,1>() << - tinv(1), tinv(0);
96  Mout.template bottomLeftCorner<1,2>().setZero();
97  Mout(2,2) = (Scalar)1;
98  }
99 
100  template<typename Matrix2Like, typename Vector2Like, typename TangentVector>
101  static void log(const Eigen::MatrixBase<Matrix2Like> & R,
102  const Eigen::MatrixBase<Vector2Like> & p,
103  const Eigen::MatrixBase<TangentVector> & v)
104  {
105  EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like, 2, 2);
106  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2Like, 2);
107  EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(TangentVector_t,TangentVector);
108 
109  TangentVector & vout = PINOCCHIO_EIGEN_CONST_CAST(TangentVector,v);
110 
111  typedef typename Matrix2Like::Scalar Scalar1;
112 
113  Scalar1 t = SO2_t::log(R);
114  const Scalar1 tabs = math::fabs(t);
115  const Scalar1 t2 = t*t;
116  Scalar1 alpha;
117  if (tabs < 1e-4)
118  {
119  alpha = 1 - t2/12 - t2*t2/720;
120  }
121  else
122  {
123  Scalar1 st,ct; SINCOS(tabs, &st, &ct);
124  alpha = tabs*st/(2*(1-ct));
125  }
126 
127  vout.template head<2>().noalias() = alpha * p;
128  vout(0) += t/2 * p(1);
129  vout(1) += -t/2 * p(0);
130  vout(2) = t;
131  }
132 
133  template<typename Matrix2Like, typename Vector2Like, typename JacobianOutLike>
134  static void Jlog(const Eigen::MatrixBase<Matrix2Like> & R,
135  const Eigen::MatrixBase<Vector2Like> & p,
136  const Eigen::MatrixBase<JacobianOutLike> & J)
137  {
138  EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like, 2, 2);
139  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2Like, 2);
140  EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(JacobianOutLike, JacobianMatrix_t);
141 
142  JacobianOutLike & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOutLike,J);
143 
144  typedef typename Matrix2Like::Scalar Scalar1;
145 
146  Scalar1 t = SO2_t::log(R);
147  const Scalar1 tabs = math::fabs(t);
148  Scalar1 alpha, alpha_dot;
149  if (tabs < 1e-4)
150  {
151  Scalar1 t2 = t*t;
152  alpha = 1 - t2/12;
153  alpha_dot = - t / 6 - t2*t / 180;
154  }
155  else
156  {
157  Scalar1 st,ct; SINCOS(t, &st, &ct);
158  Scalar1 inv_2_1_ct = 0.5 / (1-ct);
159  // t * sin(t) / (2 * (1 - cos(t)) )
160  alpha = t*st*inv_2_1_ct;
161  // [ ( 1 - cos(t) ) * sin(t) + t * cos(t) - 1 ] / (2 * (1 - cos(t))^2 )
162  alpha_dot = (st-t) * inv_2_1_ct;
163  }
164 
165  typename PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix2Like) V;
166  V(0,0) = V(1,1) = alpha;
167  V(1,0) = - t / 2;
168  V(0,1) = - V(1,0);
169 
170  Jout.template topLeftCorner <2,2>().noalias() = V * R;
171  Jout.template topRightCorner<2,1>() << alpha_dot*p[0] + p[1]/2, -p(0)/2 + alpha_dot*p(1);
172  Jout.template bottomLeftCorner<1,2>().setZero();
173  Jout(2,2) = 1;
174  }
175 
180  static Index nq()
181  {
182  return NQ;
183  }
185  static Index nv()
186  {
187  return NV;
188  }
189 
190  static ConfigVector_t neutral()
191  {
192  ConfigVector_t n; n << Scalar(0), Scalar(0), Scalar(1), Scalar(0);
193  return n;
194  }
195 
196  static std::string name()
197  {
198  return std::string("SE(2)");
199  }
200 
201  template <class ConfigL_t, class ConfigR_t, class Tangent_t>
202  static void difference_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
203  const Eigen::MatrixBase<ConfigR_t> & q1,
204  const Eigen::MatrixBase<Tangent_t> & d)
205  {
206  if (q0 == q1)
207  {
208  PINOCCHIO_EIGEN_CONST_CAST(Tangent_t,d).setZero();
209  return;
210  }
211  Matrix2 R0, R1; Vector2 t0, t1;
212  forwardKinematics(R0, t0, q0);
213  forwardKinematics(R1, t1, q1);
214  Matrix2 R (R0.transpose() * R1);
215  Vector2 t (R0.transpose() * (t1 - t0));
216 
217  log(R, t, d);
218  }
219 
220  template <ArgumentPosition arg, class ConfigL_t, class ConfigR_t, class JacobianOut_t>
221  void dDifference_impl (const Eigen::MatrixBase<ConfigL_t> & q0,
222  const Eigen::MatrixBase<ConfigR_t> & q1,
223  const Eigen::MatrixBase<JacobianOut_t>& J) const
224  {
225  Matrix2 R0, R1; Vector2 t0, t1;
226  forwardKinematics(R0, t0, q0);
227  forwardKinematics(R1, t1, q1);
228  Matrix2 R (R0.transpose() * R1);
229  Vector2 t (R0.transpose() * (t1 - t0));
230 
231  if (arg == ARG0) {
232  JacobianMatrix_t J1;
233  Jlog (R, t, J1);
234 
235  // pcross = [ y1-y0, - (x1 - x0) ]
236  Vector2 pcross (q1(1) - q0(1), q0(0) - q1(0));
237 
238  JacobianOut_t& J0 = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t, J);
239  J0.template topLeftCorner <2,2> ().noalias() = - R.transpose();
240  J0.template topRightCorner<2,1> ().noalias() = R1.transpose() * pcross;
241  J0.template bottomLeftCorner <1,2> ().setZero();
242  J0 (2,2) = -1;
243  J0.applyOnTheLeft(J1);
244  } else if (arg == ARG1) {
245  Jlog (R, t, J);
246  }
247  }
248 
249  template <class ConfigIn_t, class Velocity_t, class ConfigOut_t>
250  static void integrate_impl(const Eigen::MatrixBase<ConfigIn_t> & q,
251  const Eigen::MatrixBase<Velocity_t> & v,
252  const Eigen::MatrixBase<ConfigOut_t> & qout)
253  {
254  ConfigOut_t & out = PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout);
255 
256  Matrix2 R0, R;
257  Vector2 t0, t;
258  forwardKinematics(R0, t0, q);
259  exp(v, R, t);
260 
261  out.template head<2>().noalias() = R0 * t + t0;
262  out.template tail<2>().noalias() = R0 * R.col(0);
263  }
264 
265  template <class Config_t, class Jacobian_t>
266  static void integrateCoeffWiseJacobian_impl(const Eigen::MatrixBase<Config_t> & q,
267  const Eigen::MatrixBase<Jacobian_t> & J)
268  {
269  assert(J.rows() == nq() && J.cols() == nv() && "J is not of the right dimension");
270 
271  Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J);
272  Jout.setZero();
273 
274  const typename Config_t::Scalar & c_theta = q(2),
275  & s_theta = q(3);
276 
277  Jout.template topLeftCorner<2,2>() << c_theta, -s_theta, s_theta, c_theta;
278  Jout.template bottomRightCorner<2,1>() << -s_theta, c_theta;
279  }
280 
281  template <class Config_t, class Tangent_t, class JacobianOut_t>
282  static void dIntegrate_dq_impl(const Eigen::MatrixBase<Config_t > & /*q*/,
283  const Eigen::MatrixBase<Tangent_t> & v,
284  const Eigen::MatrixBase<JacobianOut_t>& J)
285  {
286  JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
287 
288  Matrix2 R;
289  Vector2 t;
290  exp(v, R, t);
291 
292  toInverseActionMatrix(R, t, Jout);
293  }
294 
295  template <class Config_t, class Tangent_t, class JacobianOut_t>
296  static void dIntegrate_dv_impl(const Eigen::MatrixBase<Config_t > & /*q*/,
297  const Eigen::MatrixBase<Tangent_t> & v,
298  const Eigen::MatrixBase<JacobianOut_t> & J)
299  {
300  JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
301  // TODO sparse version
302  MotionTpl<Scalar,0> nu; nu.toVector() << v.template head<2>(), 0, 0, 0, v[2];
303  Eigen::Matrix<Scalar,6,6> Jtmp6;
304  Jexp6(nu, Jtmp6);
305  Jout << Jtmp6.template topLeftCorner<2,2>(), Jtmp6.template topRightCorner<2,1>(),
306  Jtmp6.template bottomLeftCorner<1,2>(), Jtmp6.template bottomRightCorner<1,1>();
307  }
308 
309  // interpolate_impl use default implementation.
310  // template <class ConfigL_t, class ConfigR_t, class ConfigOut_t>
311  // static void interpolate_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
312  // const Eigen::MatrixBase<ConfigR_t> & q1,
313  // const Scalar& u,
314  // const Eigen::MatrixBase<ConfigOut_t>& qout)
315 
316  // template <class ConfigL_t, class ConfigR_t>
317  // static double squaredDistance_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
318  // const Eigen::MatrixBase<ConfigR_t> & q1)
319  template <class Config_t>
320  static void normalize_impl (const Eigen::MatrixBase<Config_t>& qout)
321  {
322  PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout).template tail<2>().normalize();
323  }
324 
325  template <class Config_t>
326  void random_impl (const Eigen::MatrixBase<Config_t>& qout) const
327  {
328  R2crossSO2_t().random(qout);
329  }
330 
331  template <class ConfigL_t, class ConfigR_t, class ConfigOut_t>
332  void randomConfiguration_impl(const Eigen::MatrixBase<ConfigL_t> & lower,
333  const Eigen::MatrixBase<ConfigR_t> & upper,
334  const Eigen::MatrixBase<ConfigOut_t> & qout)
335  const
336  {
337  R2crossSO2_t ().randomConfiguration(lower, upper, qout);
338  }
339 
340  template <class ConfigL_t, class ConfigR_t>
341  static bool isSameConfiguration_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
342  const Eigen::MatrixBase<ConfigR_t> & q1,
343  const Scalar & prec)
344  {
345  return R2crossSO2_t().isSameConfiguration(q0, q1, prec);
346  }
347 
348  protected:
349 
350  template<typename Matrix2Like, typename Vector2Like, typename Vector4Like>
351  static void forwardKinematics(const Eigen::MatrixBase<Matrix2Like> & R,
352  const Eigen::MatrixBase<Vector2Like> & t,
353  const Eigen::MatrixBase<Vector4Like> & q)
354  {
355  EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Matrix2Like, Matrix2);
356  EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Vector2Like, Vector2);
357  EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ConfigVector_t,Vector4Like);
358 
359  PINOCCHIO_EIGEN_CONST_CAST(Vector2Like,t) = q.template head<2>();
360  const typename Vector4Like::Scalar & c_theta = q(2),
361  & s_theta = q(3);
362  PINOCCHIO_EIGEN_CONST_CAST(Matrix2Like,R) << c_theta, -s_theta, s_theta, c_theta;
363 
364  }
365  }; // struct SpecialEuclideanOperationTpl<2>
366 
367  template<typename _Scalar, int _Options>
368  struct traits< SpecialEuclideanOperationTpl<3,_Scalar,_Options> >
369  {
370  typedef _Scalar Scalar;
371  enum
372  {
373  Options = _Options,
374  NQ = 7,
375  NV = 6
376  };
377  };
378 
380  template<typename _Scalar, int _Options>
381  struct SpecialEuclideanOperationTpl<3,_Scalar,_Options>
382  : public LieGroupBase <SpecialEuclideanOperationTpl<3,_Scalar,_Options> >
383  {
384  PINOCCHIO_LIE_GROUP_TPL_PUBLIC_INTERFACE(SpecialEuclideanOperationTpl);
385 
387 
388  typedef Eigen::Quaternion<Scalar,Options> Quaternion_t;
389  typedef Eigen::Map< Quaternion_t> QuaternionMap_t;
390  typedef Eigen::Map<const Quaternion_t> ConstQuaternionMap_t;
392  typedef SE3Tpl<Scalar,Options> SE3;
393 
398  static Index nq()
399  {
400  return NQ;
401  }
403  static Index nv()
404  {
405  return NV;
406  }
407 
408  static ConfigVector_t neutral()
409  {
410  ConfigVector_t n; n.template head<6>().setZero(); n[6] = 1;
411  return n;
412  }
413 
414  static std::string name()
415  {
416  return std::string("SE(3)");
417  }
418 
419  template <class ConfigL_t, class ConfigR_t, class Tangent_t>
420  static void difference_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
421  const Eigen::MatrixBase<ConfigR_t> & q1,
422  const Eigen::MatrixBase<Tangent_t> & d)
423  {
424  if (q0 == q1)
425  {
426  PINOCCHIO_EIGEN_CONST_CAST(Tangent_t,d).setZero();
427  return;
428  }
429  ConstQuaternionMap_t p0 (q0.derived().template tail<4>().data());
430  ConstQuaternionMap_t p1 (q1.derived().template tail<4>().data());
431  PINOCCHIO_EIGEN_CONST_CAST(Tangent_t,d)
432  = log6( SE3(p0.matrix(), q0.derived().template head<3>()).inverse()
433  * SE3(p1.matrix(), q1.derived().template head<3>())).toVector();
434  }
435 
436  template <ArgumentPosition arg, class ConfigL_t, class ConfigR_t, class JacobianOut_t>
437  void dDifference_impl (const Eigen::MatrixBase<ConfigL_t> & q0,
438  const Eigen::MatrixBase<ConfigR_t> & q1,
439  const Eigen::MatrixBase<JacobianOut_t>& J) const
440  {
441  ConstQuaternionMap_t p0 (q0.derived().template tail<4>().data());
442  ConstQuaternionMap_t p1 (q1.derived().template tail<4>().data());
443  typename SE3::Matrix3 R0 (p0.matrix()),
444  R1 (p1.matrix());
445  SE3 M ( SE3(R0, q0.derived().template head<3>()).inverse()
446  * SE3(R1, q1.derived().template head<3>()));
447 
448  if (arg == ARG0) {
449  JacobianMatrix_t J1;
450  Jlog6 (M, J1);
451 
452  typename SE3::Vector3 p1_p0 ( q1.derived().template head<3>()
453  - q0.derived().template head<3>());
454 
455  JacobianOut_t& J0 = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
456  J0.template topLeftCorner <3,3> ().noalias() = - M.rotation().transpose();
457  J0.template topRightCorner<3,3> ().noalias() = R1.transpose() * skew (p1_p0) * R0;
458  J0.template bottomLeftCorner <3,3> ().setZero();
459  J0.template bottomRightCorner<3,3> ().noalias() = - M.rotation().transpose();
460  J0.applyOnTheLeft(J1);
461  } else if (arg == ARG1) {
462  Jlog6 (M, J);
463  }
464  }
465 
466  template <class ConfigIn_t, class Velocity_t, class ConfigOut_t>
467  static void integrate_impl(const Eigen::MatrixBase<ConfigIn_t> & q,
468  const Eigen::MatrixBase<Velocity_t> & v,
469  const Eigen::MatrixBase<ConfigOut_t> & qout)
470  {
471  ConfigOut_t & out = PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout);
472  ConstQuaternionMap_t quat(q.derived().template tail<4>().data());
473  QuaternionMap_t res_quat (out.template tail<4>().data());
474 
475  SE3 M0 (quat.matrix(), q.derived().template head<3>());
476  MotionRef<const Velocity_t> mref_v(v.derived());
477  SE3 M1 (M0 * exp6(mref_v));
478 
479  out.template head<3>() = M1.translation();
480  res_quat = M1.rotation();
481  if(res_quat.dot(quat) < 0) res_quat.coeffs() *= -1.;
482  // Norm of qs might be epsilon-different to 1, so M1.rotation might be epsilon-different to a rotation matrix.
483  // It is then safer to re-normalized after converting M1.rotation to quaternion.
485  }
486 
487  template <class Config_t, class Jacobian_t>
488  static void integrateCoeffWiseJacobian_impl(const Eigen::MatrixBase<Config_t> & q,
489  const Eigen::MatrixBase<Jacobian_t> & J)
490  {
491  assert(J.rows() == nq() && J.cols() == nv() && "J is not of the right dimension");
492 
493  typedef typename PINOCCHIO_EIGEN_PLAIN_TYPE(Config_t) ConfigPlainType;
494  typedef typename PINOCCHIO_EIGEN_PLAIN_TYPE(Jacobian_t) JacobianPlainType;
495  typedef typename ConfigPlainType::Scalar Scalar;
496  Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J);
497  Jout.setZero();
498 
499  ConstQuaternionMap_t quat_map(q.derived().template tail<4>().data());
500  Jout.template topLeftCorner<3,3>() = quat_map.toRotationMatrix();
501 // Jexp3(quat,Jout.template bottomRightCorner<4,3>());
502 
503  typedef Eigen::Matrix<Scalar,4,3,JacobianPlainType::Options|Eigen::RowMajor> Jacobian43;
505  Jacobian43 Jexp3QuatCoeffWise;
506 
507  Scalar theta;
508  typename SE3::Vector3 v = quaternion::log3(quat_map,theta);
509  quaternion::Jexp3CoeffWise(v,Jexp3QuatCoeffWise);
510  typename SE3::Matrix3 Jlog;
511  Jlog3(theta,v,Jlog);
512 
513 // std::cout << "Jexp3QuatCoeffWise\n" << Jexp3QuatCoeffWise << std::endl;
514 // std::cout << "Jlog\n" << Jlog << std::endl;
515 
516 // if(quat_map.w() >= 0.) // comes from the log3 for quaternions which may change the sign.
517  if(quat_map.coeffs()[3] >= 0.) // comes from the log3 for quaternions which may change the sign.
518  PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J).template bottomRightCorner<4,3>().noalias() = Jexp3QuatCoeffWise * Jlog;
519  else
520  PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J).template bottomRightCorner<4,3>().noalias() = -Jexp3QuatCoeffWise * Jlog;
521  }
522 
523  template <class Config_t, class Tangent_t, class JacobianOut_t>
524  static void dIntegrate_dq_impl(const Eigen::MatrixBase<Config_t > & /*q*/,
525  const Eigen::MatrixBase<Tangent_t> & v,
526  const Eigen::MatrixBase<JacobianOut_t>& J)
527  {
528  JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
529  Jout = exp6(MotionRef<const Tangent_t>(v.derived())).toDualActionMatrix().transpose();
530  }
531 
532  template <class Config_t, class Tangent_t, class JacobianOut_t>
533  static void dIntegrate_dv_impl(const Eigen::MatrixBase<Config_t > & /*q*/,
534  const Eigen::MatrixBase<Tangent_t> & v,
535  const Eigen::MatrixBase<JacobianOut_t>& J)
536  {
537  Jexp6(MotionRef<const Tangent_t>(v.derived()), J.derived());
538  }
539 
540  // interpolate_impl use default implementation.
541  // template <class ConfigL_t, class ConfigR_t, class ConfigOut_t>
542  // static void interpolate_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
543  // const Eigen::MatrixBase<ConfigR_t> & q1,
544  // const Scalar& u,
545  // const Eigen::MatrixBase<ConfigOut_t>& qout)
546  // {
547  // }
548 
549  template <class ConfigL_t, class ConfigR_t>
550  static Scalar squaredDistance_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
551  const Eigen::MatrixBase<ConfigR_t> & q1)
552  {
553  TangentVector_t t;
554  difference_impl(q0, q1, t);
555  return t.squaredNorm();
556  }
557 
558  template <class Config_t>
559  static void normalize_impl (const Eigen::MatrixBase<Config_t>& qout)
560  {
561  Config_t& qout_ = (const_cast< Eigen::MatrixBase<Config_t>& >(qout)).derived();
562  qout_.template tail<4>().normalize();
563  }
564 
565  template <class Config_t>
566  void random_impl (const Eigen::MatrixBase<Config_t>& qout) const
567  {
568  R3crossSO3_t().random(qout);
569  }
570 
571  template <class ConfigL_t, class ConfigR_t, class ConfigOut_t>
572  void randomConfiguration_impl(const Eigen::MatrixBase<ConfigL_t> & lower,
573  const Eigen::MatrixBase<ConfigR_t> & upper,
574  const Eigen::MatrixBase<ConfigOut_t> & qout)
575  const
576  {
577  R3crossSO3_t ().randomConfiguration(lower, upper, qout);
578  }
579 
580  template <class ConfigL_t, class ConfigR_t>
581  static bool isSameConfiguration_impl(const Eigen::MatrixBase<ConfigL_t> & q0,
582  const Eigen::MatrixBase<ConfigR_t> & q1,
583  const Scalar & prec)
584  {
585  return R3crossSO3_t().isSameConfiguration(q0, q1, prec);
586  }
587  }; // struct SpecialEuclideanOperationTpl<3>
588 
589 } // namespace pinocchio
590 
591 #endif // ifndef __pinocchio_special_euclidean_operation_hpp__
int nv(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointNvVisitor to get the dimension of the joint tangent space...
static Index nv()
Get dimension of Lie Group tangent space.
static Index nv()
Get dimension of Lie Group tangent space.
int nq(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointNqVisitor to get the dimension of the joint configuration space...
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.
std::string name(const LieGroupGenericTpl< LieGroupCollection > &lg)
Visit a LieGroupVariant to get the name of it.
void firstOrderNormalize(const Eigen::QuaternionBase< D > &q)
Definition: quaternion.hpp:77
void Jlog6(const SE3Tpl< Scalar, Options > &M, const Eigen::MatrixBase< Matrix6Like > &Jlog)
Derivative of log6 where and .
Definition: explog.hpp:455
MotionTpl< Scalar, Options > log6(const SE3Tpl< Scalar, Options > &M)
Log: SE3 -> se3.
Definition: explog.hpp:333
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.
void Jexp6(const MotionDense< MotionDerived > &nu, const Eigen::MatrixBase< Matrix6Like > &Jexp)
Derivative of exp6 Computed as the inverse of Jlog6.
Definition: explog.hpp:383
void forwardKinematics(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q)
Update the joint placements according to the current joint configuration.
Main pinocchio namespace.
Definition: treeview.dox:24
void neutral(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ReturnType > &qout)
Return the neutral configuration element related to the model configuration space.
Common traits structure to fully define base classes for CRTP.
Definition: spatial/fwd.hpp:29
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...
Definition: skew.hpp:21
void normalize(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ConfigVectorType > &qout)
Normalize a configuration vector.
SE3Tpl< typename MotionDerived::Scalar, typename MotionDerived::Vector3::Options > exp6(const MotionDense< MotionDerived > &nu)
Exp: se3 -> SE3.
Definition: explog.hpp:248