53 :
public LieGroupBase<SpecialOrthogonalOperationTpl<2, _Scalar, _Options>>
56 typedef Eigen::Matrix<Scalar, 2, 2> Matrix2;
57 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
59 template<
typename Matrix2Like>
60 static typename Matrix2Like::Scalar log(
const Eigen::MatrixBase<Matrix2Like> & R)
62 typedef typename Matrix2Like::Scalar Scalar;
65 const Scalar
tr = R.trace();
69 using internal::if_then_else;
70 Scalar
theta = if_then_else(
71 internal::GT,
tr, Scalar(2),
74 internal::LT,
tr, Scalar(-2),
76 internal::GE, R(1, 0), Scalar(0),
PI_value,
80 static_cast<Scalar
>(Scalar(2) - Scalar(1
e-2)),
81 static_cast<Scalar
>(
asin((R(1, 0) - R(0, 1)) / Scalar(2))),
83 internal::GE, R(1, 0), Scalar(0),
84 static_cast<Scalar
>(
acos(
tr / Scalar(2))),
85 static_cast<Scalar
>(-
acos(
tr / Scalar(2)))))));
100 template<
typename Matrix2Like>
101 static typename Matrix2Like::Scalar Jlog(
const Eigen::MatrixBase<Matrix2Like> &)
103 typedef typename Matrix2Like::Scalar Scalar;
123 static ConfigVector_t
neutral()
126 n << Scalar(1), Scalar(0);
130 static std::string
name()
132 return std::string(
"SO(2)");
135 template<
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
136 static void difference_impl(
137 const Eigen::MatrixBase<ConfigL_t> & q0,
138 const Eigen::MatrixBase<ConfigR_t> & q1,
139 const Eigen::MatrixBase<Tangent_t> & d)
142 R(0, 0) = R(1, 1) = q0.dot(q1);
143 R(1, 0) = q0(0) * q1(1) - q0(1) * q1(0);
145 PINOCCHIO_EIGEN_CONST_CAST(Tangent_t, d)[0] = log(R);
148 template<ArgumentPosition arg,
class ConfigL_t,
class ConfigR_t,
class JacobianOut_t>
149 static void dDifference_impl(
150 const Eigen::MatrixBase<ConfigL_t> & q0,
151 const Eigen::MatrixBase<ConfigR_t> & q1,
152 const Eigen::MatrixBase<JacobianOut_t> & J)
155 R(0, 0) = R(1, 1) = q0.dot(q1);
156 R(1, 0) = q0(0) * q1(1) - q0(1) * q1(0);
160 PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t, J).coeffRef(0, 0) = ((arg == ARG0) ? -w : w);
163 template<
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
164 static void integrate_impl(
165 const Eigen::MatrixBase<ConfigIn_t> & q,
166 const Eigen::MatrixBase<Velocity_t> & v,
167 const Eigen::MatrixBase<ConfigOut_t> & qout)
169 ConfigOut_t & out = PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t, qout);
171 const Scalar ca = q(0);
172 const Scalar sa = q(1);
173 const Scalar & omega = v(0);
175 Scalar cosOmega, sinOmega;
176 SINCOS(omega, &sinOmega, &cosOmega);
179 out << cosOmega * ca - sinOmega * sa, sinOmega * ca + cosOmega * sa;
182 const Scalar norm2 = out.squaredNorm();
183 out *= (3 - norm2) / 2;
187 template<
class Config_t,
class Jacobian_t>
188 static void integrateCoeffWiseJacobian_impl(
189 const Eigen::MatrixBase<Config_t> & q,
const Eigen::MatrixBase<Jacobian_t> & J)
191 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
192 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t, J);
196 template<
class Config_t,
class Tangent_t,
class JacobianOut_t>
197 static void dIntegrate_dq_impl(
198 const Eigen::MatrixBase<Config_t> & ,
199 const Eigen::MatrixBase<Tangent_t> & ,
200 const Eigen::MatrixBase<JacobianOut_t> & J,
201 const AssignmentOperatorType op = SETTO)
203 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t, J);
207 Jout(0, 0) = Scalar(1);
210 Jout(0, 0) += Scalar(1);
213 Jout(0, 0) -= Scalar(1);
216 assert(
false &&
"Wrong Op requesed value");
221 template<
class Config_t,
class Tangent_t,
class JacobianOut_t>
222 static void dIntegrate_dv_impl(
223 const Eigen::MatrixBase<Config_t> & ,
224 const Eigen::MatrixBase<Tangent_t> & ,
225 const Eigen::MatrixBase<JacobianOut_t> & J,
226 const AssignmentOperatorType op = SETTO)
228 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t, J);
232 Jout(0, 0) = Scalar(1);
235 Jout(0, 0) += Scalar(1);
238 Jout(0, 0) -= Scalar(1);
241 assert(
false &&
"Wrong Op requesed value");
246 template<
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
247 static void dIntegrateTransport_dq_impl(
248 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)
253 PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t, Jout) = Jin;
256 template<
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
257 static void dIntegrateTransport_dv_impl(
258 const Eigen::MatrixBase<Config_t> & ,
259 const Eigen::MatrixBase<Tangent_t> & ,
260 const Eigen::MatrixBase<JacobianIn_t> & Jin,
261 const Eigen::MatrixBase<JacobianOut_t> & Jout)
263 PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t, Jout) = Jin;
266 template<
class Config_t,
class Tangent_t,
class Jacobian_t>
267 static void dIntegrateTransport_dq_impl(
268 const Eigen::MatrixBase<Config_t> & ,
269 const Eigen::MatrixBase<Tangent_t> & ,
270 const Eigen::MatrixBase<Jacobian_t> & )
274 template<
class Config_t,
class Tangent_t,
class Jacobian_t>
275 static void dIntegrateTransport_dv_impl(
276 const Eigen::MatrixBase<Config_t> & ,
277 const Eigen::MatrixBase<Tangent_t> & ,
278 const Eigen::MatrixBase<Jacobian_t> & )
282 template<
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
283 static void interpolate_impl(
284 const Eigen::MatrixBase<ConfigL_t> & q0,
285 const Eigen::MatrixBase<ConfigR_t> & q1,
287 const Eigen::MatrixBase<ConfigOut_t> & qout)
289 ConfigOut_t & out = PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t, qout);
292 check_expression_if_real<Scalar>(abs(q0.norm() - 1) < 1e-8)
293 &&
"initial configuration not normalized");
295 check_expression_if_real<Scalar>(abs(q1.norm() - 1) < 1e-8)
296 &&
"final configuration not normalized");
297 const Scalar cosTheta = q0.dot(q1);
298 const Scalar sinTheta = q0(0) * q1(1) - q0(1) * q1(0);
299 const Scalar theta = atan2(sinTheta, cosTheta);
300 assert(check_expression_if_real<Scalar>(fabs(sin(theta) - sinTheta) < 1e-8));
302 static const Scalar PI_value = PI<Scalar>();
303 static const Scalar PI_value_lower = PI_value -
static_cast<Scalar
>(1e-6);
304 using namespace internal;
307 const Scalar abs_theta = fabs(theta);
308 out[0] = if_then_else(
309 LT, abs_theta,
static_cast<Scalar
>(1e-6),
310 static_cast<Scalar
>((Scalar(1) - u) * q0[0] + u * q1[0]),
312 LT, abs_theta, PI_value_lower,
314 (sin((Scalar(1) - u) * theta) / sinTheta) * q0[0]
315 + (sin(u * theta) / sinTheta) * q1[0]),
319 out[1] = if_then_else(
320 LT, abs_theta,
static_cast<Scalar
>(1e-6),
321 static_cast<Scalar
>((Scalar(1) - u) * q0[1] + u * q1[1]),
323 LT, abs_theta, PI_value_lower,
325 (sin((Scalar(1) - u) * theta) / sinTheta) * q0[1]
326 + (sin(u * theta) / sinTheta) * q1[1]),
331 template<
class Config_t>
332 static void normalize_impl(
const Eigen::MatrixBase<Config_t> & qout)
337 template<
class Config_t>
338 static bool isNormalized_impl(
const Eigen::MatrixBase<Config_t> & qin,
const Scalar & prec)
340 const Scalar norm = qin.norm();
342 return abs(norm - Scalar(1.0)) < prec;
345 template<
class Config_t>
346 static void random_impl(
const Eigen::MatrixBase<Config_t> & qout)
348 Config_t & out = PINOCCHIO_EIGEN_CONST_CAST(Config_t, qout);
350 static const Scalar PI_value = PI<Scalar>();
351 const Scalar angle = -PI_value + Scalar(2) * PI_value * ((Scalar)rand()) / RAND_MAX;
352 SINCOS(angle, &out(1), &out(0));
355 template<
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
356 static void randomConfiguration_impl(
357 const Eigen::MatrixBase<ConfigL_t> &,
358 const Eigen::MatrixBase<ConfigR_t> &,
359 const Eigen::MatrixBase<ConfigOut_t> & qout)
367 :
public LieGroupBase<SpecialOrthogonalOperationTpl<3, _Scalar, _Options>>
371 typedef Eigen::Quaternion<Scalar> Quaternion_t;
372 typedef Eigen::Map<Quaternion_t> QuaternionMap_t;
373 typedef Eigen::Map<const Quaternion_t> ConstQuaternionMap_t;
375 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
392 static ConfigVector_t
neutral()
400 static std::string
name()
402 return std::string(
"SO(3)");
405 template<
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
406 static void difference_impl(
407 const Eigen::MatrixBase<ConfigL_t> & q0,
408 const Eigen::MatrixBase<ConfigR_t> & q1,
409 const Eigen::MatrixBase<Tangent_t> & d)
411 ConstQuaternionMap_t quat0(q0.derived().data());
413 ConstQuaternionMap_t quat1(q1.derived().data());
416 PINOCCHIO_EIGEN_CONST_CAST(Tangent_t, d) =
420 template<ArgumentPosition arg,
class ConfigL_t,
class ConfigR_t,
class JacobianOut_t>
421 static void dDifference_impl(
422 const Eigen::MatrixBase<ConfigL_t> & q0,
423 const Eigen::MatrixBase<ConfigR_t> & q1,
424 const Eigen::MatrixBase<JacobianOut_t> & J)
426 typedef typename SE3::Matrix3 Matrix3;
428 ConstQuaternionMap_t quat0(q0.derived().data());
430 ConstQuaternionMap_t quat1(q1.derived().data());
434 const Quaternion_t q = quat0.conjugate() * quat1;
435 const Matrix3 R = q.matrix();
442 PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t, J).noalias() = -J1 * R.transpose();
444 else if (arg == ARG1)
466 template<
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
467 static void integrate_impl(
468 const Eigen::MatrixBase<ConfigIn_t> & q,
469 const Eigen::MatrixBase<Velocity_t> & v,
470 const Eigen::MatrixBase<ConfigOut_t> & qout)
472 ConstQuaternionMap_t quat(q.derived().data());
474 QuaternionMap_t quat_map(PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t, qout).data());
478 quat_map = quat * pOmega;
483 template<
class Config_t,
class Jacobian_t>
484 static void integrateCoeffWiseJacobian_impl(
485 const Eigen::MatrixBase<Config_t> & q,
const Eigen::MatrixBase<Jacobian_t> & J)
487 assert(J.rows() ==
nq() && J.cols() ==
nv() &&
"J is not of the right dimension");
489 typedef typename PINOCCHIO_EIGEN_PLAIN_TYPE(Jacobian_t) JacobianPlainType;
490 typedef typename SE3::Vector3 Vector3;
491 typedef typename SE3::Matrix3 Matrix3;
493 ConstQuaternionMap_t quat_map(q.derived().data());
496 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
497 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
498 Eigen::Matrix<Scalar, NQ, NV, JacobianPlainType::Options | Eigen::RowMajor>
505 Jlog3(theta, v, Jlog);
506 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
510 if (quat_map.coeffs()[3] >= 0.)
512 PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t, J).noalias() = Jexp3QuatCoeffWise * Jlog;
514 PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t, J).noalias() = -Jexp3QuatCoeffWise * Jlog;
520 template<
class Config_t,
class Tangent_t,
class JacobianOut_t>
521 static void dIntegrate_dq_impl(
522 const Eigen::MatrixBase<Config_t> & ,
523 const Eigen::MatrixBase<Tangent_t> & v,
524 const Eigen::MatrixBase<JacobianOut_t> & J,
525 const AssignmentOperatorType op = SETTO)
527 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t, J);
540 assert(
false &&
"Wrong Op requesed value");
545 template<
class Config_t,
class Tangent_t,
class JacobianOut_t>
546 static void dIntegrate_dv_impl(
547 const Eigen::MatrixBase<Config_t> & ,
548 const Eigen::MatrixBase<Tangent_t> & v,
549 const Eigen::MatrixBase<JacobianOut_t> & J,
550 const AssignmentOperatorType op = SETTO)
555 Jexp3<SETTO>(v, J.derived());
558 Jexp3<ADDTO>(v, J.derived());
561 Jexp3<RMTO>(v, J.derived());
564 assert(
false &&
"Wrong Op requesed value");
569 template<
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
570 static void dIntegrateTransport_dq_impl(
571 const Eigen::MatrixBase<Config_t> & ,
572 const Eigen::MatrixBase<Tangent_t> & v,
573 const Eigen::MatrixBase<JacobianIn_t> & Jin,
574 const Eigen::MatrixBase<JacobianOut_t> & J_out)
576 typedef typename SE3::Matrix3 Matrix3;
577 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t, J_out);
578 const Matrix3 Jtmp3 =
exp3(-v);
579 Jout.noalias() = Jtmp3 * Jin;
582 template<
class Config_t,
class Tangent_t,
class JacobianIn_t,
class JacobianOut_t>
583 static void dIntegrateTransport_dv_impl(
584 const Eigen::MatrixBase<Config_t> & ,
585 const Eigen::MatrixBase<Tangent_t> & v,
586 const Eigen::MatrixBase<JacobianIn_t> & Jin,
587 const Eigen::MatrixBase<JacobianOut_t> & J_out)
589 typedef typename SE3::Matrix3 Matrix3;
590 JacobianOut_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(JacobianOut_t, J_out);
591 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
592 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
594 Jexp3<SETTO>(v, Jtmp3);
595 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
596 Jout.noalias() = Jtmp3 * Jin;
599 template<
class Config_t,
class Tangent_t,
class Jacobian_t>
600 static void dIntegrateTransport_dq_impl(
601 const Eigen::MatrixBase<Config_t> & ,
602 const Eigen::MatrixBase<Tangent_t> & v,
603 const Eigen::MatrixBase<Jacobian_t> & J_out)
605 typedef typename SE3::Matrix3 Matrix3;
606 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t, J_out);
607 const Matrix3 Jtmp3 =
exp3(-v);
611 template<
class Config_t,
class Tangent_t,
class Jacobian_t>
612 static void dIntegrateTransport_dv_impl(
613 const Eigen::MatrixBase<Config_t> & ,
614 const Eigen::MatrixBase<Tangent_t> & v,
615 const Eigen::MatrixBase<Jacobian_t> & J_out)
617 typedef typename SE3::Matrix3 Matrix3;
618 Jacobian_t & Jout = PINOCCHIO_EIGEN_CONST_CAST(Jacobian_t, J_out);
619 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
620 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
622 Jexp3<SETTO>(v, Jtmp3);
623 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
627 template<
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
628 static void interpolate_impl(
629 const Eigen::MatrixBase<ConfigL_t> & q0,
630 const Eigen::MatrixBase<ConfigR_t> & q1,
632 const Eigen::MatrixBase<ConfigOut_t> & qout)
634 ConstQuaternionMap_t quat0(q0.derived().data());
636 ConstQuaternionMap_t quat1(q1.derived().data());
639 QuaternionMap_t quat_res(PINOCCHIO_EIGEN_CONST_CAST(ConfigOut_t, qout).data());
642 difference_impl(q0, q1, w);
643 integrate_impl(q0, u * w, qout);
647 template<
class ConfigL_t,
class ConfigR_t>
648 static Scalar squaredDistance_impl(
649 const Eigen::MatrixBase<ConfigL_t> & q0,
const Eigen::MatrixBase<ConfigR_t> & q1)
651 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
652 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_MAYBE_UNINITIALIZED
654 difference_impl(q0, q1, t);
655 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
656 return t.squaredNorm();
659 template<
class Config_t>
660 static void normalize_impl(
const Eigen::MatrixBase<Config_t> & qout)
665 template<
class Config_t>
666 static bool isNormalized_impl(
const Eigen::MatrixBase<Config_t> & qin,
const Scalar & prec)
668 const Scalar norm = qin.norm();
670 return abs(norm - Scalar(1.0)) < prec;
673 template<
class Config_t>
674 static void random_impl(
const Eigen::MatrixBase<Config_t> & qout)
676 QuaternionMap_t quat_map(PINOCCHIO_EIGEN_CONST_CAST(Config_t, qout).data());
682 template<
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
683 static void randomConfiguration_impl(
684 const Eigen::MatrixBase<ConfigL_t> &,
685 const Eigen::MatrixBase<ConfigR_t> &,
686 const Eigen::MatrixBase<ConfigOut_t> & qout)
691 template<
class ConfigL_t,
class ConfigR_t>
692 static bool isSameConfiguration_impl(
693 const Eigen::MatrixBase<ConfigL_t> & q0,
694 const Eigen::MatrixBase<ConfigR_t> & q1,
697 ConstQuaternionMap_t quat1(q0.derived().data());
699 ConstQuaternionMap_t quat2(q1.derived().data());