18 #ifndef __se3_special_euclidean_operation_hpp__ 19 #define __se3_special_euclidean_operation_hpp__ 23 #include <pinocchio/macros.hpp> 24 #include "pinocchio/spatial/fwd.hpp" 25 #include "pinocchio/spatial/se3.hpp" 26 #include "pinocchio/multibody/liegroup/operation-base.hpp" 28 #include "pinocchio/multibody/liegroup/vector-space.hpp" 29 #include "pinocchio/multibody/liegroup/cartesian-product.hpp" 30 #include "pinocchio/multibody/liegroup/special-orthogonal.hpp" 38 typedef double Scalar;
54 typedef Eigen::Matrix<Scalar,2,2> Matrix2;
55 typedef Eigen::Matrix<Scalar,2,1> Vector2;
57 template <
typename Tangent_t>
58 static void exp (
const Eigen::MatrixBase<Tangent_t>& v, Matrix2& R, Vector2& t)
60 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(TangentVector_t,Tangent_t);
62 const Scalar & omega = v(2);
63 Scalar cv,sv; SINCOS(omega, &sv, &cv);
66 if (std::fabs (omega) > 1e-14) {
67 Vector2 vcross (-v(1), v(0));
69 t = vcross - R * vcross;
71 t = v.template head<2>();
75 template <
typename Matrix_t>
76 static void toInverseActionMatrix (
const Matrix2& R,
const Vector2& t,
const Eigen::MatrixBase<Matrix_t>& M)
78 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix_t, 3, 3);
79 Matrix_t& Mout = const_cast <Matrix_t&> (M.derived());
80 Mout.template topLeftCorner<2,2>().noalias() = R.transpose();
81 Vector2 tinv (R.transpose() * t);
82 Mout.template topRightCorner<2,1>() << - tinv(1), tinv(0);
83 Mout.template bottomLeftCorner<1,2>().setZero();
87 template <
typename Tangent_t>
88 static void log (
const Matrix2& R,
const Vector2& p,
89 const Eigen::MatrixBase<Tangent_t>& v)
91 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(TangentVector_t,Tangent_t);
92 Tangent_t& vout =
const_cast< Tangent_t&
>(v.derived());
94 Scalar t = SO2_t::log(R);
95 const Scalar tabs = std::fabs(t);
96 const Scalar t2 = t*t;
99 alpha = 1 - t2/12 - t2*t2/720;
101 Scalar st,ct; SINCOS (tabs, &st, &ct);
102 alpha = tabs*st/(2*(1-ct));
105 Matrix2 sk; sk << 0, -t/2, t/2, 0;
106 vout.template head<2>().noalias() = alpha * p - sk * p;
110 template <
typename JacobianOut_t>
111 static void Jlog (
const Matrix2& R,
const Vector2& p,
112 const Eigen::MatrixBase<JacobianOut_t>& J)
114 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(JacobianOut_t, JacobianMatrix_t);
115 JacobianOut_t& Jout =
const_cast< JacobianOut_t&
>(J.derived());
117 Scalar t = SO2_t::log(R);
118 const Scalar tabs = std::fabs(t);
119 Scalar alpha, alpha_dot;
122 alpha_dot = - t / 6 - t*t*t / 180;
124 Scalar st,ct; SINCOS (t, &st, &ct);
125 Scalar inv_2_1_ct = 0.5 / (1-ct);
127 alpha = t*st*inv_2_1_ct;
129 alpha_dot = (st-t) * inv_2_1_ct;
133 V(0,0) = V(1,1) = alpha;
137 Jout.template topLeftCorner <2,2>() = V * R;
138 Jout.template topRightCorner<2,1>() << alpha_dot*p[0] + p[1]/2, -p(0)/2 + alpha_dot*p(1);
139 Jout.template bottomLeftCorner<1,2>().setZero();
157 ConfigVector_t
neutral ()
const 159 ConfigVector_t n; n.setZero (); n [2] = 1;
163 std::string
name ()
const 165 return std::string (
"SE(2)");
168 template <
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
169 static void difference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
170 const Eigen::MatrixBase<ConfigR_t> & q1,
171 const Eigen::MatrixBase<Tangent_t> & d)
174 (const_cast <Eigen::MatrixBase<Tangent_t> &> (d)).setZero ();
177 Matrix2 R0, R1; Vector2 t0, t1;
180 Matrix2 R (R0.transpose() * R1);
181 Vector2 t (R0.transpose() * (t1 - t0));
186 template <
class ConfigL_t,
class ConfigR_t,
class JacobianLOut_t,
class JacobianROut_t>
187 static void Jdifference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
188 const Eigen::MatrixBase<ConfigR_t> & q1,
189 const Eigen::MatrixBase<JacobianLOut_t>& J0,
190 const Eigen::MatrixBase<JacobianROut_t>& J1)
192 Matrix2 R0, R1; Vector2 t0, t1;
195 Matrix2 R (R0.transpose() * R1);
196 Vector2 t (R0.transpose() * (t1 - t0));
201 Vector2 pcross (q1(1) - q0(1), q0(0) - q1(0));
203 JacobianLOut_t& J0v =
const_cast< JacobianLOut_t&
> (J0.derived());
204 J0v.template topLeftCorner <2,2> ().noalias() = - R.transpose();
205 J0v.template topRightCorner<2,1> ().noalias() = R1.transpose() * pcross;
206 J0v.template bottomLeftCorner <1,2> ().setZero();
208 J0v.applyOnTheLeft(J1);
211 template <
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
212 static void integrate_impl(
const Eigen::MatrixBase<ConfigIn_t> & q,
213 const Eigen::MatrixBase<Velocity_t> & v,
214 const Eigen::MatrixBase<ConfigOut_t> & qout)
216 ConfigOut_t& out =
const_cast< ConfigOut_t&
>(qout.derived());
223 out.template head<2>().noalias() = R0 * t + t0;
224 out.template tail<2>().noalias() = R0 * R.col(0);
227 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
228 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
229 const Eigen::MatrixBase<Tangent_t> & v,
230 const Eigen::MatrixBase<JacobianOut_t>& J)
232 JacobianOut_t& Jout =
const_cast< JacobianOut_t&
>(J.derived());
238 toInverseActionMatrix (R, t, Jout);
241 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
242 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
243 const Eigen::MatrixBase<Tangent_t> & v,
244 const Eigen::MatrixBase<JacobianOut_t>& J)
246 JacobianOut_t& Jout =
const_cast< JacobianOut_t&
>(J.derived());
249 Eigen::Matrix<Scalar,6,6> Jtmp6;
251 Jout << Jtmp6. topLeftCorner<2,2>(), Jtmp6. topRightCorner<2,1>(),
252 Jtmp6.bottomLeftCorner<1,2>(), Jtmp6.bottomRightCorner<1,1>();
265 template <
class Config_t>
266 static void normalize_impl (
const Eigen::MatrixBase<Config_t>& qout)
268 Config_t& qout_ = (
const_cast< Eigen::MatrixBase<Config_t>&
>(qout)).derived();
272 template <
class Config_t>
273 void random_impl (
const Eigen::MatrixBase<Config_t>& qout)
const 275 R2crossSO2_t().random(qout);
278 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
279 void randomConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> & lower,
280 const Eigen::MatrixBase<ConfigR_t> & upper,
281 const Eigen::MatrixBase<ConfigOut_t> & qout)
284 R2crossSO2_t ().randomConfiguration(lower, upper, qout);
287 template <
class ConfigL_t,
class ConfigR_t>
288 static bool isSameConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
289 const Eigen::MatrixBase<ConfigR_t> & q1,
292 return R2crossSO2_t().isSameConfiguration(q0, q1, prec);
297 static void forwardKinematics(Matrix2 & R, Vector2 & t,
const Eigen::MatrixBase<V>& q)
299 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ConfigVector_t,V);
301 const double& c_theta = q(2),
304 R << c_theta, -s_theta, s_theta, c_theta;
305 t = q.template head<2>();
310 typedef double Scalar;
325 typedef Eigen::Quaternion<Scalar> Quaternion_t;
326 typedef Eigen::Map< Quaternion_t> QuaternionMap_t;
327 typedef Eigen::Map<const Quaternion_t> ConstQuaternionMap_t;
344 ConfigVector_t
neutral ()
const 346 ConfigVector_t n; n.setZero (); n [6] = 1;
350 std::string
name ()
const 352 return std::string (
"SE(3)");
355 template <
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
356 static void difference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
357 const Eigen::MatrixBase<ConfigR_t> & q1,
358 const Eigen::MatrixBase<Tangent_t> & d)
361 (const_cast < Eigen::MatrixBase<Tangent_t>& > (d)).setZero ();
364 ConstQuaternionMap_t p0 (q0.derived().template tail<4>().data());
365 ConstQuaternionMap_t p1 (q1.derived().template tail<4>().data());
366 const_cast < Eigen::MatrixBase<Tangent_t>& > (d)
367 =
log6(
SE3(p0.matrix(), q0.derived().template head<3>()).
inverse()
368 *
SE3(p1.matrix(), q1.derived().template head<3>())).toVector();
371 template <
class ConfigL_t,
class ConfigR_t,
class JacobianLOut_t,
class JacobianROut_t>
372 static void Jdifference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
373 const Eigen::MatrixBase<ConfigR_t> & q1,
374 const Eigen::MatrixBase<JacobianLOut_t>& J0,
375 const Eigen::MatrixBase<JacobianROut_t>& J1)
377 ConstQuaternionMap_t p0 (q0.derived().template tail<4>().data());
378 ConstQuaternionMap_t p1 (q1.derived().template tail<4>().data());
379 SE3::Matrix3 R0 (p0.matrix()),
382 *
SE3(R1, q1.derived().template head<3>()));
386 SE3::Vector3 p1_p0 (q1.derived().template head<3>()
387 - q0.derived().template head<3>());
389 JacobianLOut_t& J0v =
const_cast< JacobianLOut_t&
> (J0.derived());
390 J0v.template topLeftCorner <3,3> ().noalias() = - M.rotation().transpose();
391 J0v.template topRightCorner<3,3> ().noalias() = R1.transpose() *
skew (p1_p0) * R0;
392 J0v.template bottomLeftCorner <3,3> ().setZero();
393 J0v.template bottomRightCorner<3,3> ().noalias() = - M.rotation().transpose();
394 J0v.applyOnTheLeft(J1);
397 template <
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
398 static void integrate_impl(
const Eigen::MatrixBase<ConfigIn_t> & q,
399 const Eigen::MatrixBase<Velocity_t> & v,
400 const Eigen::MatrixBase<ConfigOut_t> & qout)
402 ConfigOut_t& out = (
const_cast< Eigen::MatrixBase<ConfigOut_t>&
>(qout)).derived();
403 ConstQuaternionMap_t quat(q.derived().template tail<4>().data());
404 QuaternionMap_t res_quat (out.template tail<4>().data());
406 SE3 M0 (quat.matrix(), q.derived().template head<3>());
409 out.template head<3>() = M1.translation();
410 res_quat = M1.rotation();
416 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
417 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
418 const Eigen::MatrixBase<Tangent_t> & v,
419 const Eigen::MatrixBase<JacobianOut_t>& J)
421 JacobianOut_t& Jout =
const_cast< JacobianOut_t&
>(J.derived());
422 Jout =
exp6(v).inverse().toActionMatrix();
425 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
426 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
427 const Eigen::MatrixBase<Tangent_t> & v,
428 const Eigen::MatrixBase<JacobianOut_t>& J)
442 template <
class ConfigL_t,
class ConfigR_t>
443 static double squaredDistance_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
444 const Eigen::MatrixBase<ConfigR_t> & q1)
447 difference_impl(q0, q1, t);
448 return t.squaredNorm();
451 template <
class Config_t>
452 static void normalize_impl (
const Eigen::MatrixBase<Config_t>& qout)
454 Config_t& qout_ = (
const_cast< Eigen::MatrixBase<Config_t>&
>(qout)).derived();
458 template <
class Config_t>
459 void random_impl (
const Eigen::MatrixBase<Config_t>& qout)
const 461 R3crossSO3_t().random(qout);
464 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
465 void randomConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> & lower,
466 const Eigen::MatrixBase<ConfigR_t> & upper,
467 const Eigen::MatrixBase<ConfigOut_t> & qout)
470 R3crossSO3_t ().randomConfiguration(lower, upper, qout);
473 template <
class ConfigL_t,
class ConfigR_t>
474 static bool isSameConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
475 const Eigen::MatrixBase<ConfigR_t> & q1,
478 return R3crossSO3_t().isSameConfiguration(q0, q1, prec);
484 #endif // ifndef __se3_special_euclidean_operation_hpp__
Index nv() const
Get dimension of Lie Group tangent space.
void Jexp6(const MotionDense< MotionDerived > &nu, const Eigen::MatrixBase< Matrix6Like > &Jexp)
Derivative of exp6 Computed as the inverse of Jlog6.
MotionTpl< Scalar, Options > log6(const SE3Tpl< Scalar, Options > &M)
Log: SE3 -> se3.
SE3Tpl inverse() const
aXb = bXa.inverse()
std::string name(const LieGroupVariant &lg)
Visit a LieGroupVariant to get the name of it.
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...
Eigen::VectorXd neutral(const Model &model)
Return the neutral configuration element related to the model configuration space.
SE3Tpl< typename MotionDerived::Scalar, Eigen::internal::traits< typename MotionDerived::Vector3 >::Options > exp6(const MotionDense< MotionDerived > &nu)
Exp: se3 -> SE3.
void Jlog6(const SE3Tpl< Scalar, Options > &M, const Eigen::MatrixBase< Matrix6Like > &Jlog)
Derivative of log6 and .
Index nv() const
Get dimension of Lie Group tangent space.
void normalize(const Model &model, Eigen::VectorXd &q)
Normalize a configuration.
void forwardKinematics(const Model &model, Data &data, const Eigen::VectorXd &q)
Update the joint placements according to the current joint configuration.
void firstOrderNormalize(const Eigen::QuaternionBase< D > &q)