This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Cannot use AngleAxis<ceres::Jet> operator =

Tags: None
(comma "," separated)
jsola
Registered Member
Posts
4
Karma
0
Eigen 3.2.2, Mac OSX El Capitan.

Hi. As part of a large robotics project, I wrote this function:
Code: Select all
template<typename Derived>
inline Eigen::Matrix<typename Derived::Scalar, 3, 1> log_q(const Eigen::QuaternionBase<Derived>& _q)
{
    typedef typename Derived::Scalar T;
    Eigen::AngleAxis<T> aa(_q);
    return aa.angle() * aa.axis();
}

which pretends to use Eigen's ability to convert from different rotation representations to write the logarithm of a quaternion via AngleAxis.

When using a Quaternion<ceres::Jet> type, we have Derived::Scalar = ceres::Jet<double, 7> and the following error occurs at compile time:
Code: Select all
In file included from /usr/local/include/eigen3/Eigen/Geometry:43:
/usr/local/include/eigen3/Eigen/src/Geometry/AngleAxis.h:181:14: error: invalid operands to binary expression ('Scalar' (aka 'ceres::Jet<double, 7>') and 'int')
    if(q.w() < 0)
       ~~~~~ ^ ~

which refers to line 181 in AngleAxis.h, with the operator=,
Code: Select all
template<typename Scalar>
template<typename QuatDerived>
EIGEN_DEVICE_FUNC AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived>& q)
{
  EIGEN_USING_STD_MATH(atan2)
  EIGEN_USING_STD_MATH(abs)
  Scalar n = q.vec().norm();
  if(n<NumTraits<Scalar>::epsilon())
    n = q.vec().stableNorm();

  if (n != Scalar(0))
  {
    m_angle = Scalar(2)*atan2(n, abs(q.w()));
    if(q.w() < 0)
      n = -n;
    m_axis  = q.vec() / n;
  }
  else
  {
    m_angle = Scalar(0);
    m_axis << Scalar(1), Scalar(0), Scalar(0);
  }
  return *this;
}


In this line 181, we see:
Code: Select all
    if(q.w() < 0)

which is comparing a ceres::Jet q.w() against an 'int' scalar (not even a double!).

Usually, we would rather cast the plain scalar for Jet compatibility (ceres::Jet is very picky with these otherwise obvious binary operators)
Code: Select all
    if( q.w() < Scalar(0) )

being Scalar precisely the ceres::Jet type, through the template definition (or at least I assume so).

I tried to alter this line as suggested above, and other errors then followed, like this:
Code: Select all
In file included from /usr/local/include/eigen3/Eigen/Core:446:
/usr/local/include/eigen3/Eigen/src/Core/StableNorm.h:26:33: error: no member named 'highest' in 'Eigen::NumTraits<ceres::Jet<double, 7> >'
    if(tmp > NumTraits<Scalar>::highest())
             ~~~~~~~~~~~~~~~~~~~^


This second error is now cryptic to me. So I stopped my investigation and reverted to a custom implementation of my log_q function (which is not very complicated anyway).

Am I doing anything wrong? Could I expect Eigen's AngleAxis to accept a Quaternion<Jet> and work at all? Is this a minor Eigen bug, or would this fix require major redesign efforts?

Thank you.
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
Please check with a recent version of Eigen first.
jsola
Registered Member
Posts
4
Karma
0
Sorry for the old version. Just tried with Eigen 3.3.4. The issue remains exactly the same as explained in the original post.
jsola
Registered Member
Posts
4
Karma
0
In order to narrow the issue, I have edited the 'AngleAxis::operator=' function to:
Code: Select all
template<typename Scalar>
template<typename QuatDerived>
EIGEN_DEVICE_FUNC AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived>& q)
{
  EIGEN_USING_STD_MATH(atan2)
  EIGEN_USING_STD_MATH(abs)
  Scalar n = q.vec().norm();
 // if(n<NumTraits<Scalar>::epsilon())   // <-- edited here
  //  n = q.vec().stableNorm();          // <-- edited here

  if (n != Scalar(0))
  {
    m_angle = Scalar(2)*atan2(n, abs(q.w()));
    if(q.w() < Scalar(0))                // <-- edited here
      n = -n;
    m_axis  = q.vec() / n;
  }
  else
  {
    m_angle = Scalar(0);
    m_axis << Scalar(1), Scalar(0), Scalar(0);
  }
  return *this;
}

that is, I casted the lonely '0' value, and commented out the 'stableNorm()' call, which was giving problems.

My 'log_q' function now compiles and executes correctly.
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
I checked and both problems have been fixed a while ago. For "highest" you need to update ceres. For Scalar(0), you need the head of the 3.3 branch (will be 3.3.5).
jsola
Registered Member
Posts
4
Karma
0
Thanks for this answer. Success required both HEAD versions of eigen and ceres-solver. In this order:
Code: Select all
brew install --HEAD eigen
brew install --build-from-source --HEAD ceres-solver


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], Sogou [Bot]