6 #ifndef __spatial_explog_hpp__ 7 #define __spatial_explog_hpp__ 9 #include <Eigen/Geometry> 11 #include "pinocchio/fwd.hpp" 12 #include "pinocchio/math/fwd.hpp" 13 #include "pinocchio/math/sincos.hpp" 14 #include "pinocchio/math/taylor-expansion.hpp" 15 #include "pinocchio/spatial/motion.hpp" 16 #include "pinocchio/spatial/skew.hpp" 17 #include "pinocchio/spatial/se3.hpp" 29 template<
typename Vector3Like>
30 typename Eigen::Matrix<typename Vector3Like::Scalar,3,3,PINOCCHIO_EIGEN_PLAIN_TYPE(Vector3Like)::Options>
31 exp3(
const Eigen::MatrixBase<Vector3Like> & v)
33 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Vector3Like, v, 3, 1);
35 typedef typename Vector3Like::Scalar Scalar;
36 typedef typename PINOCCHIO_EIGEN_PLAIN_TYPE(Vector3Like) Vector3LikePlain;
37 typedef Eigen::Matrix<Scalar,3,3,Vector3LikePlain::Options> Matrix3;
39 const Scalar t2 = v.squaredNorm();
41 const Scalar t = math::sqrt(t2);
44 Scalar ct,st;
SINCOS(t,&st,&ct);
45 const Scalar alpha_vxvx = (1 - ct)/t2;
46 const Scalar alpha_vx = (st)/t;
47 Matrix3 res(alpha_vxvx * v * v.transpose());
48 res.coeffRef(0,1) -= alpha_vx * v[2]; res.coeffRef(1,0) += alpha_vx * v[2];
49 res.coeffRef(0,2) += alpha_vx * v[1]; res.coeffRef(2,0) -= alpha_vx * v[1];
50 res.coeffRef(1,2) -= alpha_vx * v[0]; res.coeffRef(2,1) += alpha_vx * v[0];
51 res.diagonal().array() += ct;
57 const Scalar alpha_vxvx = Scalar(1)/Scalar(2) - t2/24;
58 const Scalar alpha_vx = Scalar(1) - t2/6;
59 Matrix3 res(alpha_vxvx * v * v.transpose());
60 res.coeffRef(0,1) -= alpha_vx * v[2]; res.coeffRef(1,0) += alpha_vx * v[2];
61 res.coeffRef(0,2) += alpha_vx * v[1]; res.coeffRef(2,0) -= alpha_vx * v[1];
62 res.coeffRef(1,2) -= alpha_vx * v[0]; res.coeffRef(2,1) += alpha_vx * v[0];
63 res.diagonal().array() += Scalar(1) - t2/2;
76 template<
typename Matrix3Like>
77 Eigen::Matrix<typename Matrix3Like::Scalar,3,1,PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix3Like)::Options>
78 log3(
const Eigen::MatrixBase<Matrix3Like> & R,
79 typename Matrix3Like::Scalar & theta)
81 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Matrix3Like, R, 3, 3);
83 typedef typename Matrix3Like::Scalar Scalar;
84 typedef Eigen::Matrix<Scalar,3,1,PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix3Like)::Options> Vector3;
86 static const Scalar PI_value = PI<Scalar>();
89 const Scalar tr = R.trace();
90 if (tr > Scalar(3)) theta = 0;
91 else if (tr < Scalar(-1)) theta = PI_value;
92 else theta = acos((tr - Scalar(1))/Scalar(2));
93 assert(theta == theta &&
"theta contains some NaN");
96 if (theta < PI_value - 1e-2)
100 : Scalar(1)) / Scalar(2);
101 res(0) = t * (R (2, 1) - R (1, 2));
102 res(1) = t * (R (0, 2) - R (2, 0));
103 res(2) = t * (R (1, 0) - R (0, 1));
111 const Scalar cphi = cos(theta - PI_value);
112 const Scalar beta = theta*theta / ( Scalar(1) + cphi );
113 Vector3 tmp((R.diagonal().array() + cphi) * beta);
114 res(0) = (R (2, 1) > R (1, 2) ? Scalar(1) : Scalar(-1)) * (tmp[0] > Scalar(0) ? sqrt(tmp[0]) : Scalar(0));
115 res(1) = (R (0, 2) > R (2, 0) ? Scalar(1) : Scalar(-1)) * (tmp[1] > Scalar(0) ? sqrt(tmp[1]) : Scalar(0));
116 res(2) = (R (1, 0) > R (0, 1) ? Scalar(1) : Scalar(-1)) * (tmp[2] > Scalar(0) ? sqrt(tmp[2]) : Scalar(0));
130 template<
typename Matrix3Like>
131 Eigen::Matrix<typename Matrix3Like::Scalar,3,1,PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix3Like)::Options>
132 log3(
const Eigen::MatrixBase<Matrix3Like> & R)
134 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Matrix3Like, R, 3, 3);
136 typename Matrix3Like::Scalar theta;
137 return log3(R.derived(),theta);
148 template<
typename Vector3Like,
typename Matrix3Like>
149 void Jexp3(
const Eigen::MatrixBase<Vector3Like> & r,
150 const Eigen::MatrixBase<Matrix3Like> & Jexp)
152 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Vector3Like, r , 3, 1);
153 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Matrix3Like, Jexp, 3, 3);
155 Matrix3Like & Jout =
const_cast<Matrix3Like &
>(Jexp.derived());
156 typedef typename Matrix3Like::Scalar Scalar;
158 Scalar n2 = r.squaredNorm(),a,b,c;
159 Scalar n = math::sqrt(n2);
163 a = Scalar(1) - n2/Scalar(6);
164 b = - Scalar(1)/Scalar(2) - n2/Scalar(24);
165 c = Scalar(1)/Scalar(6) - n2/Scalar(120);
169 Scalar n_inv = Scalar(1)/n;
170 Scalar n2_inv = n_inv * n_inv;
171 Scalar cn,sn;
SINCOS(n,&sn,&cn);
175 c = n2_inv * (1 - a);
178 Jout.diagonal().setConstant(a);
180 Jout(0,1) = -b*r[2]; Jout(1,0) = -Jout(0,1);
181 Jout(0,2) = b*r[1]; Jout(2,0) = -Jout(0,2);
182 Jout(1,2) = -b*r[0]; Jout(2,1) = -Jout(1,2);
184 Jout.noalias() += c * r * r.transpose();
187 template<
typename Scalar,
typename Vector3Like,
typename Matrix3Like>
188 void Jlog3(
const Scalar & theta,
189 const Eigen::MatrixBase<Vector3Like> & log,
190 const Eigen::MatrixBase<Matrix3Like> & Jlog)
192 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Vector3Like, log, 3, 1);
193 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Matrix3Like, Jlog, 3, 3);
195 Matrix3Like & Jout =
const_cast<Matrix3Like &
>(Jlog.derived());
199 const Scalar alpha = Scalar(1)/Scalar(12) + theta*theta / Scalar(720);
200 Jout.noalias() = alpha * log * log.transpose();
202 Jout.diagonal().array() += Scalar(0.5) * (2 - theta*theta / Scalar(6));
210 Scalar ct,st;
SINCOS(theta,&st,&ct);
211 const Scalar st_1mct = st/(Scalar(1)-ct);
213 const Scalar alpha = Scalar(1)/(theta*theta) - st_1mct/(Scalar(2)*theta);
214 Jout.noalias() = alpha * log * log.transpose();
216 Jout.diagonal().array() += Scalar(0.5) * (theta*st_1mct);
223 template<
typename Matrix3Like1,
typename Matrix3Like2>
224 void Jlog3(
const Eigen::MatrixBase<Matrix3Like1> & R,
225 const Eigen::MatrixBase<Matrix3Like2> & Jlog)
227 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Matrix3Like1, R, 3, 3);
228 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Matrix3Like2, Jlog, 3, 3);
230 typedef typename Matrix3Like1::Scalar Scalar;
231 typedef Eigen::Matrix<Scalar,3,1,PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix3Like1)::Options> Vector3;
234 Vector3 w(
log3(R,t));
246 template<
typename MotionDerived>
250 typedef typename MotionDerived::Scalar Scalar;
251 enum { Options = PINOCCHIO_EIGEN_PLAIN_TYPE(
typename MotionDerived::Vector3)::Options };
255 const typename MotionDerived::ConstAngularType & w = nu.angular();
256 const typename MotionDerived::ConstLinearType & v = nu.linear();
258 const Scalar t2 = w.squaredNorm();
261 typename SE3::LinearType & trans = res.translation();
262 typename SE3::AngularType & rot = res.rotation();
264 const Scalar t = math::sqrt(t2);
268 const Scalar alpha_wxv = Scalar(1)/Scalar(2) - t2/24;
269 const Scalar alpha_v = Scalar(1) - t2/6;
270 const Scalar alpha_w = (Scalar(1)/Scalar(6) - t2/120)*w.dot(v);
273 trans.noalias() = (alpha_v*v + alpha_w*w + alpha_wxv*w.cross(v));
276 rot.noalias() = alpha_wxv * w * w.transpose();
277 rot.coeffRef(0,1) -= alpha_v * w[2]; rot.coeffRef(1,0) += alpha_v * w[2];
278 rot.coeffRef(0,2) += alpha_v * w[1]; rot.coeffRef(2,0) -= alpha_v * w[1];
279 rot.coeffRef(1,2) -= alpha_v * w[0]; rot.coeffRef(2,1) += alpha_v * w[0];
280 rot.diagonal().array() += Scalar(1) - t2/2;
284 Scalar ct,st;
SINCOS(t,&st,&ct);
286 const Scalar inv_t2 = Scalar(1)/t2;
287 const Scalar alpha_wxv = (Scalar(1) - ct)*inv_t2;
288 const Scalar alpha_v = (st)/t;
289 const Scalar alpha_w = (Scalar(1) - alpha_v)*inv_t2 * w.dot(v);
292 trans.noalias() = (alpha_v*v + alpha_w*w + alpha_wxv*w.cross(v));
295 rot.noalias() = alpha_wxv * w * w.transpose();
296 rot.coeffRef(0,1) -= alpha_v * w[2]; rot.coeffRef(1,0) += alpha_v * w[2];
297 rot.coeffRef(0,2) += alpha_v * w[1]; rot.coeffRef(2,0) -= alpha_v * w[1];
298 rot.coeffRef(1,2) -= alpha_v * w[0]; rot.coeffRef(2,1) += alpha_v * w[0];
299 rot.diagonal().array() += ct;
313 template<
typename Vector6Like>
315 exp6(
const Eigen::MatrixBase<Vector6Like> & v)
317 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Vector6Like, v, 6, 1);
331 template <
typename Scalar,
int Options>
337 typedef typename SE3::Vector3 Vector3;
339 typename SE3::ConstAngularRef R = M.rotation();
340 typename SE3::ConstLinearRef p = M.translation();
343 Vector3 w(
log3(R,t));
344 const Scalar t2 = t*t;
348 alpha = Scalar(1) - t2/Scalar(12) - t2*t2/Scalar(720);
349 beta = Scalar(1)/Scalar(12) + t2/Scalar(720);
353 Scalar st,ct;
SINCOS(t,&st,&ct);
354 alpha = t*st/(Scalar(2)*(Scalar(1)-ct));
355 beta = Scalar(1)/t2 - st/(Scalar(2)*t*(Scalar(1)-ct));
358 return Motion(alpha * p - 0.5 * w.cross(p) + beta * w.dot(p) * w,
370 template<
typename Matrix4Like>
372 log6(
const Eigen::MatrixBase<Matrix4Like> & M)
374 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Matrix4Like, M, 4, 4);
382 template<
typename MotionDerived,
typename Matrix6Like>
384 const Eigen::MatrixBase<Matrix6Like> & Jexp)
386 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Matrix6Like, Jexp, 6, 6);
388 typedef typename MotionDerived::Scalar Scalar;
389 typedef typename MotionDerived::Vector3 Vector3;
390 typedef Eigen::Matrix<Scalar, 3, 3, Vector3::Options> Matrix3;
391 Matrix6Like & Jout =
const_cast<Matrix6Like &
> (Jexp.derived());
393 const typename MotionDerived::ConstLinearType & v = nu.linear();
394 const typename MotionDerived::ConstAngularType & w = nu.angular();
395 const Scalar t2 = w.squaredNorm();
396 const Scalar t = math::sqrt(t2);
400 Jexp3(w, Jout.template bottomRightCorner<3,3>());
401 Jout.template topLeftCorner<3,3>() = Jout.template bottomRightCorner<3,3>();
403 Scalar beta, beta_dot_over_theta;
406 beta = Scalar(1)/Scalar(12) + t2/Scalar(720);
407 beta_dot_over_theta = Scalar(1)/Scalar(360);
411 const Scalar tinv = Scalar(1)/t,
413 Scalar st,ct;
SINCOS (t, &st, &ct);
414 const Scalar inv_2_2ct = Scalar(1)/(Scalar(2)*(Scalar(1)-ct));
416 beta = t2inv - st*tinv*inv_2_2ct;
417 beta_dot_over_theta = -Scalar(2)*t2inv*t2inv +
418 (Scalar(1) + st*tinv) * t2inv * inv_2_2ct;
421 Vector3 p (Jout.template topLeftCorner<3,3>().transpose() * v);
422 Scalar wTp (w.dot (p));
424 (beta_dot_over_theta*wTp) *w*w.transpose()
425 - (t2*beta_dot_over_theta+Scalar(2)*beta)*p*w.transpose()
426 + wTp * beta * Matrix3::Identity()
427 + beta *w*p.transpose());
429 Jout.template topRightCorner<3,3>().noalias() =
430 - Jout.template topLeftCorner<3,3>() * J;
431 Jout.template bottomLeftCorner<3,3>().setZero();
454 template<
typename Scalar,
int Options,
typename Matrix6Like>
456 const Eigen::MatrixBase<Matrix6Like> & Jlog)
458 PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE (Matrix6Like, Jlog, 6, 6);
461 typedef typename SE3::Vector3 Vector3;
462 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix6Like,6,6);
463 Matrix6Like & value =
const_cast<Matrix6Like &
> (Jlog.derived());
465 typename SE3::ConstAngularRef R = M.rotation();
466 typename SE3::ConstLinearRef p = M.translation();
469 Vector3 w(
log3(R,t));
474 typedef Eigen::Block<Matrix6Like,3,3,Matrix6Like::IsRowMajor> Block33;
475 Block33 A = value.template topLeftCorner<3,3>();
476 Block33 B = value.template topRightCorner<3,3>();
477 Block33 C = value.template bottomLeftCorner<3,3>();
478 Block33 D = value.template bottomRightCorner<3,3>();
483 const Scalar t2 = t*t;
484 Scalar beta, beta_dot_over_theta;
487 beta = Scalar(1)/Scalar(12) + t2/Scalar(720);
488 beta_dot_over_theta = Scalar(1)/Scalar(360);
492 const Scalar tinv = Scalar(1)/t,
494 Scalar st,ct;
SINCOS (t, &st, &ct);
495 const Scalar inv_2_2ct = Scalar(1)/(Scalar(2)*(Scalar(1)-ct));
497 beta = t2inv - st*tinv*inv_2_2ct;
498 beta_dot_over_theta = -Scalar(2)*t2inv*t2inv +
499 (Scalar(1) + st*tinv) * t2inv * inv_2_2ct;
502 Scalar wTp = w.dot(p);
504 Vector3 v3_tmp((beta_dot_over_theta*wTp)*w - (t2*beta_dot_over_theta+Scalar(2)*beta)*p);
506 C.noalias() = v3_tmp * w.transpose();
507 C.noalias() += beta * w * p.transpose();
508 C.diagonal().array() += wTp * beta;
516 #include "pinocchio/spatial/explog-quaternion.hpp" 518 #endif //#ifndef __spatial_explog_hpp__
Eigen::Matrix< typename Matrix3Like::Scalar, 3, 1, Matrix3Like::Options > log3(const Eigen::MatrixBase< Matrix3Like > &R, typename Matrix3Like::Scalar &theta)
Same as log3.
Eigen::Matrix< typename Vector3Like::Scalar, 3, 3, Vector3Like::Options > exp3(const Eigen::MatrixBase< Vector3Like > &v)
Exp: so3 -> SO3.
void Jlog6(const SE3Tpl< Scalar, Options > &M, const Eigen::MatrixBase< Matrix6Like > &Jlog)
Derivative of log6 where and .
Helper struct to retrieve some useful information for a Taylor series expansion according to the a gi...
MotionTpl< Scalar, Options > log6(const SE3Tpl< Scalar, Options > &M)
Log: SE3 -> se3.
void SINCOS(const Scalar &a, Scalar *sa, Scalar *ca)
Computes sin/cos values of a given input scalar.
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.
void addSkew(const Eigen::MatrixBase< Vector3Like > &v, const Eigen::MatrixBase< Matrix3Like > &M)
Add skew matrix represented by a 3d vector to a given matrix, i.e. add the antisymmetric matrix repre...
Main pinocchio namespace.
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 ( )
SE3Tpl< typename MotionDerived::Scalar, typename MotionDerived::Vector3::Options > exp6(const MotionDense< MotionDerived > &nu)
Exp: se3 -> SE3.