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>
22 template<
int Dim,
typename Scalar,
int Options>
27 template<
typename _Scalar,
int _Options>
30 typedef _Scalar Scalar;
39 template<
typename _Scalar,
int _Options>
42 typedef _Scalar Scalar;
51 template<
typename _Scalar,
int _Options>
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;
63 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like, 2, 2);
65 const Scalar tr = R.trace();
67 static const Scalar PI_value = PI<Scalar>();
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,
77 static_cast<Scalar
>(-PI_value)),
80 static_cast<Scalar
>(Scalar(2) - Scalar(1e-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)))))));
94 assert(check_expression_if_real<Scalar>(theta == theta) &&
"theta is NaN");
100 template<
typename Matrix2Like>
101 static typename Matrix2Like::Scalar Jlog(
const Eigen::MatrixBase<Matrix2Like> &)
103 typedef typename Matrix2Like::Scalar Scalar;
104 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix2Like, 2, 2);
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)
365 template<
typename _Scalar,
int _Options>
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());
void exp3(const Eigen::MatrixBase< Vector3Like > &v, Eigen::QuaternionBase< QuaternionLike > &quat_out)
Exp: so3 -> SO3 (quaternion)
void firstOrderNormalize(const Eigen::QuaternionBase< D > &q)
bool isNormalized(const Eigen::QuaternionBase< Quaternion > &quat, const typename Quaternion::Coefficients::RealScalar &prec)
Check whether the input quaternion is Normalized within the given precision.
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.
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.
void Jexp3CoeffWise(const Eigen::MatrixBase< Vector3Like > &v, const Eigen::MatrixBase< Matrix43Like > &Jexp)
Derivative of where is a small perturbation of at identity.
void uniformRandom(Eigen::QuaternionBase< Derived > &q)
Uniformly random quaternion sphere.
Main pinocchio namespace.
Eigen::Matrix< typename Vector3Like::Scalar, 3, 3, Vector3Like ::Options > exp3(const Eigen::MatrixBase< Vector3Like > &v)
Exp: so3 -> SO3.
void Jlog3(const Scalar &theta, const Eigen::MatrixBase< Vector3Like > &log, const Eigen::MatrixBase< Matrix3Like > &Jlog)
Derivative of log3.
bool isNormalized(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ConfigVectorType > &q, const Scalar &prec=Eigen::NumTraits< Scalar >::dummy_precision())
Check whether a configuration vector is normalized within the given precision provided by prec.
int nv(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointNvVisitor to get the dimension of the joint tangent space.
int nq(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointNqVisitor to get the dimension of the joint configuration space.
std::string name(const LieGroupGenericTpl< LieGroupCollection > &lg)
Visit a LieGroupVariant to get the name of it.
void normalize(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ConfigVectorType > &qout)
Normalize a configuration vector.
void neutral(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ReturnType > &qout)
Return the neutral configuration element related to the model configuration space.
void SINCOS(const S1 &a, S2 *sa, S3 *ca)
Computes sin/cos values of a given input scalar.
static Index nv()
Get dimension of Lie Group tangent space.
static Index nv()
Get dimension of Lie Group tangent space.
Common traits structure to fully define base classes for CRTP.