18 #ifndef __se3_special_orthogonal_operation_hpp__ 19 #define __se3_special_orthogonal_operation_hpp__ 23 #include <pinocchio/spatial/explog.hpp> 24 #include <pinocchio/math/quaternion.hpp> 25 #include <pinocchio/multibody/liegroup/operation-base.hpp> 33 typedef double Scalar;
41 typedef double Scalar;
52 typedef Eigen::Matrix<Scalar,2,2> Matrix2;
54 static Scalar log(
const Matrix2 & R)
57 const Scalar tr = R.trace();
58 const bool pos = (R (1, 0) > Scalar(0));
59 const Scalar PI_value = PI<Scalar>();
60 if (tr > Scalar(2)) theta = Scalar(0);
61 else if (tr < Scalar(-2)) theta = (pos ? PI_value : -PI_value);
64 else if (tr > Scalar(2) - 1e-2) theta = asin ((R(1,0) - R(0,1)) / Scalar(2));
65 else theta = (pos ? acos (tr/Scalar(2)) : -acos(tr/Scalar(2)));
66 assert (theta == theta);
67 assert (fabs(theta - atan2 (R(1,0), R(0,0))) < 1e-6);
71 static Scalar Jlog (
const Matrix2&)
92 ConfigVector_t n; n.setZero(); n[0] = Scalar(1);
96 std::string
name ()
const 98 return std::string (
"SO(2)");
101 template <
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
102 static void difference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
103 const Eigen::MatrixBase<ConfigR_t> & q1,
104 const Eigen::MatrixBase<Tangent_t> & d)
107 (const_cast < Tangent_t& > (d.derived())).setZero ();
111 R(0,0) = R(1,1) = q0.dot(q1);
112 R(1,0) = q0(0) * q1(1) - q0(1) * q1(0);
114 const_cast < Tangent_t& > (d.derived()) [0] = log (R);
117 template <
class ConfigL_t,
class ConfigR_t,
class JacobianLOut_t,
class JacobianROut_t>
118 static void Jdifference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
119 const Eigen::MatrixBase<ConfigR_t> & q1,
120 const Eigen::MatrixBase<JacobianLOut_t>& J0,
121 const Eigen::MatrixBase<JacobianROut_t>& J1)
124 R(0,0) = R(1,1) = q0.dot(q1);
125 R(1,0) = q0(0) * q1(1) - q0(1) * q1(0);
129 const_cast< JacobianLOut_t&
> (J0.derived()).coeffRef(0,0) = -w;
130 const_cast< JacobianROut_t&
> (J1.derived()).coeffRef(0,0) = w;
133 template <
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
134 static void integrate_impl(
const Eigen::MatrixBase<ConfigIn_t> & q,
135 const Eigen::MatrixBase<Velocity_t> & v,
136 const Eigen::MatrixBase<ConfigOut_t> & qout)
138 ConfigOut_t& out = (
const_cast< Eigen::MatrixBase<ConfigOut_t>&
>(qout)).derived();
140 const Scalar & ca = q(0);
141 const Scalar & sa = q(1);
142 const Scalar & omega = v(0);
144 Scalar cosOmega,sinOmega; SINCOS(omega, &sinOmega, &cosOmega);
147 out << cosOmega * ca - sinOmega * sa,
148 sinOmega * ca + cosOmega * sa;
149 const Scalar norm2 = q.squaredNorm();
150 out *= (3 - norm2) / 2;
153 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
154 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
155 const Eigen::MatrixBase<Tangent_t> & ,
156 const Eigen::MatrixBase<JacobianOut_t>& J)
158 JacobianOut_t& Jout =
const_cast< JacobianOut_t&
>(J.derived());
162 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
163 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
164 const Eigen::MatrixBase<Tangent_t> & ,
165 const Eigen::MatrixBase<JacobianOut_t>& J)
167 JacobianOut_t& Jout =
const_cast< JacobianOut_t&
>(J.derived());
171 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
172 static void interpolate_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
173 const Eigen::MatrixBase<ConfigR_t> & q1,
175 const Eigen::MatrixBase<ConfigOut_t>& qout)
177 ConfigOut_t& out = (
const_cast< Eigen::MatrixBase<ConfigOut_t>&
>(qout)).derived();
179 assert ( (q0.norm() - 1) < 1e-8 &&
"initial configuration not normalized");
180 assert ( (q1.norm() - 1) < 1e-8 &&
"final configuration not normalized");
181 Scalar cosTheta = q0.dot(q1);
182 Scalar sinTheta = q0(0)*q1(1) - q0(1)*q1(0);
183 Scalar theta = atan2(sinTheta, cosTheta);
184 assert (fabs (sin (theta) - sinTheta) < 1e-8);
186 const Scalar PI_value = PI<Scalar>();
188 if (fabs (theta) > 1e-6 && fabs (theta) < PI_value - 1e-6)
190 out = (sin ((1-u)*theta)/sinTheta) * q0
191 + (sin ( u *theta)/sinTheta) * q1;
193 else if (fabs (theta) < 1e-6)
195 out = (1-u) * q0 + u * q1;
199 Scalar theta0 = atan2 (q0(1), q0(0));
200 SINCOS(theta0,&out[1],&out[0]);
208 template <
class Config_t>
209 static void normalize_impl (
const Eigen::MatrixBase<Config_t>& qout)
211 Config_t& qout_ = (
const_cast< Eigen::MatrixBase<Config_t>&
>(qout)).derived();
215 template <
class Config_t>
216 void random_impl (
const Eigen::MatrixBase<Config_t>& qout)
const 218 Config_t& out = (
const_cast< Eigen::MatrixBase<Config_t>&
>(qout)).derived();
220 const Scalar PI_value = PI<Scalar>();
221 const Scalar angle = -PI_value + Scalar(2)* PI_value * ((Scalar)rand())/RAND_MAX;
222 SINCOS(angle, &out(1), &out(0));
225 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
226 void randomConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> &,
227 const Eigen::MatrixBase<ConfigR_t> &,
228 const Eigen::MatrixBase<ConfigOut_t> & qout)
240 typedef Eigen::Quaternion<Scalar> Quaternion_t;
241 typedef Eigen::Map< Quaternion_t> QuaternionMap_t;
242 typedef Eigen::Map<const Quaternion_t> ConstQuaternionMap_t;
258 ConfigVector_t
neutral ()
const 260 ConfigVector_t n; n.setZero (); n[3] = Scalar(1);
264 std::string
name ()
const 266 return std::string (
"SO(3)");
269 template <
class ConfigL_t,
class ConfigR_t,
class Tangent_t>
270 static void difference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
271 const Eigen::MatrixBase<ConfigR_t> & q1,
272 const Eigen::MatrixBase<Tangent_t> & d)
275 (const_cast < Eigen::MatrixBase<Tangent_t>& > (d)).setZero ();
278 ConstQuaternionMap_t p0 (q0.derived().data());
279 ConstQuaternionMap_t p1 (q1.derived().data());
280 const_cast < Eigen::MatrixBase<Tangent_t>& > (d)
281 =
log3((p0.matrix().transpose() * p1.matrix()).eval());
284 template <
class ConfigL_t,
class ConfigR_t,
class JacobianLOut_t,
class JacobianROut_t>
285 static void Jdifference_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
286 const Eigen::MatrixBase<ConfigR_t> & q1,
287 const Eigen::MatrixBase<JacobianLOut_t>& J0,
288 const Eigen::MatrixBase<JacobianROut_t>& J1)
290 ConstQuaternionMap_t p0 (q0.derived().data());
291 ConstQuaternionMap_t p1 (q1.derived().data());
292 Eigen::Matrix<Scalar, 3, 3> R = p0.matrix().transpose() * p1.matrix();
296 JacobianLOut_t& J0v =
const_cast< JacobianLOut_t&
> (J0.derived());
297 J0v.noalias() = - J1 * R.transpose();
300 template <
class ConfigIn_t,
class Velocity_t,
class ConfigOut_t>
301 static void integrate_impl(
const Eigen::MatrixBase<ConfigIn_t> & q,
302 const Eigen::MatrixBase<Velocity_t> & v,
303 const Eigen::MatrixBase<ConfigOut_t> & qout)
305 ConstQuaternionMap_t quat(q.derived().data());
306 QuaternionMap_t quaternion_result (
307 (
const_cast< Eigen::MatrixBase<ConfigOut_t>&
>(qout)).derived().data()
310 Quaternion_t pOmega(
exp3(v));
311 quaternion_result = quat * pOmega;
315 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
316 static void dIntegrate_dq_impl(
const Eigen::MatrixBase<Config_t > & ,
317 const Eigen::MatrixBase<Tangent_t> & v,
318 const Eigen::MatrixBase<JacobianOut_t>& J)
320 JacobianOut_t& Jout =
const_cast< JacobianOut_t&
>(J.derived());
321 Jout =
exp3(v).transpose();
324 template <
class Config_t,
class Tangent_t,
class JacobianOut_t>
325 static void dIntegrate_dv_impl(
const Eigen::MatrixBase<Config_t > & ,
326 const Eigen::MatrixBase<Tangent_t> & v,
327 const Eigen::MatrixBase<JacobianOut_t>& J)
329 Jexp3 (v, J.derived());
332 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
333 static void interpolate_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
334 const Eigen::MatrixBase<ConfigR_t> & q1,
336 const Eigen::MatrixBase<ConfigOut_t>& qout)
338 ConstQuaternionMap_t p0 (q0.derived().data());
339 ConstQuaternionMap_t p1 (q1.derived().data());
340 QuaternionMap_t quaternion_result (
341 (
const_cast< Eigen::MatrixBase<ConfigOut_t>&
>(qout)).derived().data()
344 quaternion_result = p0.slerp(u, p1);
347 template <
class ConfigL_t,
class ConfigR_t>
348 static double squaredDistance_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
349 const Eigen::MatrixBase<ConfigR_t> & q1)
352 difference_impl(q0, q1, t);
353 return t.squaredNorm();
356 template <
class Config_t>
357 static void normalize_impl (
const Eigen::MatrixBase<Config_t>& qout)
359 Config_t& qout_ = (
const_cast< Eigen::MatrixBase<Config_t>&
>(qout)).derived();
363 template <
class Config_t>
364 void random_impl (
const Eigen::MatrixBase<Config_t>& qout)
const 366 QuaternionMap_t out (
367 (
const_cast< Eigen::MatrixBase<Config_t>&
>(qout)).derived().data()
372 template <
class ConfigL_t,
class ConfigR_t,
class ConfigOut_t>
373 void randomConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> &,
374 const Eigen::MatrixBase<ConfigR_t> &,
375 const Eigen::MatrixBase<ConfigOut_t> & qout)
381 template <
class ConfigL_t,
class ConfigR_t>
382 static bool isSameConfiguration_impl(
const Eigen::MatrixBase<ConfigL_t> & q0,
383 const Eigen::MatrixBase<ConfigR_t> & q1,
386 ConstQuaternionMap_t quat1(q0.derived().data());
387 ConstQuaternionMap_t quat2(q1.derived().data());
394 #endif // ifndef __se3_special_orthogonal_operation_hpp__
void Jexp3(const Eigen::MatrixBase< Vector3Like > &r, const Eigen::MatrixBase< Matrix3Like > &Jexp)
Derivative of .
std::string name(const LieGroupVariant &lg)
Visit a LieGroupVariant to get the name of it.
Eigen::Matrix< typename Matrix3Like::Scalar, 3, 1, Eigen::internal::traits< Matrix3Like >::Options > log3(const Eigen::MatrixBase< Matrix3Like > &R, S2 &theta)
Same as log3.
Eigen::VectorXd neutral(const Model &model)
Return the neutral configuration element related to the model configuration space.
void uniformRandom(const Eigen::QuaternionBase< D > &q)
Uniformly random quaternion sphere.
Index nv() const
Get dimension of Lie Group tangent space.
Eigen::Matrix< typename Vector3Like::Scalar, 3, 3, EIGEN_PLAIN_TYPE(Vector3Like)::Options > exp3(const Eigen::MatrixBase< Vector3Like > &v)
Exp: so3 -> SO3.
void firstOrderNormalize(const Eigen::QuaternionBase< D > &q)
Index nv() const
Get dimension of Lie Group tangent space.
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.