5 #ifndef __pinocchio_multibody_liegroup_special_euclidean_operation_hpp__
6 #define __pinocchio_multibody_liegroup_special_euclidean_operation_hpp__
10 #include "pinocchio/macros.hpp"
11 #include "pinocchio/math/quaternion.hpp"
12 #include "pinocchio/spatial/fwd.hpp"
13 #include "pinocchio/utils/static-if.hpp"
14 #include "pinocchio/spatial/se3.hpp"
15 #include "pinocchio/multibody/liegroup/liegroup-base.hpp"
17 #include "pinocchio/multibody/liegroup/vector-space.hpp"
18 #include "pinocchio/multibody/liegroup/cartesian-product.hpp"
19 #include "pinocchio/multibody/liegroup/special-orthogonal.hpp"
23 template<
int Dim,
typename Scalar,
int Options = 0>
27 template<
int Dim,
typename Scalar,
int Options>
31 template<
typename _Scalar,
int _Options>
34 typedef _Scalar Scalar;
44 template<
typename _Scalar,
int _Options>
46 :
public LieGroupBase <SpecialEuclideanOperationTpl<2,_Scalar,_Options> >
54 typedef Eigen::Matrix<Scalar,2,2,Options> Matrix2;
55 typedef Eigen::Matrix<Scalar,2,1,Options> Vector2;
57 template<
typename TangentVector,
typename Matrix2Like,
typename Vector2Like>
58 static void exp(
const Eigen::MatrixBase<TangentVector> & v,
59 const Eigen::MatrixBase<Matrix2Like> & R,
60 const Eigen::MatrixBase<Vector2Like> & t)
62 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(TangentVector_t,TangentVector);
63 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like, 2, 2);
64 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2Like, 2);
66 typedef typename Matrix2Like::Scalar Scalar;
67 const Scalar omega = v(2);
68 Scalar cv,sv;
SINCOS(omega, &sv, &cv);
69 PINOCCHIO_EIGEN_CONST_CAST(Matrix2Like,R) << cv, -sv, sv, cv;
70 using internal::if_then_else;
73 typename PINOCCHIO_EIGEN_PLAIN_TYPE(Vector2Like) vcross(-v(1), v(0));
74 vcross -= -v(1)*R.col(0) + v(0)*R.col(1);
76 Scalar omega_abs = math::fabs(omega);
77 PINOCCHIO_EIGEN_CONST_CAST(Vector2Like,t).coeffRef(0) = if_then_else(internal::GT, omega_abs , Scalar(1e-14),
81 PINOCCHIO_EIGEN_CONST_CAST(Vector2Like,t).coeffRef(1) = if_then_else(internal::GT, omega_abs, Scalar(1e-14),
88 template<
typename Matrix2Like,
typename Vector2Like,
typename Matrix3Like>
89 static void toInverseActionMatrix(
const Eigen::MatrixBase<Matrix2Like> & R,
90 const Eigen::MatrixBase<Vector2Like> & t,
91 const Eigen::MatrixBase<Matrix3Like> & M,
92 const AssignmentOperatorType op)
94 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like, 2, 2);
95 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2Like, 2);
96 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix3Like, M, 3, 3);
97 Matrix3Like & Mout = PINOCCHIO_EIGEN_CONST_CAST(Matrix3Like,M);
98 typedef typename Matrix3Like::Scalar Scalar;
100 typename PINOCCHIO_EIGEN_PLAIN_TYPE(Vector2Like) tinv((R.transpose() * t).reverse());
101 tinv[0] *= Scalar(-1.);
105 Mout.template topLeftCorner<2,2>() = R.transpose();
106 Mout.template topRightCorner<2,1>() = tinv;
107 Mout.template bottomLeftCorner<1,2>().setZero();
108 Mout(2,2) = (Scalar)1;
111 Mout.template topLeftCorner<2,2>() += R.transpose();
112 Mout.template topRightCorner<2,1>() += tinv;
113 Mout(2,2) += (Scalar)1;
116 Mout.template topLeftCorner<2,2>() -= R.transpose();
117 Mout.template topRightCorner<2,1>() -= tinv;
118 Mout(2,2) -= (Scalar)1;
121 assert(
false &&
"Wrong Op requesed value");
129 template<
typename Matrix2Like,
typename Vector2Like,
typename TangentVector>
130 static void log(
const Eigen::MatrixBase<Matrix2Like> & R,
131 const Eigen::MatrixBase<Vector2Like> & p,
132 const Eigen::MatrixBase<TangentVector> & v)
134 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like, 2, 2);
135 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2Like, 2);
136 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(TangentVector_t,TangentVector);
138 TangentVector & vout = PINOCCHIO_EIGEN_CONST_CAST(TangentVector,v);
140 typedef typename Matrix2Like::Scalar Scalar1;
142 Scalar1 t = SO2_t::log(R);
143 const Scalar1 tabs = math::fabs(t);
144 const Scalar1 t2 = t*t;
145 Scalar1 st,ct;
SINCOS(tabs, &st, &ct);
147 alpha = internal::if_then_else(internal::LT, tabs, Scalar(1e-4),
148 1 - t2/12 - t2*t2/720,
151 vout.template head<2>().noalias() = alpha * p;
152 vout(0) += t/2 * p(1);
153 vout(1) += -t/2 * p(0);
157 template<
typename Matrix2Like,
typename Vector2Like,
typename JacobianOutLike>
158 static void Jlog(
const Eigen::MatrixBase<Matrix2Like> & R,
159 const Eigen::MatrixBase<Vector2Like> & p,
160 const Eigen::MatrixBase<JacobianOutLike> & J)
162 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like, 2, 2);
163 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector2Like, 2);
164 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(JacobianOutLike, JacobianMatrix_t);
166 JacobianOutLike & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOutLike,J);
168 typedef typename Matrix2Like::Scalar Scalar1;
170 Scalar1 t = SO2_t::log(R);
171 const Scalar1 tabs = math::fabs(t);
172 Scalar1 alpha, alpha_dot;
174 Scalar1 st,ct;
SINCOS(t, &st, &ct);
175 Scalar1 inv_2_1_ct = 0.5 / (1-ct);
177 alpha = internal::if_then_else(internal::LT, tabs, Scalar(1e-4),
180 alpha_dot = internal::if_then_else(internal::LT, tabs, Scalar(1e-4),
181 - t / 6 - t2*t / 180,
182 (st-t) * inv_2_1_ct);
184 typename PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix2Like) V;
185 V(0,0) = V(1,1) = alpha;
189 Jout.template topLeftCorner <2,2>().noalias() = V * R;
190 Jout.template topRightCorner<2,1>() << alpha_dot*p[0] + p[1]/2, -p(0)/2 + alpha_dot*p(1);
191 Jout.template bottomLeftCorner<1,2>().setZero();
209 static ConfigVector_t
neutral()
211 ConfigVector_t n; n << Scalar(0), Scalar(0), Scalar(1), Scalar(0);
215 static std::string
name()
217 return std::string(
"SE(2)");
220 template <
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
221 static void difference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
222 const Eigen::MatrixBase<ConfigR_t> & q1,
223 const Eigen::MatrixBase<Tangent_t> & d)
225 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
226 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
227 Matrix2 R0, R1; Vector2 t0, t1;
230 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
231 Matrix2 R (R0.transpose() * R1);
232 Vector2 t (R0.transpose() * (t1 - t0));
237 template <ArgumentPosition arg,
class ConfigL_t,
class ConfigR_t,
class JacobianOut_t>
238 void dDifference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
239 const Eigen::MatrixBase<ConfigR_t> & q1,
240 const Eigen::MatrixBase<JacobianOut_t>& J)
const
242 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
243 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
244 Matrix2 R0, R1; Vector2 t0, t1;
247 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
248 Matrix2 R (R0.transpose() * R1);
249 Vector2 t (R0.transpose() * (t1 - t0));
252 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
253 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
256 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
259 Vector2 pcross (q1(1) - q0(1), q0(0) - q1(0));
261 JacobianOut_t& J0 = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t, J);
262 J0.template topLeftCorner <2,2> ().noalias() = - R.transpose();
263 J0.template topRightCorner<2,1> ().noalias() = R1.transpose() * pcross;
264 J0.template bottomLeftCorner <1,2> ().setZero();
266 J0.applyOnTheLeft(J1);
267 }
else if (arg == ARG1) {
272 template <
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
273 static void integrate_impl(
const Eigen::MatrixBase<ConfigIn_t> & q,
274 const Eigen::MatrixBase<Velocity_t> & v,
275 const Eigen::MatrixBase<ConfigOut_t> & qout)
277 ConfigOut_t & out = PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout);
279 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
280 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
285 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
287 out.template head<2>().noalias() = R0 * t + t0;
288 out.template tail<2>().noalias() = R0 * R.col(0);
291 template <
class Config_t,
class Jacobian_t>
292 static void integrateCoeffWiseJacobian_impl(
const Eigen::MatrixBase<Config_t> & q,
293 const Eigen::MatrixBase<Jacobian_t> & J)
295 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
297 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J);
300 const typename Config_t::Scalar & c_theta = q(2),
303 Jout.template topLeftCorner<2,2>() << c_theta, -s_theta, s_theta, c_theta;
304 Jout.template bottomRightCorner<2,1>() << -s_theta, c_theta;
307 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
308 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
309 const Eigen::MatrixBase<Tangent_t> & v,
310 const Eigen::MatrixBase<JacobianOut_t>& J,
311 const AssignmentOperatorType op=SETTO)
313 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
315 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
316 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
320 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
322 toInverseActionMatrix(R, t, Jout, op);
325 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
326 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
327 const Eigen::MatrixBase<Tangent_t> & v,
328 const Eigen::MatrixBase<JacobianOut_t> & J,
329 const AssignmentOperatorType op=SETTO)
331 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
333 MotionTpl<Scalar,0> nu; nu.toVector() << v.template head<2>(), 0, 0, 0, v[2];
334 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
335 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
336 Eigen::Matrix<Scalar,6,6> Jtmp6;
338 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
343 Jout << Jtmp6.template topLeftCorner<2,2>(), Jtmp6.template topRightCorner<2,1>(),
344 Jtmp6.template bottomLeftCorner<1,2>(), Jtmp6.template bottomRightCorner<1,1>();
347 Jout.template topLeftCorner<2,2>() += Jtmp6.template topLeftCorner<2,2>();
348 Jout.template topRightCorner<2,1>() += Jtmp6.template topRightCorner<2,1>();
349 Jout.template bottomLeftCorner<1,2>() += Jtmp6.template bottomLeftCorner<1,2>();
350 Jout.template bottomRightCorner<1,1>() += Jtmp6.template bottomRightCorner<1,1>();
353 Jout.template topLeftCorner<2,2>() -= Jtmp6.template topLeftCorner<2,2>();
354 Jout.template topRightCorner<2,1>() -= Jtmp6.template topRightCorner<2,1>();
355 Jout.template bottomLeftCorner<1,2>() -= Jtmp6.template bottomLeftCorner<1,2>();
356 Jout.template bottomRightCorner<1,1>() -= Jtmp6.template bottomRightCorner<1,1>();
359 assert(
false &&
"Wrong Op requesed value");
364 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
365 static void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
366 const Eigen::MatrixBase<Tangent_t> & v,
367 const Eigen::MatrixBase<JacobianIn_t> & Jin,
368 const Eigen::MatrixBase<JacobianOut_t> & J_out)
370 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J_out);
371 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
372 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
376 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
378 Vector2 tinv = (R.transpose() * t).reverse();
379 tinv[0] *= Scalar(-1.);
381 Jout.template topRows<2>().noalias() = R.transpose() * Jin.template topRows<2>();
382 Jout.template topRows<2>().noalias() += tinv * Jin.template bottomRows<1>();
383 Jout.template bottomRows<1>() = Jin.template bottomRows<1>();
386 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
387 static void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
388 const Eigen::MatrixBase<Tangent_t> & v,
389 const Eigen::MatrixBase<JacobianIn_t> & Jin,
390 const Eigen::MatrixBase<JacobianOut_t> & J_out)
392 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J_out);
393 MotionTpl<Scalar,0> nu; nu.toVector() << v.template head<2>(), 0, 0, 0, v[2];
395 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
396 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
397 Eigen::Matrix<Scalar,6,6> Jtmp6;
399 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
401 Jout.template topRows<2>().noalias()
402 = Jtmp6.template topLeftCorner<2,2>() * Jin.template topRows<2>();
403 Jout.template topRows<2>().noalias()
404 += Jtmp6.template topRightCorner<2,1>() * Jin.template bottomRows<1>();
405 Jout.template bottomRows<1>().noalias()
406 = Jtmp6.template bottomLeftCorner<1,2>()* Jin.template topRows<2>();
407 Jout.template bottomRows<1>().noalias()
408 += Jtmp6.template bottomRightCorner<1,1>() * Jin.template bottomRows<1>();
412 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
413 static void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
414 const Eigen::MatrixBase<Tangent_t> & v,
415 const Eigen::MatrixBase<Jacobian_t> & J)
417 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J);
418 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
419 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
423 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
425 Vector2 tinv = (R.transpose() * t).reverse();
426 tinv[0] *= Scalar(-1);
428 Jout.template topRows<2>() = R.transpose() * Jout.template topRows<2>();
430 Jout.template topRows<2>().noalias() += tinv * Jout.template bottomRows<1>();
433 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
434 static void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
435 const Eigen::MatrixBase<Tangent_t> & v,
436 const Eigen::MatrixBase<Jacobian_t> & J)
438 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J);
439 MotionTpl<Scalar,0> nu; nu.toVector() << v.template head<2>(), 0, 0, 0, v[2];
441 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
442 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
443 Eigen::Matrix<Scalar,6,6> Jtmp6;
445 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
447 Jout.template topRows<2>()
448 = Jtmp6.template topLeftCorner<2,2>() * Jout.template topRows<2>();
449 Jout.template topRows<2>().noalias()
450 += Jtmp6.template topRightCorner<2,1>() * Jout.template bottomRows<1>();
451 Jout.template bottomRows<1>()
452 = Jtmp6.template bottomRightCorner<1,1>() * Jout.template bottomRows<1>();
453 Jout.template bottomRows<1>().noalias()
454 += Jtmp6.template bottomLeftCorner<1,2>() * Jout.template topRows<2>();
457 template <
class Config_t>
458 static void normalize_impl(
const Eigen::MatrixBase<Config_t> & qout)
460 PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout).template tail<2>().normalize();
463 template <
class Config_t>
464 static bool isNormalized_impl(
const Eigen::MatrixBase<Config_t> & qin,
467 const Scalar norm = Scalar(qin.template tail<2>().norm());
469 return abs(norm - Scalar(1.0)) < prec;
472 template <
class Config_t>
473 static void random_impl(
const Eigen::MatrixBase<Config_t> & qout)
475 R2crossSO2_t().random(qout);
478 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
479 static void randomConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> & lower,
480 const Eigen::MatrixBase<ConfigR_t> & upper,
481 const Eigen::MatrixBase<ConfigOut_t> & qout)
483 R2crossSO2_t ().randomConfiguration(lower, upper, qout);
486 template <
class ConfigL_t,
class ConfigR_t>
487 static bool isSameConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
488 const Eigen::MatrixBase<ConfigR_t> & q1,
491 return R2crossSO2_t().isSameConfiguration(q0, q1, prec);
496 template<
typename Matrix2Like,
typename Vector2Like,
typename Vector4Like>
498 const Eigen::MatrixBase<Vector2Like> & t,
499 const Eigen::MatrixBase<Vector4Like> & q)
501 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Matrix2Like, Matrix2);
502 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Vector2Like, Vector2);
503 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ConfigVector_t,Vector4Like);
505 PINOCCHIO_EIGEN_CONST_CAST(Vector2Like,t) = q.template head<2>();
506 const typename Vector4Like::Scalar & c_theta = q(2),
508 PINOCCHIO_EIGEN_CONST_CAST(Matrix2Like,R) << c_theta, -s_theta, s_theta, c_theta;
513 template<
typename _Scalar,
int _Options>
516 typedef _Scalar Scalar;
526 template<
typename _Scalar,
int _Options>
528 :
public LieGroupBase <SpecialEuclideanOperationTpl<3,_Scalar,_Options> >
534 typedef Eigen::Quaternion<Scalar,Options> Quaternion_t;
535 typedef Eigen::Map< Quaternion_t> QuaternionMap_t;
536 typedef Eigen::Map<const Quaternion_t> ConstQuaternionMap_t;
539 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
555 static ConfigVector_t
neutral()
557 ConfigVector_t n; n.template head<6>().setZero(); n[6] = 1;
561 static std::string
name()
563 return std::string(
"SE(3)");
566 template <
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
567 static void difference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
568 const Eigen::MatrixBase<ConfigR_t> & q1,
569 const Eigen::MatrixBase<Tangent_t> & d)
571 ConstQuaternionMap_t quat0 (q0.derived().template tail<4>().data());
573 ConstQuaternionMap_t quat1 (q1.derived().template tail<4>().data());
576 PINOCCHIO_EIGEN_CONST_CAST(Tangent_t,d)
577 =
log6( SE3(quat0.matrix(), q0.derived().template head<3>()).
inverse()
578 * SE3(quat1.matrix(), q1.derived().template head<3>())).toVector();
582 template <ArgumentPosition arg,
class ConfigL_t,
class ConfigR_t,
class JacobianOut_t>
584 const Eigen::MatrixBase<ConfigR_t> & q1,
585 const Eigen::MatrixBase<JacobianOut_t> & J)
587 typedef typename SE3::Vector3 Vector3;
588 typedef typename SE3::Matrix3 Matrix3;
590 ConstQuaternionMap_t quat0 (q0.derived().template tail<4>().data());
592 ConstQuaternionMap_t quat1 (q1.derived().template tail<4>().data());
595 Matrix3 R0(quat0.matrix()), R1 (quat1.matrix());
599 *
SE3(R1, q1.template head<3>()));
602 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
603 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
606 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
608 const Vector3 p1_p0 = R1.transpose()*(q1.template head<3>() - q0.template head<3>());
610 JacobianOut_t & J0 = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
611 J0.template bottomRightCorner<3,3> ().noalias() = J0.template topLeftCorner <3,3> ().noalias() = - M.rotation().transpose();
612 J0.template topRightCorner<3,3> ().noalias() =
skew(p1_p0) * M.rotation().transpose();
613 J0.template bottomLeftCorner<3,3> ().setZero();
614 J0.applyOnTheLeft(J1);
616 else if (arg == ARG1) {
621 template <
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
622 static void integrate_impl(
const Eigen::MatrixBase<ConfigIn_t> & q,
623 const Eigen::MatrixBase<Velocity_t> & v,
624 const Eigen::MatrixBase<ConfigOut_t> & qout)
626 ConfigOut_t & out = PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t,qout);
627 Quaternion_t
const quat(q.derived().template tail<4>());
629 QuaternionMap_t res_quat (out.template tail<4>().data());
631 using internal::if_then_else;
633 SE3 M0 (quat.matrix(), q.derived().template head<3>());
637 out.template head<3>() = M1.translation();
638 quaternion::assignQuaternion(res_quat,M1.rotation());
639 const Scalar dot_product = res_quat.dot(quat);
640 for(Eigen::DenseIndex k = 0; k < 4; ++k)
642 res_quat.coeffs().coeffRef(k) = if_then_else(internal::LT, dot_product, Scalar(0),
643 -res_quat.coeffs().coeff(k),
644 res_quat.coeffs().coeff(k));
653 template <
class Config_t,
class Jacobian_t>
654 static void integrateCoeffWiseJacobian_impl(
const Eigen::MatrixBase<Config_t> & q,
655 const Eigen::MatrixBase<Jacobian_t> & J)
657 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
659 typedef typename PINOCCHIO_EIGEN_PLAIN_TYPE(Config_t) ConfigPlainType;
660 typedef typename PINOCCHIO_EIGEN_PLAIN_TYPE(Jacobian_t) JacobianPlainType;
661 typedef typename ConfigPlainType::Scalar Scalar;
663 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J);
666 ConstQuaternionMap_t quat_map(q.derived().template tail<4>().data());
668 Jout.template topLeftCorner<3,3>() = quat_map.toRotationMatrix();
671 typedef Eigen::Matrix<Scalar,4,3,JacobianPlainType::Options|Eigen::RowMajor> Jacobian43;
672 typedef SE3Tpl<Scalar,ConfigPlainType::Options> SE3;
673 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
674 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
675 Jacobian43 Jexp3QuatCoeffWise;
680 typename SE3::Matrix3 Jlog;
682 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
688 if(quat_map.coeffs()[3] >= Scalar(0))
689 PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J).template bottomRightCorner<4,3>().noalias() = Jexp3QuatCoeffWise * Jlog;
691 PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J).template bottomRightCorner<4,3>().noalias() = -Jexp3QuatCoeffWise * Jlog;
694 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
695 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
696 const Eigen::MatrixBase<Tangent_t> & v,
697 const Eigen::MatrixBase<JacobianOut_t>& J,
698 const AssignmentOperatorType op=SETTO)
700 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J);
705 Jout =
exp6(MotionRef<const Tangent_t>(v.derived())).toDualActionMatrix().transpose();
708 Jout +=
exp6(MotionRef<const Tangent_t>(v.derived())).toDualActionMatrix().transpose();
711 Jout -=
exp6(MotionRef<const Tangent_t>(v.derived())).toDualActionMatrix().transpose();
714 assert(
false &&
"Wrong Op requesed value");
719 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
720 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
721 const Eigen::MatrixBase<Tangent_t> & v,
722 const Eigen::MatrixBase<JacobianOut_t>& J,
723 const AssignmentOperatorType op=SETTO)
728 Jexp6<SETTO>(MotionRef<const Tangent_t>(v.derived()), J.derived());
731 Jexp6<ADDTO>(MotionRef<const Tangent_t>(v.derived()), J.derived());
734 Jexp6<RMTO>(MotionRef<const Tangent_t>(v.derived()), J.derived());
737 assert(
false &&
"Wrong Op requesed value");
742 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
743 static void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
744 const Eigen::MatrixBase<Tangent_t> & v,
745 const Eigen::MatrixBase<JacobianIn_t> & Jin,
746 const Eigen::MatrixBase<JacobianOut_t> & J_out)
748 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J_out);
749 Eigen::Matrix<Scalar,6,6> Jtmp6;
750 Jtmp6 =
exp6(MotionRef<const Tangent_t>(v.derived())).toDualActionMatrix().transpose();
752 Jout.template topRows<3>().noalias()
753 = Jtmp6.template topLeftCorner<3,3>() * Jin.template topRows<3>();
754 Jout.template topRows<3>().noalias()
755 += Jtmp6.template topRightCorner<3,3>() * Jin.template bottomRows<3>();
756 Jout.template bottomRows<3>().noalias()
757 = Jtmp6.template bottomRightCorner<3,3>() * Jin.template bottomRows<3>();
760 template <
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
761 static void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
762 const Eigen::MatrixBase<Tangent_t> & v,
763 const Eigen::MatrixBase<JacobianIn_t> & Jin,
764 const Eigen::MatrixBase<JacobianOut_t> & J_out)
766 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t,J_out);
767 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
768 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
769 Eigen::Matrix<Scalar,6,6> Jtmp6;
770 Jexp6<SETTO>(MotionRef<const Tangent_t>(v.derived()), Jtmp6);
771 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
773 Jout.template topRows<3>().noalias()
774 = Jtmp6.template topLeftCorner<3,3>() * Jin.template topRows<3>();
775 Jout.template topRows<3>().noalias()
776 += Jtmp6.template topRightCorner<3,3>() * Jin.template bottomRows<3>();
777 Jout.template bottomRows<3>().noalias()
778 = Jtmp6.template bottomRightCorner<3,3>() * Jin.template bottomRows<3>();
782 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
783 static void dIntegrateTransport_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
784 const Eigen::MatrixBase<Tangent_t> & v,
785 const Eigen::MatrixBase<Jacobian_t> & J_out)
787 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J_out);
788 Eigen::Matrix<Scalar,6,6> Jtmp6;
789 Jtmp6 =
exp6(MotionRef<const Tangent_t>(v.derived())).toDualActionMatrix().transpose();
792 Jout.template topRows<3>()
793 = Jtmp6.template topLeftCorner<3,3>() * Jout.template topRows<3>();
794 Jout.template topRows<3>().noalias()
795 += Jtmp6.template topRightCorner<3,3>() * Jout.template bottomRows<3>();
796 Jout.template bottomRows<3>()
797 = Jtmp6.template bottomRightCorner<3,3>() * Jout.template bottomRows<3>();
800 template <
class Config_t,
class Tangent_t,
class Jacobian_t>
801 static void dIntegrateTransport_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
802 const Eigen::MatrixBase<Tangent_t> & v,
803 const Eigen::MatrixBase<Jacobian_t> & J_out)
805 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t,J_out);
806 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
807 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
808 Eigen::Matrix<Scalar,6,6> Jtmp6;
809 Jexp6<SETTO>(MotionRef<const Tangent_t>(v.derived()), Jtmp6);
810 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
812 Jout.template topRows<3>()
813 = Jtmp6.template topLeftCorner<3,3>() * Jout.template topRows<3>();
814 Jout.template topRows<3>().noalias()
815 += Jtmp6.template topRightCorner<3,3>() * Jout.template bottomRows<3>();
816 Jout.template bottomRows<3>()
817 = Jtmp6.template bottomRightCorner<3,3>() * Jout.template bottomRows<3>();
820 template <
class ConfigL_t,
class ConfigR_t>
821 static Scalar squaredDistance_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
822 const Eigen::MatrixBase<ConfigR_t> & q1)
824 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
825 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
827 difference_impl(q0, q1, t);
828 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
829 return t.squaredNorm();
832 template <
class Config_t>
833 static void normalize_impl (
const Eigen::MatrixBase<Config_t>& qout)
835 Config_t & qout_ = PINOCCHIO_EIGEN_CONST_CAST(Config_t,qout);
836 qout_.template tail<4>().normalize();
839 template <
class Config_t>
840 static bool isNormalized_impl(
const Eigen::MatrixBase<Config_t>& qin,
843 Scalar norm = Scalar(qin.template tail<4>().norm());
845 return abs(norm - Scalar(1.0)) < prec;
848 template <
class Config_t>
849 static void random_impl (
const Eigen::MatrixBase<Config_t>& qout)
851 R3crossSO3_t().random(qout);
854 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
855 static void randomConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> & lower,
856 const Eigen::MatrixBase<ConfigR_t> & upper,
857 const Eigen::MatrixBase<ConfigOut_t> & qout)
859 R3crossSO3_t ().randomConfiguration(lower, upper, qout);
862 template <
class ConfigL_t,
class ConfigR_t>
863 static bool isSameConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
864 const Eigen::MatrixBase<ConfigR_t> & q1,
867 return R3crossSO3_t().isSameConfiguration(q0, q1, prec);
873 #endif // ifndef __pinocchio_multibody_liegroup_special_euclidean_operation_hpp__