5 #ifndef __pinocchio_special_euclidean_operation_hpp__ 6 #define __pinocchio_special_euclidean_operation_hpp__ 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" 15 #include "pinocchio/multibody/liegroup/vector-space.hpp" 16 #include "pinocchio/multibody/liegroup/cartesian-product.hpp" 17 #include "pinocchio/multibody/liegroup/special-orthogonal.hpp" 21 template<
int Dim,
typename Scalar,
int Options = 0>
25 template<
int Dim,
typename Scalar,
int Options>
29 template<
typename _Scalar,
int _Options>
32 typedef _Scalar Scalar;
42 template<
typename _Scalar,
int _Options>
44 :
public LieGroupBase <SpecialEuclideanOperationTpl<2,_Scalar,_Options> >
52 typedef Eigen::Matrix<Scalar,2,2,Options> Matrix2;
53 typedef Eigen::Matrix<Scalar,2,1,Options> Vector2;
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)
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);
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;
69 if (math::fabs(omega) > 1e-14)
71 typename PINOCCHIO_EIGEN_PLAIN_TYPE(Vector2Like) vcross(-v(1), v(0));
73 PINOCCHIO_EIGEN_CONST_CAST(Vector2Like,t).noalias() = vcross - R * vcross;
77 PINOCCHIO_EIGEN_CONST_CAST(Vector2Like,t) = v.template head<2>();
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)
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);
90 typedef typename Matrix3Like::Scalar Scalar;
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;
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)
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);
109 TangentVector & vout = PINOCCHIO_EIGEN_CONST_CAST(TangentVector,v);
111 typedef typename Matrix2Like::Scalar Scalar1;
113 Scalar1 t = SO2_t::log(R);
114 const Scalar1 tabs = math::fabs(t);
115 const Scalar1 t2 = t*t;
119 alpha = 1 - t2/12 - t2*t2/720;
123 Scalar1 st,ct;
SINCOS(tabs, &st, &ct);
124 alpha = tabs*st/(2*(1-ct));
127 vout.template head<2>().noalias() = alpha * p;
128 vout(0) += t/2 * p(1);
129 vout(1) += -t/2 * p(0);
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)
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);
142 JacobianOutLike & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOutLike,J);
144 typedef typename Matrix2Like::Scalar Scalar1;
146 Scalar1 t = SO2_t::log(R);
147 const Scalar1 tabs = math::fabs(t);
148 Scalar1 alpha, alpha_dot;
153 alpha_dot = - t / 6 - t2*t / 180;
157 Scalar1 st,ct;
SINCOS(t, &st, &ct);
158 Scalar1 inv_2_1_ct = 0.5 / (1-ct);
160 alpha = t*st*inv_2_1_ct;
162 alpha_dot = (st-t) * inv_2_1_ct;
165 typename PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix2Like) V;
166 V(0,0) = V(1,1) = alpha;
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();
190 static ConfigVector_t
neutral()
192 ConfigVector_t n; n << Scalar(0), Scalar(0), Scalar(1), Scalar(0);
196 static std::string
name()
198 return std::string(
"SE(2)");
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)
208 PINOCCHIO_EIGEN_CONST_CAST(Tangent_t,d).setZero();
211 Matrix2 R0, R1; Vector2 t0, t1;
214 Matrix2 R (R0.transpose() * R1);
215 Vector2 t (R0.transpose() * (t1 - t0));
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 225 Matrix2 R0, R1; Vector2 t0, t1;
228 Matrix2 R (R0.transpose() * R1);
229 Vector2 t (R0.transpose() * (t1 - t0));
236 Vector2 pcross (q1(1) - q0(1), q0(0) - q1(0));
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();
243 J0.applyOnTheLeft(J1);
244 }
else if (arg == ARG1) {
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)
254 ConfigOut_t & out = PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout);
261 out.template head<2>().noalias() = R0 * t + t0;
262 out.template tail<2>().noalias() = R0 * R.col(0);
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)
269 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
271 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J);
274 const typename Config_t::Scalar & c_theta = q(2),
277 Jout.template topLeftCorner<2,2>() << c_theta, -s_theta, s_theta, c_theta;
278 Jout.template bottomRightCorner<2,1>() << -s_theta, c_theta;
281 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
282 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
283 const Eigen::MatrixBase<Tangent_t> & v,
284 const Eigen::MatrixBase<JacobianOut_t>& J)
286 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
292 toInverseActionMatrix(R, t, Jout);
295 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
296 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
297 const Eigen::MatrixBase<Tangent_t> & v,
298 const Eigen::MatrixBase<JacobianOut_t> & J)
300 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
303 Eigen::Matrix<Scalar,6,6> Jtmp6;
305 Jout << Jtmp6.template topLeftCorner<2,2>(), Jtmp6.template topRightCorner<2,1>(),
306 Jtmp6.template bottomLeftCorner<1,2>(), Jtmp6.template bottomRightCorner<1,1>();
319 template <
class Config_t>
320 static void normalize_impl (
const Eigen::MatrixBase<Config_t>& qout)
322 PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout).template tail<2>().
normalize();
325 template <
class Config_t>
326 void random_impl (
const Eigen::MatrixBase<Config_t>& qout)
const 328 R2crossSO2_t().random(qout);
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)
337 R2crossSO2_t ().randomConfiguration(lower, upper, qout);
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,
345 return R2crossSO2_t().isSameConfiguration(q0, q1, prec);
350 template<
typename Matrix2Like,
typename Vector2Like,
typename Vector4Like>
352 const Eigen::MatrixBase<Vector2Like> & t,
353 const Eigen::MatrixBase<Vector4Like> & q)
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);
359 PINOCCHIO_EIGEN_CONST_CAST(Vector2Like,t) = q.template head<2>();
360 const typename Vector4Like::Scalar & c_theta = q(2),
362 PINOCCHIO_EIGEN_CONST_CAST(Matrix2Like,R) << c_theta, -s_theta, s_theta, c_theta;
367 template<
typename _Scalar,
int _Options>
370 typedef _Scalar Scalar;
380 template<
typename _Scalar,
int _Options>
382 :
public LieGroupBase <SpecialEuclideanOperationTpl<3,_Scalar,_Options> >
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;
408 static ConfigVector_t
neutral()
410 ConfigVector_t n; n.template head<6>().setZero(); n[6] = 1;
414 static std::string
name()
416 return std::string(
"SE(3)");
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)
426 PINOCCHIO_EIGEN_CONST_CAST(Tangent_t,d).setZero();
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();
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 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()),
445 SE3 M ( SE3(R0, q0.derived().template head<3>()).inverse()
446 * SE3(R1, q1.derived().template head<3>()));
452 typename SE3::Vector3 p1_p0 ( q1.derived().template head<3>()
453 - q0.derived().template head<3>());
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) {
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)
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());
475 SE3 M0 (quat.matrix(), q.derived().template head<3>());
477 SE3 M1 (M0 *
exp6(mref_v));
479 out.template head<3>() = M1.translation();
480 res_quat = M1.rotation();
481 if(res_quat.dot(quat) < 0) res_quat.coeffs() *= -1.;
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)
491 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
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);
499 ConstQuaternionMap_t quat_map(q.derived().template tail<4>().data());
500 Jout.template topLeftCorner<3,3>() = quat_map.toRotationMatrix();
503 typedef Eigen::Matrix<Scalar,4,3,JacobianPlainType::Options|Eigen::RowMajor> Jacobian43;
505 Jacobian43 Jexp3QuatCoeffWise;
510 typename SE3::Matrix3 Jlog;
517 if(quat_map.coeffs()[3] >= 0.)
518 PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J).template bottomRightCorner<4,3>().noalias() = Jexp3QuatCoeffWise * Jlog;
520 PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J).template bottomRightCorner<4,3>().noalias() = -Jexp3QuatCoeffWise * Jlog;
523 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
524 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
525 const Eigen::MatrixBase<Tangent_t> & v,
526 const Eigen::MatrixBase<JacobianOut_t>& J)
528 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
532 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
533 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
534 const Eigen::MatrixBase<Tangent_t> & v,
535 const Eigen::MatrixBase<JacobianOut_t>& J)
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)
554 difference_impl(q0, q1, t);
555 return t.squaredNorm();
558 template <
class Config_t>
559 static void normalize_impl (
const Eigen::MatrixBase<Config_t>& qout)
561 Config_t& qout_ = (
const_cast< Eigen::MatrixBase<Config_t>&
>(qout)).derived();
565 template <
class Config_t>
566 void random_impl (
const Eigen::MatrixBase<Config_t>& qout)
const 568 R3crossSO3_t().random(qout);
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)
577 R3crossSO3_t ().randomConfiguration(lower, upper, qout);
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,
585 return R3crossSO3_t().isSameConfiguration(q0, q1, prec);
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)
void Jlog6(const SE3Tpl< Scalar, Options > &M, const Eigen::MatrixBase< Matrix6Like > &Jlog)
Derivative of log6 where and .
MotionTpl< Scalar, Options > log6(const SE3Tpl< Scalar, Options > &M)
Log: SE3 -> se3.
void SINCOS(const Scalar &a, Scalar *sa, Scalar *ca)
Computes sin/cos values of a given input scalar.
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.
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.
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.
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...
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.