5 #ifndef __pinocchio_multibody_liegroup_special_orthogonal_operation_hpp__
6 #define __pinocchio_multibody_liegroup_special_orthogonal_operation_hpp__
10 #include "pinocchio/spatial/explog.hpp"
11 #include "pinocchio/math/quaternion.hpp"
12 #include "pinocchio/multibody/liegroup/liegroup-base.hpp"
13 #include "pinocchio/utils/static-if.hpp"
17 template<
int Dim,
typename Scalar,
int Options = 0>
21 template<
int Dim,
typename Scalar,
int Options>
25 template<
typename _Scalar,
int _Options>
28 typedef _Scalar Scalar;
37 template<
typename _Scalar,
int _Options >
39 typedef _Scalar Scalar;
48 template<
typename _Scalar,
int _Options>
50 :
public LieGroupBase< SpecialOrthogonalOperationTpl<2,_Scalar,_Options> >
53 typedef Eigen::Matrix<Scalar,2,2> Matrix2;
54 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
56 template<
typename Matrix2Like>
57 static typename Matrix2Like::Scalar
58 log(
const Eigen::MatrixBase<Matrix2Like> & R)
60 typedef typename Matrix2Like::Scalar Scalar;
61 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like,2,2);
63 const Scalar tr = R.trace();
65 static const Scalar PI_value = PI<Scalar>();
67 using internal::if_then_else;
69 if_then_else(internal::GT, tr, Scalar(2),
71 if_then_else(internal::LT, tr, Scalar(-2),
72 if_then_else(internal::GE, R (1, 0), Scalar(0),
74 if_then_else(internal::GT, tr, Scalar(2) - Scalar(1e-2),
75 asin((R(1,0) - R(0,1)) / Scalar(2)),
76 if_then_else(internal::GE, R (1, 0), Scalar(0),
92 assert (theta == theta);
98 template<
typename Matrix2Like>
99 static typename Matrix2Like::Scalar
100 Jlog(
const Eigen::MatrixBase<Matrix2Like> &)
102 typedef typename Matrix2Like::Scalar Scalar;
103 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like,2,2);
122 static ConfigVector_t
neutral()
124 ConfigVector_t n; n << Scalar(1), Scalar(0);
128 static std::string
name()
130 return std::string(
"SO(2)");
133 template <
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
134 static void difference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
135 const Eigen::MatrixBase<ConfigR_t> & q1,
136 const Eigen::MatrixBase<Tangent_t> & d)
139 R(0,0) = R(1,1) = q0.dot(q1);
140 R(1,0) = q0(0) * q1(1) - q0(1) * q1(0);
142 PINOCCHIO_EIGEN_CONST_CAST(Tangent_t,d)[0] = log(R);
145 template <ArgumentPosition arg,
class ConfigL_t,
class ConfigR_t,
class JacobianOut_t>
146 static void dDifference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
147 const Eigen::MatrixBase<ConfigR_t> & q1,
148 const Eigen::MatrixBase<JacobianOut_t> & J)
151 R(0,0) = R(1,1) = q0.dot(q1);
152 R(1,0) = q0(0) * q1(1) - q0(1) * q1(0);
156 PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J).coeffRef(0,0) = ((arg==ARG0) ? -w : w);
159 template <
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
160 static void integrate_impl(
const Eigen::MatrixBase<ConfigIn_t> & q,
161 const Eigen::MatrixBase<Velocity_t> & v,
162 const Eigen::MatrixBase<ConfigOut_t> & qout)
164 ConfigOut_t & out = PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout);
166 const Scalar ca = q(0);
167 const Scalar sa = q(1);
168 const Scalar & omega = v(0);
170 Scalar cosOmega,sinOmega;
SINCOS(omega, &sinOmega, &cosOmega);
173 out << cosOmega * ca - sinOmega * sa,
174 sinOmega * ca + cosOmega * sa;
177 const Scalar norm2 = out.squaredNorm();
178 out *= (3 - norm2) / 2;
182 template <
class Config_t,
class Jacobian_t>
183 static void integrateCoeffWiseJacobian_impl(
const Eigen::MatrixBase<Config_t> & q,
184 const Eigen::MatrixBase<Jacobian_t> & J)
186 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
187 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J);
191 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
192 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
193 const Eigen::MatrixBase<Tangent_t> & ,
194 const Eigen::MatrixBase<JacobianOut_t> & J,
195 const AssignmentOperatorType op=SETTO)
197 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
201 Jout(0,0) = Scalar(1);
204 Jout(0,0) += Scalar(1);
207 Jout(0,0) -= Scalar(1);
210 assert(
false &&
"Wrong Op requesed value");
215 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
216 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
217 const Eigen::MatrixBase<Tangent_t> & ,
218 const Eigen::MatrixBase<JacobianOut_t> & J,
219 const AssignmentOperatorType op=SETTO)
221 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
225 Jout(0,0) = Scalar(1);
228 Jout(0,0) += Scalar(1);
231 Jout(0,0) -= Scalar(1);
234 assert(
false &&
"Wrong Op requesed value");
239 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
240 static void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
241 const Eigen::MatrixBase<Tangent_t> & ,
242 const Eigen::MatrixBase<JacobianIn_t> & Jin,
243 const Eigen::MatrixBase<JacobianOut_t> & Jout)
245 PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,Jout) = Jin;
248 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
249 static void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
250 const Eigen::MatrixBase<Tangent_t> & ,
251 const Eigen::MatrixBase<JacobianIn_t> & Jin,
252 const Eigen::MatrixBase<JacobianOut_t> & Jout)
254 PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,Jout) = Jin;
257 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
258 static void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
259 const Eigen::MatrixBase<Tangent_t> & ,
260 const Eigen::MatrixBase<Jacobian_t> & ) {}
262 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
263 static void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
264 const Eigen::MatrixBase<Tangent_t> & ,
265 const Eigen::MatrixBase<Jacobian_t> & ) {}
269 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
270 static void interpolate_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
271 const Eigen::MatrixBase<ConfigR_t> & q1,
273 const Eigen::MatrixBase<ConfigOut_t>& qout)
275 ConfigOut_t & out = PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout);
277 assert ( std::abs(q0.norm() - 1) < 1e-8 &&
"initial configuration not normalized");
278 assert ( std::abs(q1.norm() - 1) < 1e-8 &&
"final configuration not normalized");
279 Scalar cosTheta = q0.dot(q1);
280 Scalar sinTheta = q0(0)*q1(1) - q0(1)*q1(0);
281 Scalar theta = atan2(sinTheta, cosTheta);
282 assert (fabs (sin (theta) - sinTheta) < 1e-8);
284 const Scalar PI_value = PI<Scalar>();
286 if (fabs (theta) > 1e-6 && fabs (theta) < PI_value - 1e-6)
288 out = (sin ((1-u)*theta)/sinTheta) * q0
289 + (sin ( u *theta)/sinTheta) * q1;
291 else if (fabs (theta) < 1e-6)
293 out = (1-u) * q0 + u * q1;
297 Scalar theta0 = atan2 (q0(1), q0(0));
298 SINCOS(theta0,&out[1],&out[0]);
302 template <
class Config_t>
303 static void normalize_impl (
const Eigen::MatrixBase<Config_t> & qout)
305 Config_t & qout_ = PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout).derived();
309 template <
class Config_t>
310 static bool isNormalized_impl (
const Eigen::MatrixBase<Config_t> & qin,
313 const Scalar norm = qin.norm();
315 return abs(norm - Scalar(1.0)) < prec;
318 template <
class Config_t>
319 static void random_impl (
const Eigen::MatrixBase<Config_t>& qout)
321 Config_t & out = PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout);
323 const Scalar PI_value = PI<Scalar>();
324 const Scalar angle = -PI_value + Scalar(2)* PI_value * ((Scalar)rand())/RAND_MAX;
325 SINCOS(angle, &out(1), &out(0));
328 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
329 static void randomConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> &,
330 const Eigen::MatrixBase<ConfigR_t> &,
331 const Eigen::MatrixBase<ConfigOut_t> & qout)
337 template<
typename _Scalar,
int _Options>
339 :
public LieGroupBase< SpecialOrthogonalOperationTpl<3,_Scalar,_Options> >
343 typedef Eigen::Quaternion<Scalar> Quaternion_t;
344 typedef Eigen::Map< Quaternion_t> QuaternionMap_t;
345 typedef Eigen::Map<const Quaternion_t> ConstQuaternionMap_t;
347 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
364 static ConfigVector_t
neutral()
366 ConfigVector_t n; n.setZero (); n[3] = Scalar(1);
370 static std::string
name()
372 return std::string(
"SO(3)");
375 template <
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
376 static void difference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
377 const Eigen::MatrixBase<ConfigR_t> & q1,
378 const Eigen::MatrixBase<Tangent_t> & d)
380 ConstQuaternionMap_t quat0 (q0.derived().data());
382 ConstQuaternionMap_t quat1 (q1.derived().data());
385 PINOCCHIO_EIGEN_CONST_CAST(Tangent_t,d)
389 template <ArgumentPosition arg,
class ConfigL_t,
class ConfigR_t,
class JacobianOut_t>
390 static void dDifference_impl (
const Eigen::MatrixBase<ConfigL_t> & q0,
391 const Eigen::MatrixBase<ConfigR_t> & q1,
392 const Eigen::MatrixBase<JacobianOut_t> & J)
394 typedef typename SE3::Matrix3 Matrix3;
396 ConstQuaternionMap_t quat0 (q0.derived().data());
398 ConstQuaternionMap_t quat1 (q1.derived().data());
401 const Quaternion_t quat_diff = quat0.conjugate() * quat1;
404 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
405 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
408 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
409 const Matrix3 R = (quat_diff).matrix();
411 PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J).noalias() = - J1 * R.transpose();
412 }
else if (arg == ARG1) {
417 template <
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
418 static void integrate_impl(
const Eigen::MatrixBase<ConfigIn_t> & q,
419 const Eigen::MatrixBase<Velocity_t> & v,
420 const Eigen::MatrixBase<ConfigOut_t> & qout)
422 ConstQuaternionMap_t quat(q.derived().data());
424 QuaternionMap_t quat_map(PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout).data());
427 quat_map = quat * pOmega;
432 template <
class Config_t,
class Jacobian_t>
433 static void integrateCoeffWiseJacobian_impl(
const Eigen::MatrixBase<Config_t> & q,
434 const Eigen::MatrixBase<Jacobian_t> & J)
436 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
438 typedef typename PINOCCHIO_EIGEN_PLAIN_TYPE(Jacobian_t) JacobianPlainType;
439 typedef typename SE3::Vector3 Vector3;
440 typedef typename SE3::Matrix3 Matrix3;
442 ConstQuaternionMap_t quat_map(q.derived().data());
445 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
446 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
447 Eigen::Matrix<Scalar,NQ,NV,JacobianPlainType::Options|Eigen::RowMajor> Jexp3QuatCoeffWise;
454 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
457 if(quat_map.coeffs()[3] >= 0.)
458 PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J).noalias() = Jexp3QuatCoeffWise * Jlog;
460 PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J).noalias() = -Jexp3QuatCoeffWise * Jlog;
465 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
466 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
467 const Eigen::MatrixBase<Tangent_t> & v,
468 const Eigen::MatrixBase<JacobianOut_t> & J,
469 const AssignmentOperatorType op=SETTO)
471 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
484 assert(
false &&
"Wrong Op requesed value");
489 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
490 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
491 const Eigen::MatrixBase<Tangent_t> & v,
492 const Eigen::MatrixBase<JacobianOut_t> & J,
493 const AssignmentOperatorType op=SETTO)
498 Jexp3<SETTO>(v, J.derived());
501 Jexp3<ADDTO>(v, J.derived());
504 Jexp3<RMTO>(v, J.derived());
507 assert(
false &&
"Wrong Op requesed value");
512 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
513 static void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
514 const Eigen::MatrixBase<Tangent_t> & v,
515 const Eigen::MatrixBase<JacobianIn_t> & Jin,
516 const Eigen::MatrixBase<JacobianOut_t> & J_out)
518 typedef typename SE3::Matrix3 Matrix3;
519 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J_out);
520 const Matrix3 Jtmp3 =
exp3(-v);
521 Jout.noalias() = Jtmp3 * Jin;
524 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
525 static void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
526 const Eigen::MatrixBase<Tangent_t> & v,
527 const Eigen::MatrixBase<JacobianIn_t> & Jin,
528 const Eigen::MatrixBase<JacobianOut_t> & J_out)
530 typedef typename SE3::Matrix3 Matrix3;
531 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J_out);
532 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
533 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
535 Jexp3<SETTO>(v, Jtmp3);
536 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
537 Jout.noalias() = Jtmp3 * Jin;
540 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
541 static void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
542 const Eigen::MatrixBase<Tangent_t> & v,
543 const Eigen::MatrixBase<Jacobian_t> & J_out)
545 typedef typename SE3::Matrix3 Matrix3;
546 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J_out);
547 const Matrix3 Jtmp3 =
exp3(-v);
551 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
552 static void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
553 const Eigen::MatrixBase<Tangent_t> & v,
554 const Eigen::MatrixBase<Jacobian_t> & J_out)
556 typedef typename SE3::Matrix3 Matrix3;
557 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J_out);
558 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
559 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
561 Jexp3<SETTO>(v, Jtmp3);
562 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
567 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
568 static void interpolate_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
569 const Eigen::MatrixBase<ConfigR_t> & q1,
571 const Eigen::MatrixBase<ConfigOut_t> & qout)
573 ConstQuaternionMap_t quat0 (q0.derived().data());
575 ConstQuaternionMap_t quat1 (q1.derived().data());
578 QuaternionMap_t quat_map(PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout).data());
580 quat_map = quat0.slerp(u, quat1);
584 template <
class ConfigL_t,
class ConfigR_t>
585 static Scalar squaredDistance_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
586 const Eigen::MatrixBase<ConfigR_t> & q1)
588 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
589 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
591 difference_impl(q0, q1, t);
592 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
593 return t.squaredNorm();
596 template <
class Config_t>
597 static void normalize_impl(
const Eigen::MatrixBase<Config_t> & qout)
599 Config_t & qout_ = PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout);
603 template <
class Config_t>
604 static bool isNormalized_impl (
const Eigen::MatrixBase<Config_t> & qin,
607 const Scalar norm = qin.norm();
609 return abs(norm - Scalar(1.0)) < prec;
612 template <
class Config_t>
613 static void random_impl(
const Eigen::MatrixBase<Config_t> & qout)
615 QuaternionMap_t quat_map(PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout).data());
621 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
622 static void randomConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> &,
623 const Eigen::MatrixBase<ConfigR_t> &,
624 const Eigen::MatrixBase<ConfigOut_t> & qout)
629 template <
class ConfigL_t,
class ConfigR_t>
630 static bool isSameConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
631 const Eigen::MatrixBase<ConfigR_t> & q1,
634 ConstQuaternionMap_t quat1(q0.derived().data());
636 ConstQuaternionMap_t quat2(q1.derived().data());
645 #endif // ifndef __pinocchio_multibody_liegroup_special_orthogonal_operation_hpp__