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) - 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 void dDifference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
147 const Eigen::MatrixBase<ConfigR_t> & q1,
148 const Eigen::MatrixBase<JacobianOut_t> & J)
const 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;
181 template <
class Config_t,
class Jacobian_t>
182 static void integrateCoeffWiseJacobian_impl(
const Eigen::MatrixBase<Config_t> & q,
183 const Eigen::MatrixBase<Jacobian_t> & J)
185 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
186 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J);
190 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
191 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
192 const Eigen::MatrixBase<Tangent_t> & ,
193 const Eigen::MatrixBase<JacobianOut_t> & J,
194 const AssignmentOperatorType op=SETTO)
196 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
200 Jout(0,0) = Scalar(1);
203 Jout(0,0) += Scalar(1);
206 Jout(0,0) -= Scalar(1);
209 assert(
false &&
"Wrong Op requesed value");
214 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
215 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
216 const Eigen::MatrixBase<Tangent_t> & ,
217 const Eigen::MatrixBase<JacobianOut_t> & J,
218 const AssignmentOperatorType op=SETTO)
220 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
224 Jout(0,0) = Scalar(1);
227 Jout(0,0) += Scalar(1);
230 Jout(0,0) -= Scalar(1);
233 assert(
false &&
"Wrong Op requesed value");
238 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
239 void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
240 const Eigen::MatrixBase<Tangent_t> & ,
241 const Eigen::MatrixBase<JacobianIn_t> & Jin,
242 const Eigen::MatrixBase<JacobianOut_t> & Jout)
const 244 PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,Jout) = Jin;
247 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
248 void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
249 const Eigen::MatrixBase<Tangent_t> & ,
250 const Eigen::MatrixBase<JacobianIn_t> & Jin,
251 const Eigen::MatrixBase<JacobianOut_t> & Jout)
const 253 PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,Jout) = Jin;
256 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
257 void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
258 const Eigen::MatrixBase<Tangent_t> & ,
259 const Eigen::MatrixBase<Jacobian_t> & )
const {}
261 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
262 void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
263 const Eigen::MatrixBase<Tangent_t> & ,
264 const Eigen::MatrixBase<Jacobian_t> & )
const {}
268 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
269 static void interpolate_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
270 const Eigen::MatrixBase<ConfigR_t> & q1,
272 const Eigen::MatrixBase<ConfigOut_t>& qout)
274 ConfigOut_t & out = PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout);
276 assert ( std::abs(q0.norm() - 1) < 1e-8 &&
"initial configuration not normalized");
277 assert ( std::abs(q1.norm() - 1) < 1e-8 &&
"final configuration not normalized");
278 Scalar cosTheta = q0.dot(q1);
279 Scalar sinTheta = q0(0)*q1(1) - q0(1)*q1(0);
280 Scalar theta = atan2(sinTheta, cosTheta);
281 assert (fabs (sin (theta) - sinTheta) < 1e-8);
283 const Scalar PI_value = PI<Scalar>();
285 if (fabs (theta) > 1e-6 && fabs (theta) < PI_value - 1e-6)
287 out = (sin ((1-u)*theta)/sinTheta) * q0
288 + (sin ( u *theta)/sinTheta) * q1;
290 else if (fabs (theta) < 1e-6)
292 out = (1-u) * q0 + u * q1;
296 Scalar theta0 = atan2 (q0(1), q0(0));
297 SINCOS(theta0,&out[1],&out[0]);
301 template <
class Config_t>
302 static void normalize_impl (
const Eigen::MatrixBase<Config_t> & qout)
304 Config_t & qout_ = PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout).derived();
308 template <
class Config_t>
309 void random_impl (
const Eigen::MatrixBase<Config_t>& qout)
const 311 Config_t & out = PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout);
313 const Scalar PI_value = PI<Scalar>();
314 const Scalar angle = -PI_value + Scalar(2)* PI_value * ((Scalar)rand())/RAND_MAX;
315 SINCOS(angle, &out(1), &out(0));
318 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
319 void randomConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> &,
320 const Eigen::MatrixBase<ConfigR_t> &,
321 const Eigen::MatrixBase<ConfigOut_t> & qout)
const 327 template<
typename _Scalar,
int _Options>
329 :
public LieGroupBase< SpecialOrthogonalOperationTpl<3,_Scalar,_Options> >
333 typedef Eigen::Quaternion<Scalar> Quaternion_t;
334 typedef Eigen::Map< Quaternion_t> QuaternionMap_t;
335 typedef Eigen::Map<const Quaternion_t> ConstQuaternionMap_t;
337 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
354 static ConfigVector_t
neutral()
356 ConfigVector_t n; n.setZero (); n[3] = Scalar(1);
360 static std::string
name()
362 return std::string(
"SO(3)");
365 template <
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
366 static void difference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
367 const Eigen::MatrixBase<ConfigR_t> & q1,
368 const Eigen::MatrixBase<Tangent_t> & d)
370 ConstQuaternionMap_t quat0 (q0.derived().data());
372 ConstQuaternionMap_t quat1 (q1.derived().data());
375 PINOCCHIO_EIGEN_CONST_CAST(Tangent_t,d)
376 =
log3((quat0.matrix().transpose() * quat1.matrix()).eval());
379 template <ArgumentPosition arg,
class ConfigL_t,
class ConfigR_t,
class JacobianOut_t>
380 void dDifference_impl (
const Eigen::MatrixBase<ConfigL_t> & q0,
381 const Eigen::MatrixBase<ConfigR_t> & q1,
382 const Eigen::MatrixBase<JacobianOut_t> & J)
const 384 typedef typename SE3::Matrix3 Matrix3;
386 ConstQuaternionMap_t quat0 (q0.derived().data());
388 ConstQuaternionMap_t quat1 (q1.derived().data());
391 const Matrix3 R = quat0.matrix().transpose() * quat1.matrix();
397 PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J).noalias() = - J1 * R.transpose();
398 }
else if (arg == ARG1) {
403 template <
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
404 static void integrate_impl(
const Eigen::MatrixBase<ConfigIn_t> & q,
405 const Eigen::MatrixBase<Velocity_t> & v,
406 const Eigen::MatrixBase<ConfigOut_t> & qout)
408 ConstQuaternionMap_t quat(q.derived().data());
410 QuaternionMap_t quat_map(PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout).data());
413 quat_map = quat * pOmega;
418 template <
class Config_t,
class Jacobian_t>
419 static void integrateCoeffWiseJacobian_impl(
const Eigen::MatrixBase<Config_t> & q,
420 const Eigen::MatrixBase<Jacobian_t> & J)
422 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
424 typedef typename PINOCCHIO_EIGEN_PLAIN_TYPE(Jacobian_t) JacobianPlainType;
425 typedef typename SE3::Vector3 Vector3;
426 typedef typename SE3::Matrix3 Matrix3;
428 ConstQuaternionMap_t quat_map(q.derived().data());
431 Eigen::Matrix<Scalar,NQ,NV,JacobianPlainType::Options|Eigen::RowMajor> Jexp3QuatCoeffWise;
440 if(quat_map.coeffs()[3] >= 0.)
441 PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J).noalias() = Jexp3QuatCoeffWise * Jlog;
443 PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J).noalias() = -Jexp3QuatCoeffWise * Jlog;
448 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
449 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
450 const Eigen::MatrixBase<Tangent_t> & v,
451 const Eigen::MatrixBase<JacobianOut_t> & J,
452 const AssignmentOperatorType op=SETTO)
454 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
467 assert(
false &&
"Wrong Op requesed value");
472 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
473 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
474 const Eigen::MatrixBase<Tangent_t> & v,
475 const Eigen::MatrixBase<JacobianOut_t> & J,
476 const AssignmentOperatorType op=SETTO)
481 Jexp3<SETTO>(v, J.derived());
484 Jexp3<ADDTO>(v, J.derived());
487 Jexp3<RMTO>(v, J.derived());
490 assert(
false &&
"Wrong Op requesed value");
495 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
496 void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
497 const Eigen::MatrixBase<Tangent_t> & v,
498 const Eigen::MatrixBase<JacobianIn_t> & Jin,
499 const Eigen::MatrixBase<JacobianOut_t> & J_out)
const 501 typedef typename SE3::Matrix3 Matrix3;
502 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J_out);
503 const Matrix3 Jtmp3 =
exp3(-v);
504 Jout.noalias() = Jtmp3 * Jin;
507 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
508 void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
509 const Eigen::MatrixBase<Tangent_t> & v,
510 const Eigen::MatrixBase<JacobianIn_t> & Jin,
511 const Eigen::MatrixBase<JacobianOut_t> & J_out)
const 513 typedef typename SE3::Matrix3 Matrix3;
514 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J_out);
516 Jexp3<SETTO>(v, Jtmp3);
517 Jout.noalias() = Jtmp3 * Jin;
520 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
521 void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
522 const Eigen::MatrixBase<Tangent_t> & v,
523 const Eigen::MatrixBase<Jacobian_t> & J_out)
const 525 typedef typename SE3::Matrix3 Matrix3;
526 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J_out);
527 const Matrix3 Jtmp3 =
exp3(-v);
531 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
532 void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
533 const Eigen::MatrixBase<Tangent_t> & v,
534 const Eigen::MatrixBase<Jacobian_t> & J_out)
const 536 typedef typename SE3::Matrix3 Matrix3;
537 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J_out);
539 Jexp3<SETTO>(v, Jtmp3);
544 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
545 static void interpolate_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
546 const Eigen::MatrixBase<ConfigR_t> & q1,
548 const Eigen::MatrixBase<ConfigOut_t> & qout)
550 ConstQuaternionMap_t quat0 (q0.derived().data());
552 ConstQuaternionMap_t quat1 (q1.derived().data());
555 QuaternionMap_t quat_map(PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout).data());
557 quat_map = quat0.slerp(u, quat1);
561 template <
class ConfigL_t,
class ConfigR_t>
562 static Scalar squaredDistance_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
563 const Eigen::MatrixBase<ConfigR_t> & q1)
566 difference_impl(q0, q1, t);
567 return t.squaredNorm();
570 template <
class Config_t>
571 static void normalize_impl(
const Eigen::MatrixBase<Config_t> & qout)
573 Config_t & qout_ = PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout);
577 template <
class Config_t>
578 void random_impl(
const Eigen::MatrixBase<Config_t> & qout)
const 580 QuaternionMap_t quat_map(PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout).data());
586 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
587 void randomConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> &,
588 const Eigen::MatrixBase<ConfigR_t> &,
589 const Eigen::MatrixBase<ConfigOut_t> & qout)
const 594 template <
class ConfigL_t,
class ConfigR_t>
595 static bool isSameConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
596 const Eigen::MatrixBase<ConfigR_t> & q1,
599 ConstQuaternionMap_t quat1(q0.derived().data());
601 ConstQuaternionMap_t quat2(q1.derived().data());
610 #endif // ifndef __pinocchio_multibody_liegroup_special_orthogonal_operation_hpp__ int nv(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointNvVisitor to get the dimension of the joint tangent space...
Eigen::Matrix< typename Matrix3Like::Scalar, 3, 1, Matrix3Like ::Options > log3(const Eigen::MatrixBase< Matrix3Like > &R, typename Matrix3Like::Scalar &theta)
Same as log3.
bool defineSameRotation(const Eigen::QuaternionBase< D1 > &q1, const Eigen::QuaternionBase< D2 > &q2, const typename D1::RealScalar &prec=Eigen::NumTraits< typename D1::Scalar >::dummy_precision())
Check if two quaternions define the same rotations.
int nq(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointNqVisitor to get the dimension of the joint configuration space...
void Jlog3(const Scalar &theta, const Eigen::MatrixBase< Vector3Like > &log, const Eigen::MatrixBase< Matrix3Like > &Jlog)
Derivative of log3.
Eigen::Matrix< typename Vector3Like::Scalar, 3, 3, Vector3Like ::Options > exp3(const Eigen::MatrixBase< Vector3Like > &v)
Exp: so3 -> SO3.
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)
void exp3(const Eigen::MatrixBase< Vector3Like > &v, Eigen::QuaternionBase< QuaternionLike > &quat_out)
Exp: so3 -> SO3 (quaternion)
void Jexp3CoeffWise(const Eigen::MatrixBase< Vector3Like > &v, const Eigen::MatrixBase< Matrix43Like > &Jexp)
Derivative of where is a small perturbation of at identity.
static Index nv()
Get dimension of Lie Group tangent space.
static Index nv()
Get dimension of Lie Group tangent space.
void SINCOS(const S1 &a, S2 *sa, S3 *ca)
Computes sin/cos values of a given input scalar.
void uniformRandom(const Eigen::QuaternionBase< Derived > &q)
Uniformly random quaternion sphere.
Main pinocchio namespace.
void neutral(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ReturnType > &qout)
Return the neutral configuration element related to the model configuration space.
bool isNormalized(const Eigen::QuaternionBase< Quaternion > &quat, const typename Quaternion::Coefficients::RealScalar &prec=Eigen::NumTraits< typename Quaternion::Coefficients::RealScalar >::dummy_precision())
Check whether the input quaternion is Normalized within the given precision.
Common traits structure to fully define base classes for CRTP.