1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
template<typename Matrix3Like, typename Vector3Out> static void run( const Eigen::MatrixBase<Matrix3Like> & R, typename Matrix3Like::Scalar & theta, const Eigen::MatrixBase<Vector3Out> & angle_axis) { PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix3Like, R, 3, 3); PINOCCHIO_ASSERT_MATRIX_SPECIFIC_SIZE(Vector3Out, angle_axis, 3, 1); using namespace internal;
typedef typename Matrix3Like::Scalar Scalar; typedef Eigen::Matrix<Scalar, 3, 1, PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix3Like)::Options> Vector3; static const Scalar eps = Eigen::NumTraits<Scalar>::epsilon();
const static Scalar PI_value = PI<Scalar>(); Vector3Out & angle_axis_ = angle_axis.const_cast_derived();
typedef typename PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix3Like) Matrix3; const Matrix3 Rnormed = renormalize_rotation_matrix(R);
const Scalar tr = Rnormed.trace(); const Scalar cos_value = (tr - Scalar(1)) / Scalar(2);
const Scalar prec = TaylorSeriesExpansion<Scalar>::template precision<2>(); Vector3 angle_axis_singular; Scalar theta_singular;
{ Vector3 val_singular; val_singular.array() = Scalar(2) * Rnormed.diagonal().array() - tr + Scalar(1); Vector3 axis_0, axis_1, axis_2; Scalar theta_0, theta_1, theta_2;
internal::compute_theta_axis<0>(val_singular[0], Rnormed, theta_0, axis_0); internal::compute_theta_axis<1>(val_singular[1], Rnormed, theta_1, axis_1); internal::compute_theta_axis<2>(val_singular[2], Rnormed, theta_2, axis_2);
theta_singular = if_then_else( GE, val_singular[0], val_singular[1], if_then_else(GE, val_singular[0], val_singular[2], theta_0, theta_2), if_then_else(GE, val_singular[1], val_singular[2], theta_1, theta_2));
for (int k = 0; k < 3; ++k) angle_axis_singular[k] = if_then_else( GE, val_singular[0], val_singular[1], if_then_else(GE, val_singular[0], val_singular[2], axis_0[k], axis_2[k]), if_then_else(GE, val_singular[1], val_singular[2], axis_1[k], axis_2[k])); } const Scalar acos_expansion = math::sqrt(Scalar(2) * (Scalar(1) - cos_value) + eps * eps); const Scalar theta_nominal = if_then_else( LE, tr, static_cast<Scalar>(Scalar(3) - prec), if_then_else( GE, tr, static_cast<Scalar>(Scalar(-1) + prec), math::acos(cos_value), static_cast<Scalar>(PI_value - acos_expansion) ), static_cast<Scalar>(acos_expansion) ); assert( check_expression_if_real<Scalar>(theta_nominal == theta_nominal) && "theta contains some NaN");
Vector3 antisymmetric_R; unSkew(Rnormed, antisymmetric_R); const Scalar norm_antisymmetric_R_squared = antisymmetric_R.squaredNorm();
const Scalar t = if_then_else( GE, theta_nominal, prec, static_cast<Scalar>(theta_nominal / sin(theta_nominal)), static_cast<Scalar>( Scalar(1.) + norm_antisymmetric_R_squared / Scalar(6) + norm_antisymmetric_R_squared * norm_antisymmetric_R_squared * Scalar(3) / Scalar(40)) );
theta = if_then_else( GE, cos_value, static_cast<Scalar>(Scalar(-1.) + prec), theta_nominal, theta_singular);
for (int k = 0; k < 3; ++k) angle_axis_[k] = if_then_else( GE, cos_value, static_cast<Scalar>(Scalar(-1.) + prec), static_cast<Scalar>(t * antisymmetric_R[k]), static_cast<Scalar>(theta_singular * angle_axis_singular[k])); }
|