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>
37 template<
typename _Scalar,
int _Options >
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>
58 log(
const Eigen::MatrixBase<Matrix2Like> & R)
61 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like,2,2);
63 const Scalar tr = R.trace();
65 static const Scalar PI_value = PI<Scalar>();
75 asin((R(1,0) - R(0,1)) /
Scalar(2)),
92 assert (theta == theta);
98 template<
typename Matrix2Like>
100 Jlog(
const Eigen::MatrixBase<Matrix2Like> &)
103 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like,2,2);
130 return std::string(
"SO(2)");
133 template <
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
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);
145 template <ArgumentPosition arg,
class ConfigL_t,
class ConfigR_t,
class JacobianOut_t>
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);
159 template <
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
161 const Eigen::MatrixBase<Velocity_t> &
v,
162 const Eigen::MatrixBase<ConfigOut_t> & qout)
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>
183 const Eigen::MatrixBase<Jacobian_t> &
J)
185 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
190 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
192 const Eigen::MatrixBase<Tangent_t> & ,
193 const Eigen::MatrixBase<JacobianOut_t> &
J,
209 assert(
false &&
"Wrong Op requesed value");
214 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
216 const Eigen::MatrixBase<Tangent_t> & ,
217 const Eigen::MatrixBase<JacobianOut_t> &
J,
233 assert(
false &&
"Wrong Op requesed value");
238 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
240 const Eigen::MatrixBase<Tangent_t> & ,
241 const Eigen::MatrixBase<JacobianIn_t> & Jin,
242 const Eigen::MatrixBase<JacobianOut_t> & Jout)
const 247 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
249 const Eigen::MatrixBase<Tangent_t> & ,
250 const Eigen::MatrixBase<JacobianIn_t> & Jin,
251 const Eigen::MatrixBase<JacobianOut_t> & Jout)
const 256 template <
class Config_t,
class Tangent_t,
class Jacobian_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>
263 const Eigen::MatrixBase<Tangent_t> & ,
264 const Eigen::MatrixBase<Jacobian_t> & )
const {}
268 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
270 const Eigen::MatrixBase<ConfigR_t> &
q1,
272 const Eigen::MatrixBase<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);
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;
297 SINCOS(theta0,&out[1],&out[0]);
301 template <
class Config_t>
308 template <
class Config_t>
312 const Scalar norm = qin.norm();
314 return abs(norm -
Scalar(1.0)) < prec;
317 template <
class Config_t>
322 const Scalar PI_value = PI<Scalar>();
324 SINCOS(angle, &out(1), &out(0));
327 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
329 const Eigen::MatrixBase<ConfigR_t> &,
330 const Eigen::MatrixBase<ConfigOut_t> & qout)
const 336 template<
typename _Scalar,
int _Options>
338 :
public LieGroupBase< SpecialOrthogonalOperationTpl<3,_Scalar,_Options> >
371 return std::string(
"SO(3)");
374 template <
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
376 const Eigen::MatrixBase<ConfigR_t> &
q1,
377 const Eigen::MatrixBase<Tangent_t> &
d)
379 ConstQuaternionMap_t quat0 (q0.derived().data());
381 ConstQuaternionMap_t quat1 (q1.derived().data());
385 =
log3((quat0.matrix().transpose() * quat1.matrix()).eval());
388 template <ArgumentPosition arg,
class ConfigL_t,
class ConfigR_t,
class JacobianOut_t>
390 const Eigen::MatrixBase<ConfigR_t> &
q1,
391 const Eigen::MatrixBase<JacobianOut_t> &
J)
const 395 ConstQuaternionMap_t quat0 (q0.derived().data());
397 ConstQuaternionMap_t quat1 (q1.derived().data());
400 const Matrix3
R = quat0.matrix().transpose() * quat1.matrix();
407 }
else if (arg ==
ARG1) {
412 template <
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
414 const Eigen::MatrixBase<Velocity_t> &
v,
415 const Eigen::MatrixBase<ConfigOut_t> & qout)
417 ConstQuaternionMap_t
quat(q.derived().data());
422 quat_map =
quat * pOmega;
427 template <
class Config_t,
class Jacobian_t>
429 const Eigen::MatrixBase<Jacobian_t> &
J)
431 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
437 ConstQuaternionMap_t quat_map(q.derived().data());
440 Eigen::Matrix<Scalar,NQ,NV,JacobianPlainType::Options|Eigen::RowMajor> Jexp3QuatCoeffWise;
449 if(quat_map.coeffs()[3] >= 0.)
457 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
459 const Eigen::MatrixBase<Tangent_t> &
v,
460 const Eigen::MatrixBase<JacobianOut_t> &
J,
476 assert(
false &&
"Wrong Op requesed value");
481 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
483 const Eigen::MatrixBase<Tangent_t> &
v,
484 const Eigen::MatrixBase<JacobianOut_t> &
J,
490 Jexp3<SETTO>(
v, J.derived());
493 Jexp3<ADDTO>(
v, J.derived());
496 Jexp3<RMTO>(
v, J.derived());
499 assert(
false &&
"Wrong Op requesed value");
504 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
506 const Eigen::MatrixBase<Tangent_t> &
v,
507 const Eigen::MatrixBase<JacobianIn_t> & Jin,
508 const Eigen::MatrixBase<JacobianOut_t> & J_out)
const 512 const Matrix3 Jtmp3 =
exp3(-v);
513 Jout.noalias() = Jtmp3 * Jin;
516 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
518 const Eigen::MatrixBase<Tangent_t> &
v,
519 const Eigen::MatrixBase<JacobianIn_t> & Jin,
520 const Eigen::MatrixBase<JacobianOut_t> & J_out)
const 525 Jexp3<SETTO>(
v, Jtmp3);
526 Jout.noalias() = Jtmp3 * Jin;
529 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
531 const Eigen::MatrixBase<Tangent_t> &
v,
532 const Eigen::MatrixBase<Jacobian_t> & J_out)
const 536 const Matrix3 Jtmp3 =
exp3(-v);
540 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
542 const Eigen::MatrixBase<Tangent_t> &
v,
543 const Eigen::MatrixBase<Jacobian_t> & J_out)
const 548 Jexp3<SETTO>(
v, Jtmp3);
553 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
555 const Eigen::MatrixBase<ConfigR_t> &
q1,
557 const Eigen::MatrixBase<ConfigOut_t> & qout)
559 ConstQuaternionMap_t quat0 (q0.derived().data());
561 ConstQuaternionMap_t quat1 (q1.derived().data());
566 quat_map = quat0.slerp(u, quat1);
570 template <
class ConfigL_t,
class ConfigR_t>
572 const Eigen::MatrixBase<ConfigR_t> &
q1)
575 difference_impl(q0, q1, t);
576 return t.squaredNorm();
579 template <
class Config_t>
586 template <
class Config_t>
590 const Scalar norm = qin.norm();
592 return abs(norm -
Scalar(1.0)) < prec;
595 template <
class Config_t>
604 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
606 const Eigen::MatrixBase<ConfigR_t> &,
607 const Eigen::MatrixBase<ConfigOut_t> & qout)
const 612 template <
class ConfigL_t,
class ConfigR_t>
614 const Eigen::MatrixBase<ConfigR_t> &
q1,
617 ConstQuaternionMap_t quat1(q0.derived().data());
619 ConstQuaternionMap_t quat2(q1.derived().data());
628 #endif // ifndef __pinocchio_multibody_liegroup_special_orthogonal_operation_hpp__ Eigen::Matrix< typename Matrix3Like::Scalar, 3, 1, PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix3Like)::Options > log3(const Eigen::MatrixBase< Matrix3Like > &R, typename Matrix3Like::Scalar &theta)
Same as log3.
JointCollectionTpl const Eigen::MatrixBase< ConfigVectorType > const Eigen::MatrixBase< TangentVectorType > & v
static bool isSameConfiguration_impl(const Eigen::MatrixBase< ConfigL_t > &q0, const Eigen::MatrixBase< ConfigR_t > &q1, const Scalar &prec)
Eigen::Map< const Quaternion_t > ConstQuaternionMap_t
int nv(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointNvVisitor to get the dimension of the joint tangent space...
static void integrateCoeffWiseJacobian_impl(const Eigen::MatrixBase< Config_t > &q, const Eigen::MatrixBase< Jacobian_t > &J)
void dIntegrateTransport_dq_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &v, const Eigen::MatrixBase< JacobianIn_t > &Jin, const Eigen::MatrixBase< JacobianOut_t > &J_out) const
Eigen::Matrix< Scalar, NQ, 1, Options > ConfigVector_t
void dIntegrateTransport_dv_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &, const Eigen::MatrixBase< Jacobian_t > &) const
static bool isNormalized_impl(const Eigen::MatrixBase< Config_t > &qin, const Scalar &prec)
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.
static void difference_impl(const Eigen::MatrixBase< ConfigL_t > &q0, const Eigen::MatrixBase< ConfigR_t > &q1, const Eigen::MatrixBase< Tangent_t > &d)
void randomConfiguration_impl(const Eigen::MatrixBase< ConfigL_t > &, const Eigen::MatrixBase< ConfigR_t > &, const Eigen::MatrixBase< ConfigOut_t > &qout) const
Eigen::Matrix< Scalar, NV, NV, Options > JacobianMatrix_t
int nq(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointNqVisitor to get the dimension of the joint configuration space...
void randomConfiguration_impl(const Eigen::MatrixBase< ConfigL_t > &, const Eigen::MatrixBase< ConfigR_t > &, const Eigen::MatrixBase< ConfigOut_t > &qout) const
void Jlog3(const Scalar &theta, const Eigen::MatrixBase< Vector3Like > &log, const Eigen::MatrixBase< Matrix3Like > &Jlog)
Derivative of log3.
void dIntegrateTransport_dv_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &v, const Eigen::MatrixBase< JacobianIn_t > &Jin, const Eigen::MatrixBase< JacobianOut_t > &J_out) const
void dDifference_impl(const Eigen::MatrixBase< ConfigL_t > &q0, const Eigen::MatrixBase< ConfigR_t > &q1, const Eigen::MatrixBase< JacobianOut_t > &J) const
static void normalize_impl(const Eigen::MatrixBase< Config_t > &qout)
void dIntegrateTransport_dq_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &v, const Eigen::MatrixBase< Jacobian_t > &J_out) const
Eigen::Matrix< Scalar, NV, 1, Options > TangentVector_t
void dIntegrateTransport_dv_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &v, const Eigen::MatrixBase< Jacobian_t > &J_out) const
static void interpolate_impl(const Eigen::MatrixBase< ConfigL_t > &q0, const Eigen::MatrixBase< ConfigR_t > &q1, const Scalar &u, const Eigen::MatrixBase< ConfigOut_t > &qout)
static Index nv()
Get dimension of Lie Group tangent space.
void firstOrderNormalize(const Eigen::QuaternionBase< D > &q)
#define PINOCCHIO_LIE_GROUP_TPL_PUBLIC_INTERFACE(Derived)
static void difference_impl(const Eigen::MatrixBase< ConfigL_t > &q0, const Eigen::MatrixBase< ConfigR_t > &q1, const Eigen::MatrixBase< Tangent_t > &d)
void exp3(const Eigen::MatrixBase< Vector3Like > &v, Eigen::QuaternionBase< QuaternionLike > &quat_out)
Exp: so3 -> SO3 (quaternion)
traits< LieGroupDerived >::Scalar Scalar
JointCollectionTpl const Eigen::MatrixBase< ConfigVectorType > & q
#define PINOCCHIO_EIGEN_CONST_CAST(TYPE, OBJ)
Macro for an automatic const_cast.
void dDifference_impl(const Eigen::MatrixBase< ConfigL_t > &q0, const Eigen::MatrixBase< ConfigR_t > &q1, const Eigen::MatrixBase< JacobianOut_t > &J) const
static ConfigVector_t neutral()
void Jexp3CoeffWise(const Eigen::MatrixBase< Vector3Like > &v, const Eigen::MatrixBase< Matrix43Like > &Jexp)
Derivative of where is a small perturbation of at identity.
Eigen::Matrix< typename Vector3Like::Scalar, 3, 3, PINOCCHIO_EIGEN_PLAIN_TYPE(Vector3Like)::Options > exp3(const Eigen::MatrixBase< Vector3Like > &v)
Exp: so3 -> SO3.
static std::string name()
static Index nv()
Get dimension of Lie Group tangent space.
static void integrate_impl(const Eigen::MatrixBase< ConfigIn_t > &q, const Eigen::MatrixBase< Velocity_t > &v, const Eigen::MatrixBase< ConfigOut_t > &qout)
JointCollectionTpl const Eigen::MatrixBase< ConfigVectorIn1 > const Eigen::MatrixBase< ConfigVectorIn2 > const Scalar & u
Eigen::NumTraits< Scalar >::Real RealScalar
static void normalize_impl(const Eigen::MatrixBase< Config_t > &qout)
Eigen::Matrix< typename QuaternionLike::Scalar, 3, 1, PINOCCHIO_EIGEN_PLAIN_TYPE(typename QuaternionLike::Vector3)::Options > log3(const Eigen::QuaternionBase< QuaternionLike > &quat, typename QuaternionLike::Scalar &theta)
Same as log3 but with a unit quaternion as input.
Eigen::Map< Quaternion_t > QuaternionMap_t
static Matrix2Like::Scalar log(const Eigen::MatrixBase< Matrix2Like > &R)
void random_impl(const Eigen::MatrixBase< Config_t > &qout) const
static Matrix2Like::Scalar Jlog(const Eigen::MatrixBase< Matrix2Like > &)
static void dIntegrate_dq_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &, const Eigen::MatrixBase< JacobianOut_t > &J, const AssignmentOperatorType op=SETTO)
static Scalar squaredDistance_impl(const Eigen::MatrixBase< ConfigL_t > &q0, const Eigen::MatrixBase< ConfigR_t > &q1)
static void interpolate_impl(const Eigen::MatrixBase< ConfigL_t > &q0, const Eigen::MatrixBase< ConfigR_t > &q1, const Scalar &u, const Eigen::MatrixBase< ConfigOut_t > &qout)
JointCollectionTpl const Eigen::MatrixBase< ConfigVectorIn1 > const Eigen::MatrixBase< ConfigVectorIn2 > & q1
static std::string name()
void SINCOS(const S1 &a, S2 *sa, S3 *ca)
Computes sin/cos values of a given input scalar.
Eigen::Quaternion< Scalar > Quaternion_t
traits< SE3Tpl >::Vector3 Vector3
static void dIntegrate_dv_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &v, const Eigen::MatrixBase< JacobianOut_t > &J, const AssignmentOperatorType op=SETTO)
void uniformRandom(const Eigen::QuaternionBase< Derived > &q)
Uniformly random quaternion sphere.
static ConfigVector_t neutral()
void random_impl(const Eigen::MatrixBase< Config_t > &qout) const
Eigen::NumTraits< Scalar >::Real RealScalar
Eigen::Matrix< Scalar, 2, 2 > Matrix2
Main pinocchio namespace.
JointCollectionTpl const Eigen::MatrixBase< ConfigVectorIn1 > & q0
PINOCCHIO_EIGEN_PLAIN_TYPE(ConfigVectorType) integrate(const ModelTpl< Scalar
Integrate a configuration vector for the specified model for a tangent vector during one unit time...
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.
#define PINOCCHIO_DEFAULT_QUATERNION_NORM_TOLERANCE_VALUE
Common traits structure to fully define base classes for CRTP.
if_then_else_impl< LhsType, RhsType, ThenType, ElseType >::ReturnType if_then_else(const ComparisonOperators op, const LhsType &lhs_value, const RhsType &rhs_value, const ThenType &then_value, const ElseType &else_value)
SE3Tpl< Scalar, Options > SE3
static bool isNormalized_impl(const Eigen::MatrixBase< Config_t > &qin, const Scalar &prec)
void dIntegrateTransport_dq_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &, const Eigen::MatrixBase< Jacobian_t > &) const
static void integrateCoeffWiseJacobian_impl(const Eigen::MatrixBase< Config_t > &q, const Eigen::MatrixBase< Jacobian_t > &J)
traits< SE3Tpl >::Matrix3 Matrix3
static void integrate_impl(const Eigen::MatrixBase< ConfigIn_t > &q, const Eigen::MatrixBase< Velocity_t > &v, const Eigen::MatrixBase< ConfigOut_t > &qout)
void dIntegrateTransport_dv_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &, const Eigen::MatrixBase< JacobianIn_t > &Jin, const Eigen::MatrixBase< JacobianOut_t > &Jout) const
static void dIntegrate_dv_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &, const Eigen::MatrixBase< JacobianOut_t > &J, const AssignmentOperatorType op=SETTO)
void dIntegrateTransport_dq_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &, const Eigen::MatrixBase< JacobianIn_t > &Jin, const Eigen::MatrixBase< JacobianOut_t > &Jout) const
static void dIntegrate_dq_impl(const Eigen::MatrixBase< Config_t > &, const Eigen::MatrixBase< Tangent_t > &v, const Eigen::MatrixBase< JacobianOut_t > &J, const AssignmentOperatorType op=SETTO)