19 #ifndef __spatial_explog_hpp__ 20 #define __spatial_explog_hpp__ 22 #include <Eigen/Geometry> 24 #include "pinocchio/macros.hpp" 25 #include "pinocchio/math/fwd.hpp" 26 #include "pinocchio/math/sincos.hpp" 27 #include "pinocchio/spatial/motion.hpp" 28 #include "pinocchio/spatial/skew.hpp" 29 #include "pinocchio/spatial/se3.hpp" 41 template<
typename Vector3Like>
42 typename Eigen::Matrix<typename Vector3Like::Scalar,3,3,EIGEN_PLAIN_TYPE(Vector3Like)::Options>
43 exp3(
const Eigen::MatrixBase<Vector3Like> & v)
45 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Vector3Like);
46 assert(v.size() == 3);
48 typedef typename Vector3Like::Scalar Scalar;
50 typedef Eigen::Matrix<Scalar,3,3,Vector3LikePlain::Options> Matrix3;
52 const Scalar t2 = v.squaredNorm();
54 const Scalar t = std::sqrt(t2);
55 if(t > Eigen::NumTraits<Scalar>::dummy_precision())
57 Scalar ct,st; SINCOS(t,&st,&ct);
58 const Scalar alpha_vxvx = (1 - ct)/t2;
59 const Scalar alpha_vx = (st)/t;
60 Matrix3 res(alpha_vxvx * v * v.transpose());
61 res.coeffRef(0,1) -= alpha_vx * v[2]; res.coeffRef(1,0) += alpha_vx * v[2];
62 res.coeffRef(0,2) += alpha_vx * v[1]; res.coeffRef(2,0) -= alpha_vx * v[1];
63 res.coeffRef(1,2) -= alpha_vx * v[0]; res.coeffRef(2,1) += alpha_vx * v[0];
64 res.diagonal().array() += ct;
70 const Scalar alpha_vxvx = Scalar(1)/Scalar(2) - t2/24;
71 const Scalar alpha_vx = Scalar(1) - t2/6;
72 Matrix3 res(alpha_vxvx * v * v.transpose());
73 res.coeffRef(0,1) -= alpha_vx * v[2]; res.coeffRef(1,0) += alpha_vx * v[2];
74 res.coeffRef(0,2) += alpha_vx * v[1]; res.coeffRef(2,0) -= alpha_vx * v[1];
75 res.coeffRef(1,2) -= alpha_vx * v[0]; res.coeffRef(2,1) += alpha_vx * v[0];
76 res.diagonal().array() += Scalar(1) - t2/2;
89 template<
typename Matrix3Like,
typename S2>
90 Eigen::Matrix<typename Matrix3Like::Scalar,3,1,Eigen::internal::traits<Matrix3Like>::Options>
91 log3(
const Eigen::MatrixBase<Matrix3Like> & R, S2 & theta)
93 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix3Like,3,3);
94 typedef typename Matrix3Like::Scalar Scalar;
95 typedef Eigen::Matrix<Scalar,3,1,Eigen::internal::traits<Matrix3Like>::Options> Vector3;
97 const Scalar PI_value = PI<Scalar>();
100 const Scalar tr = R.trace();
101 if (tr > Scalar(3)) theta = 0;
102 else if (tr < Scalar(-1)) theta = PI_value;
103 else theta = acos((tr - Scalar(1))/Scalar(2));
104 assert(theta == theta &&
"theta contains some NaN");
107 if (theta < PI_value - 1e-2)
109 const Scalar t = ((theta > 1e-6)? theta / sin(theta) : Scalar(1)) / Scalar(2);
110 res(0) = t * (R (2, 1) - R (1, 2));
111 res(1) = t * (R (0, 2) - R (2, 0));
112 res(2) = t * (R (1, 0) - R (0, 1));
120 const Scalar cphi = cos(theta - PI_value);
121 const Scalar beta = theta*theta / ( Scalar(1) + cphi );
122 Vector3 tmp((R.diagonal().array() + cphi) * beta);
123 res(0) = (R (2, 1) > R (1, 2) ? Scalar(1) : Scalar(-1)) * (tmp[0] > Scalar(0) ? sqrt(tmp[0]) : Scalar(0));
124 res(1) = (R (0, 2) > R (2, 0) ? Scalar(1) : Scalar(-1)) * (tmp[1] > Scalar(0) ? sqrt(tmp[1]) : Scalar(0));
125 res(2) = (R (1, 0) > R (0, 1) ? Scalar(1) : Scalar(-1)) * (tmp[2] > Scalar(0) ? sqrt(tmp[2]) : Scalar(0));
139 template<
typename Matrix3Like>
140 Eigen::Matrix<typename Matrix3Like::Scalar,3,1,Eigen::internal::traits<Matrix3Like>::Options>
141 log3(
const Eigen::MatrixBase<Matrix3Like> & R)
143 typename Matrix3Like::Scalar theta;
144 return log3(R.derived(), theta);
153 template<
typename Vector3Like,
typename Matrix3Like>
154 void Jexp3(
const Eigen::MatrixBase<Vector3Like> & r,
155 const Eigen::MatrixBase<Matrix3Like> & Jexp)
157 Matrix3Like & Jout =
const_cast<Matrix3Like &
>(Jexp.derived());
158 typedef typename Matrix3Like::Scalar Scalar;
160 Scalar n = r.norm(),a,b,c;
165 a = Scalar(1) - n/Scalar(6) + n2/Scalar(120);
166 b = - Scalar(1)/Scalar(2) + n/Scalar(24) - n2/Scalar(720);
167 c = Scalar(1)/Scalar(6) - n/Scalar(120) + n2/Scalar(5040);
170 Scalar n_inv = Scalar(1.)/n;
171 Scalar n2_inv = n_inv * n_inv;
172 Scalar cn,sn; SINCOS(n,&sn,&cn);
176 c = n2_inv * (1 - a);
180 Jout.diagonal().setConstant(a);
182 Jout(0,1) = -b*r[2]; Jout(1,0) = -Jout(0,1);
183 Jout(0,2) = b*r[1]; Jout(2,0) = -Jout(0,2);
184 Jout(1,2) = -b*r[0]; Jout(2,1) = -Jout(1,2);
186 Jout.noalias() += c * r * r.transpose();
189 template<
typename Scalar,
typename Vector3Like,
typename Matrix3Like>
190 void Jlog3(
const Scalar & theta,
191 const Eigen::MatrixBase<Vector3Like> & log,
192 const Eigen::MatrixBase<Matrix3Like> & Jlog)
194 Matrix3Like & Jout =
const_cast<Matrix3Like &
>(Jlog.derived());
195 typedef typename Matrix3Like::Scalar Scalar3;
202 Scalar ct,st; SINCOS(theta,&st,&ct);
203 const Scalar st_1mct = st/(Scalar(1)-ct);
206 Jout.diagonal().setConstant (theta*st_1mct);
209 Jout(0,1) = -log(2); Jout(1,0) = log(2);
210 Jout(0,2) = log(1); Jout(2,0) = -log(1);
211 Jout(1,2) = -log(0); Jout(2,1) = log(0);
214 const Scalar alpha = Scalar(1)/(theta*theta) - st_1mct/(Scalar(2)*theta);
215 Jout += alpha * log * log.transpose();
219 template<
typename Matrix3Like1,
typename Matrix3Like2>
220 void Jlog3(
const Eigen::MatrixBase<Matrix3Like1> & R,
221 const Eigen::MatrixBase<Matrix3Like2> & Jlog)
223 typedef typename Matrix3Like1::Scalar Scalar;
224 typedef Eigen::Matrix<Scalar,3,1,Eigen::internal::traits<Matrix3Like1>::Options> Vector3;
227 Vector3 w(
log3(R,t));
239 template<
typename MotionDerived>
243 typedef typename MotionDerived::Scalar Scalar;
244 enum { Options = Eigen::internal::traits<typename MotionDerived::Vector3>::Options };
248 const typename MotionDerived::ConstAngularType & w = nu.angular();
249 const typename MotionDerived::ConstLinearType & v = nu.linear();
251 const Scalar t2 = w.squaredNorm();
254 typename SE3::Linear_t & trans = res.translation();
255 typename SE3::Angular_t & rot = res.rotation();
257 const Scalar t = std::sqrt(t2);
260 Scalar ct,st; SINCOS(t,&st,&ct);
262 const Scalar inv_t2 = Scalar(1)/t2;
263 const Scalar alpha_wxv = (Scalar(1) - ct)*inv_t2;
264 const Scalar alpha_v = (st)/t;
265 const Scalar alpha_w = (Scalar(1) - alpha_v)*inv_t2 * w.dot(v);
268 trans.noalias() = (alpha_v*v + alpha_w*w + alpha_wxv*w.cross(v));
271 rot.noalias() = alpha_wxv * w * w.transpose();
272 rot.coeffRef(0,1) -= alpha_v * w[2]; rot.coeffRef(1,0) += alpha_v * w[2];
273 rot.coeffRef(0,2) += alpha_v * w[1]; rot.coeffRef(2,0) -= alpha_v * w[1];
274 rot.coeffRef(1,2) -= alpha_v * w[0]; rot.coeffRef(2,1) += alpha_v * w[0];
275 rot.diagonal().array() += ct;
279 const Scalar alpha_wxv = Scalar(1)/Scalar(2) - t2/24;
280 const Scalar alpha_v = Scalar(1) - t2/6;
281 const Scalar alpha_w = (Scalar(1)/Scalar(6) - t2/120) * w.dot(v);
284 trans.noalias() = (alpha_v*v + alpha_w*w + alpha_wxv*w.cross(v));
287 rot.noalias() = alpha_wxv * w * w.transpose();
288 rot.coeffRef(0,1) -= alpha_v * w[2]; rot.coeffRef(1,0) += alpha_v * w[2];
289 rot.coeffRef(0,2) += alpha_v * w[1]; rot.coeffRef(2,0) -= alpha_v * w[1];
290 rot.coeffRef(1,2) -= alpha_v * w[0]; rot.coeffRef(2,1) += alpha_v * w[0];
291 rot.diagonal().array() += Scalar(1) - t2/2;
305 template<
typename Vector6Like>
307 exp6(
const Eigen::MatrixBase<Vector6Like> & v)
309 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector6Like,6);
322 template <
typename Scalar,
int Options>
328 typedef typename SE3::Vector3 Vector3;
330 const typename SE3::ConstAngular_t & R = M.rotation();
331 const typename SE3::ConstLinear_t & p = M.translation();
334 Vector3 w(
log3(R,t));
335 const Scalar t2 = t*t;
337 if (std::fabs(t) < 1e-4)
339 alpha = Scalar(1) - t2/Scalar(12) - t2*t2/Scalar(720);
340 beta = Scalar(1)/Scalar(12) + t2/Scalar(720);
343 Scalar st,ct; SINCOS(t,&st,&ct);
344 alpha = t*st/(Scalar(2)*(Scalar(1)-ct));
345 beta = Scalar(1)/t2 - st/(Scalar(2)*t*(Scalar(1)-ct));
348 return Motion(alpha * p -
alphaSkew(0.5, w) * p + beta * w.dot(p) * w,
362 log6(
const Eigen::MatrixBase<D> & M)
364 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(D, 4, 4);
368 Matrix3 rot(M.template block<3,3>(0,0));
369 Vector3 trans(M.template block<3,1>(0,3));
376 template<
typename MotionDerived,
typename Matrix6Like>
378 const Eigen::MatrixBase<Matrix6Like> & Jexp)
380 typedef typename MotionDerived::Scalar Scalar;
381 typedef typename MotionDerived::Vector3 Vector3;
382 typedef Eigen::Matrix<Scalar, 3, 3, Vector3::Options> Matrix3;
383 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix6Like,6,6);
384 Matrix6Like & Jout =
const_cast<Matrix6Like &
> (Jexp.derived());
386 const typename MotionDerived::ConstLinearType & v = nu.linear();
387 const typename MotionDerived::ConstAngularType & w = nu.angular();
388 const Scalar t = w.norm();
392 Jexp3(w, Jout.template bottomRightCorner<3,3>());
393 Jout.template topLeftCorner<3,3>() = Jout.template bottomRightCorner<3,3>();
395 const Scalar t2 = t*t;
396 Scalar beta, beta_dot_over_theta;
398 beta = Scalar(1)/Scalar(12) + t2/Scalar(720);
399 beta_dot_over_theta = Scalar(1)/Scalar(360);
401 const Scalar tinv = Scalar(1)/t,
403 Scalar st,ct; SINCOS (t, &st, &ct);
404 const Scalar inv_2_2ct = Scalar(1)/(Scalar(2)*(Scalar(1)-ct));
406 beta = t2inv - st*tinv*inv_2_2ct;
407 beta_dot_over_theta = -Scalar(2)*t2inv*t2inv +
408 (Scalar(1) + st*tinv) * t2inv * inv_2_2ct;
411 Vector3 p (Jout.template topLeftCorner<3,3>().transpose() * v);
412 Scalar wTp (w.dot (p));
414 (beta_dot_over_theta*wTp) *w*w.transpose()
415 - (t2*beta_dot_over_theta+Scalar(2)*beta)*p*w.transpose()
416 + wTp * beta * Matrix3::Identity()
417 + beta *w*p.transpose());
419 Jout.template topRightCorner<3,3>().noalias() =
420 - Jout.template topLeftCorner<3,3>() * J;
421 Jout.template bottomLeftCorner<3,3>().setZero();
442 template<
typename Scalar,
int Options,
typename Matrix6Like>
444 const Eigen::MatrixBase<Matrix6Like> & Jlog)
447 typedef typename SE3::Vector3 Vector3;
448 typedef typename SE3::Matrix3 Matrix3;
449 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix6Like,6,6);
450 Matrix6Like & value =
const_cast<Matrix6Like &
> (Jlog.derived());
452 const typename SE3::ConstAngular_t & R = M.rotation();
453 const typename SE3::ConstLinear_t & p = M.translation();
456 Vector3 w(
log3(R,t));
461 const Scalar t2 = t*t;
462 Scalar beta, beta_dot_over_theta;
465 beta = Scalar(1)/Scalar(12) + t2/Scalar(720);
466 beta_dot_over_theta = Scalar(1)/Scalar(360);
470 const Scalar tinv = Scalar(1)/t,
472 Scalar st,ct; SINCOS (t, &st, &ct);
473 const Scalar inv_2_2ct = Scalar(1)/(Scalar(2)*(Scalar(1)-ct));
475 beta = t2inv - st*tinv*inv_2_2ct;
476 beta_dot_over_theta = -Scalar(2)*t2inv*t2inv +
477 (Scalar(1) + st*tinv) * t2inv * inv_2_2ct;
480 Scalar wTp (w.dot (p));
483 (beta_dot_over_theta*wTp)*w*w.transpose()
484 - (t2*beta_dot_over_theta+Scalar(2)*beta)*p*w.transpose()
485 + wTp * beta * Matrix3::Identity()
486 + beta * w*p.transpose()
494 #endif //#ifndef __spatial_explog_hpp__ EIGEN_PLAIN_TYPE(Matrix3x) cross(const Eigen
Applies the cross product onto the columns of M.
void Jexp3(const Eigen::MatrixBase< Vector3Like > &r, const Eigen::MatrixBase< Matrix3Like > &Jexp)
Derivative of .
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.
void alphaSkew(const Scalar alpha, const Eigen::MatrixBase< Vector3 > &v, const Eigen::MatrixBase< Matrix3 > &M)
Computes the skew representation of a given 3d vector multiplied by a given scalar. i.e. the antisymmetric matrix representation of the cross product operator ( )
Eigen::Matrix< typename Matrix3Like::Scalar, 3, 1, Eigen::internal::traits< Matrix3Like >::Options > log3(const Eigen::MatrixBase< Matrix3Like > &R, S2 &theta)
Same as log3.
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 .
Eigen::Matrix< typename Vector3Like::Scalar, 3, 3, EIGEN_PLAIN_TYPE(Vector3Like)::Options > exp3(const Eigen::MatrixBase< Vector3Like > &v)
Exp: so3 -> SO3.