5 #ifndef __pinocchio_spatial_explog_quaternion_hpp__
6 #define __pinocchio_spatial_explog_quaternion_hpp__
8 #include "pinocchio/math/quaternion.hpp"
9 #include "pinocchio/spatial/explog.hpp"
10 #include "pinocchio/utils/static-if.hpp"
25 template<
typename Vector3Like,
typename QuaternionLike>
27 exp3(
const Eigen::MatrixBase<Vector3Like> & v, Eigen::QuaternionBase<QuaternionLike> & quat_out)
29 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Vector3Like);
30 assert(v.size() == 3);
32 typedef typename Vector3Like::Scalar Scalar;
35 Options = PINOCCHIO_EIGEN_PLAIN_TYPE(
typename QuaternionLike::Coefficients)::Options
37 typedef Eigen::Quaternion<typename QuaternionLike::Scalar, Options> QuaternionPlain;
38 const Scalar eps = Eigen::NumTraits<Scalar>::epsilon();
40 const Scalar t2 = v.squaredNorm();
41 const Scalar t = math::sqrt(t2 + eps * eps);
43 static const Scalar ts_prec =
47 Eigen::AngleAxis<Scalar> aa(t, v / t);
48 QuaternionPlain quat_then(aa);
51 QuaternionPlain quat_else;
52 const Scalar t2_2 = t2 / 4;
54 Scalar(0.5) * (Scalar(1) - t2_2 / Scalar(6) + t2_2 * t2_2 / Scalar(120)) * v;
55 quat_else.w() = Scalar(1) - t2_2 / 2 + t2_2 * t2_2 / 24;
57 using ::pinocchio::internal::if_then_else;
58 for (Eigen::DenseIndex k = 0; k < 4; ++k)
60 quat_out.coeffs().coeffRef(k) = if_then_else(
61 ::pinocchio::internal::GT, t2, ts_prec, quat_then.coeffs().coeffRef(k),
62 quat_else.coeffs().coeffRef(k));
72 template<
typename Vector3Like>
74 Quaternion<
typename Vector3Like::Scalar, PINOCCHIO_EIGEN_PLAIN_TYPE(Vector3Like)::Options>
75 exp3(const Eigen::MatrixBase<Vector3Like> & v)
77 typedef Eigen::Quaternion<
78 typename Vector3Like::Scalar, PINOCCHIO_EIGEN_PLAIN_TYPE(Vector3Like)::Options>
91 template<
typename MotionDerived,
typename Config_t>
96 Options = PINOCCHIO_EIGEN_PLAIN_TYPE(Config_t)::Options
98 typedef typename Config_t::Scalar Scalar;
99 typedef typename MotionDerived::Vector3 Vector3;
100 typedef Eigen::Quaternion<Scalar, Options> Quaternion_t;
101 const Scalar eps = Eigen::NumTraits<Scalar>::epsilon();
103 const typename MotionDerived::ConstAngularType & w =
motion.angular();
104 const typename MotionDerived::ConstLinearType & v =
motion.linear();
106 const Scalar t2 = w.squaredNorm() + eps * eps;
107 const Scalar t = math::sqrt(t2);
112 const Scalar inv_t2 = Scalar(1) / t2;
113 const Scalar ts_prec =
116 using ::pinocchio::internal::if_then_else;
117 using ::pinocchio::internal::LT;
119 const Scalar alpha_wxv = if_then_else(
121 Scalar(0.5) - t2 / Scalar(24),
122 (Scalar(1) - ct) * inv_t2
125 const Scalar alpha_w2 = if_then_else(
126 LT, t, ts_prec, Scalar(1) / Scalar(6) - t2 / Scalar(120), (t - st) * inv_t2 / t);
129 Eigen::Map<Vector3> trans_(qout.derived().template head<3>().data());
130 trans_.noalias() = v + alpha_wxv * w.cross(v) + alpha_w2 * w.cross(w.cross(v));
133 typedef Eigen::Map<Quaternion_t> QuaternionMap_t;
134 QuaternionMap_t quat_(qout.derived().template tail<4>().data());
143 template<
typename MotionDerived>
145 typename MotionDerived::Scalar,
148 PINOCCHIO_EIGEN_PLAIN_TYPE(
typename MotionDerived::Vector3)::Options>
151 typedef typename MotionDerived::Scalar Scalar;
154 Options = PINOCCHIO_EIGEN_PLAIN_TYPE(
typename MotionDerived::Vector3)::Options
156 typedef Eigen::Matrix<Scalar, 7, 1, Options> ReturnType;
169 template<
typename Vector6Like,
typename Config_t>
170 void exp6(
const Eigen::MatrixBase<Vector6Like> & vec6, Eigen::MatrixBase<Config_t> & qout)
173 ::pinocchio::quaternion::exp6(nu, qout);
181 template<
typename Vector6Like>
183 Matrix<
typename Vector6Like::Scalar, 7, 1, PINOCCHIO_EIGEN_PLAIN_TYPE(Vector6Like)::Options>
184 exp6(const Eigen::MatrixBase<Vector6Like> & vec6)
186 typedef typename Vector6Like::Scalar Scalar;
189 Options = PINOCCHIO_EIGEN_PLAIN_TYPE(Vector6Like)::Options
191 typedef Eigen::Matrix<Scalar, 7, 1, Options> ReturnType;
194 ::pinocchio::quaternion::exp6(vec6, qout);
205 template<
typename QuaternionLike>
207 typename QuaternionLike::Scalar,
210 PINOCCHIO_EIGEN_PLAIN_TYPE(
typename QuaternionLike::Vector3)::Options>
212 const Eigen::QuaternionBase<QuaternionLike> & quat, typename QuaternionLike::Scalar & theta)
214 typedef typename QuaternionLike::Scalar Scalar;
217 Options = PINOCCHIO_EIGEN_PLAIN_TYPE(
typename QuaternionLike::Vector3)::Options
219 typedef Eigen::Matrix<Scalar, 3, 1, Options> Vector3;
222 const Scalar norm_squared = quat.vec().squaredNorm();
224 static const Scalar eps = Eigen::NumTraits<Scalar>::epsilon();
226 const Scalar norm = math::sqrt(norm_squared + eps * eps);
228 using ::pinocchio::internal::GE;
229 using ::pinocchio::internal::if_then_else;
230 using ::pinocchio::internal::LT;
232 const Scalar pos_neg = if_then_else(GE, quat.w(), Scalar(0), Scalar(+1), Scalar(-1));
234 Eigen::Quaternion<Scalar, Options> quat_pos;
235 quat_pos.w() = pos_neg * quat.w();
236 quat_pos.vec() = pos_neg * quat.vec();
238 const Scalar theta_2 = math::atan2(norm, quat_pos.w());
239 const Scalar y_x = norm / quat_pos.w();
240 const Scalar y_x_sq = norm_squared / (quat_pos.w() * quat_pos.w());
242 theta = if_then_else(
243 LT, norm_squared, ts_prec, Scalar(2.) * (Scalar(1) - y_x_sq / Scalar(3)) * y_x,
244 Scalar(2.) * theta_2);
246 const Scalar th2_2 = theta * theta / Scalar(4);
247 const Scalar inv_sinc = if_then_else(
248 LT, norm_squared, ts_prec,
249 Scalar(2) * (Scalar(1) + th2_2 / Scalar(6) + Scalar(7) / Scalar(360) * th2_2 * th2_2),
250 theta / math::sin(theta_2));
252 for (Eigen::DenseIndex k = 0; k < 3; ++k)
258 res[k] = inv_sinc * quat_pos.vec()[k];
272 template<
typename QuaternionLike>
274 typename QuaternionLike::Scalar,
277 PINOCCHIO_EIGEN_PLAIN_TYPE(
typename QuaternionLike::Vector3)::Options>
278 log3(const Eigen::QuaternionBase<QuaternionLike> & quat)
280 typename QuaternionLike::Scalar theta;
281 return log3(quat.derived(), theta);
291 template<
typename Vector3Like,
typename Matrix43Like>
293 const Eigen::MatrixBase<Vector3Like> & v,
const Eigen::MatrixBase<Matrix43Like> & Jexp)
296 assert(Jexp.rows() == 4 && Jexp.cols() == 3 &&
"Jexp does have the right size.");
297 Matrix43Like & Jout = PINOCCHIO_EIGEN_CONST_CAST(Matrix43Like, Jexp);
299 typedef typename Vector3Like::Scalar Scalar;
301 const Scalar n2 = v.squaredNorm();
302 const Scalar n = math::sqrt(n2);
303 const Scalar theta = Scalar(0.5) * n;
304 const Scalar theta2 = Scalar(0.25) * n2;
306 if (n2 > math::sqrt(Eigen::NumTraits<Scalar>::epsilon()))
310 Jout.template topRows<3>().noalias() =
311 ((Scalar(0.5) / n2) * (c - 2 * s / n)) * v * v.transpose();
312 Jout.template topRows<3>().diagonal().array() += s / n;
313 Jout.template bottomRows<1>().noalias() = -s / (2 * n) * v.transpose();
317 Jout.template topRows<3>().noalias() =
318 (-Scalar(1) / Scalar(12) + n2 / Scalar(480)) * v * v.transpose();
319 Jout.template topRows<3>().diagonal().array() += Scalar(0.5) * (1 - theta2 / 6);
320 Jout.template bottomRows<1>().noalias() =
321 (Scalar(-0.25) * (Scalar(1) - theta2 / 6)) * v.transpose();
331 template<
typename QuaternionLike,
typename Matrix3Like>
333 const Eigen::QuaternionBase<QuaternionLike> & quat,
334 const Eigen::MatrixBase<Matrix3Like> & Jlog)
336 typedef typename QuaternionLike::Scalar Scalar;
337 typedef Eigen::Matrix<
338 Scalar, 3, 1, PINOCCHIO_EIGEN_PLAIN_TYPE(
typename QuaternionLike::Coefficients)::Options>
342 Vector3 w(
log3(quat, t));
void exp3(const Eigen::MatrixBase< Vector3Like > &v, Eigen::QuaternionBase< QuaternionLike > &quat_out)
Exp: so3 -> SO3 (quaternion)
void exp6(const MotionDense< MotionDerived > &motion, Eigen::MatrixBase< Config_t > &qout)
The se3 -> SE3 exponential map, using quaternions to represent the output rotation.
void Jlog3(const Eigen::QuaternionBase< QuaternionLike > &quat, const Eigen::MatrixBase< Matrix3Like > &Jlog)
Computes the Jacobian of log3 operator for a unit quaternion.
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.
Main pinocchio namespace.
MotionTpl< Scalar, Options > motion(const JointDataTpl< Scalar, Options, JointCollectionTpl > &jdata)
Visit a JointDataTpl through JointMotionVisitor to get the joint internal motion as a dense motion.
void Jlog3(const Scalar &theta, const Eigen::MatrixBase< Vector3Like > &log, const Eigen::MatrixBase< Matrix3Like > &Jlog)
Derivative of log3.
void SINCOS(const S1 &a, S2 *sa, S3 *ca)
Computes sin/cos values of a given input scalar.