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

Euclidean Transformation

Tags: None
(comma "," separated)
hijokpayne
Registered Member
Posts
25
Karma
0

Euclidean Transformation

Tue Oct 30, 2012 3:13 pm
Hi all,

I am trying to store some euclidean transformation (3D rotation and translation) which is just a an affine transformation with linear part as a 3D rotation matrix. I am currently using the Transform class to store [R t] in affine-compact form (See the code below).

However when I take an inverse, I want to really get [R' -R't] instead computing an generic affine inverse. I can see that Tranform::inverse documentation has something called isometry, which is probably what I am looking for. But I couldn't figure out how to use that?

Code: Select all
// Typedef for SE(3) group (special euclidean group)
typedef Eigen::Transform< double, 3, AffineCompact > SE3;

SE3 camera;
Vector3d camera_centre =camera.inverse().translation();
// I want the above result to be just -R't instead of computing a generic affine inverse

Would really appreciate some help regarding this.
Oxyd
Registered Member
Posts
14
Karma
0
OS

Re: Euclidean Transformation

Tue Oct 30, 2012 5:29 pm
Just pass Isometry as the first argument to .inverse(). Like this:

Code: Select all
Eigen::Vector3d camera_centre = camera.inverse(Eigen::Isometry).translation();


In fact, since the argument defaults to the _Mode template parameter of Eigen::Transform, you could just use
Code: Select all
typedef Eigen::Transform<double, 3, Eigen::Isometry> SE3;
, which sounds more like what you want. In fact, this typedef is already in Eigen: Eigen::Isometry3d is Eigen::Transform<double, 3, Eigen::Isometry>.
hijokpayne
Registered Member
Posts
25
Karma
0

Re: Euclidean Transformation

Tue Oct 30, 2012 9:56 pm
Thanks a lot Oxyd, for your reply.

I have some more questions. If I want a Compact version (3x4) matrix version, how do I typedef it?
Code: Select all
typedef Eigen::Transform<double, 3, Eigen::AffineCompact, Eigen::Isometry> SE3;
compiles, but I suspect its not doing isometry inversion when we I call
Code: Select all
camera.inverse().translation()


Also how do I check the actual expression produced by Eigen (pardon my c++ knowledge). Right now I using the following code to check the runtime and the above typedef takes more time than using Isometry3d or directly using inverse(Isometry) function.
Code: Select all
#include <Eigen/Geometry>
#include <Eigen/Dense>
#include <boost/timer/timer.hpp>

using namespace Eigen;

int main(int argc, char *argv[]) {
  typedef Transform<double, 3, AffineCompact, Isometry> SE3;
 
  boost::timer::auto_cpu_timer t; 
 
  for (unsigned i = 0; i < 999999; ++i) {   
    SE3 camera;
    Vector3d a = camera.inverse().translation();
  }
  return 0;
}
Oxyd
Registered Member
Posts
14
Karma
0
OS

Re: Euclidean Transformation  Topic is solved

Tue Oct 30, 2012 10:44 pm
hijokpayne wrote:Also how do I check the actual expression produced by Eigen (pardon my c++ knowledge). Right now I using the following code to check the runtime and the above typedef takes more time than using Isometry3d or directly using inverse(Isometry) function.


Above all, I'd start by actually trusting the documentation and Eigen developers. You could step through the call with a debugger or read the source code:
Code: Select all
template<typename Scalar, int Dim, int Mode, int Options>
Transform<Scalar,Dim,Mode,Options>
Transform<Scalar,Dim,Mode,Options>::inverse(TransformTraits hint) const
{
  Transform res;
  if (hint == Projective)
  {
    internal::projective_transform_inverse<Transform>::run(*this, res);
  }
  else
  {
    if (hint == Isometry)
    {
      res.matrix().template topLeftCorner<Dim,Dim>() = linear().transpose();
    }
    else if(hint&Affine)
    {
      res.matrix().template topLeftCorner<Dim,Dim>() = linear().inverse();
    }
    else
    {
      eigen_assert(false && "Invalid transform traits in Transform::Inverse");
    }
    // translation and remaining parts
    res.matrix().template topRightCorner<Dim,1>()
    = - res.matrix().template topLeftCorner<Dim,Dim>() * translation();
    res.makeAffine(); // we do need this, because in the beginning res is uninitialized
  }
  return res;
}


As you can see, if hint == Isometry, the inverse amounts to transposing the linear part and setting the last column to the product of the transposed linear part and the original last column, with the sign inverted.

Your typedef
Code: Select all
typedef Eigen::Transform<double, 3, Eigen::AffineCompact, Eigen::Isometry> SE3;
won't really work the way you want it to. You passed AffineCompact as the third template argument for the Mode parameter, and Isometry as the fourth argument which specifies the value of the Options parameter. The Options parameter is used for specifying whether the transformation is to be stored in row-major or column-major order and whether it should be aligned in memory.

However, it appears that if you use Eigen::Isometry3d, AKA Eigen::Transform<double, 3, Eigen::Isometry>, you won't get the compact 3x4 representation, and if you choose the compact 3x4 representation, you won't get the fast inverse you're after as a default behaviour.

So I'd say the best option here is to use
Code: Select all
typedef Eigen::AffineCompact3d SE3;
SE3 camera;
// ...
camera.inverse(Eigen::Isometry);  // Explicitely specify the hint every time you take the inverse.
This way you'll get the compact representation, and you can always ask for a fast inverse by specifying the hint each time you call .inverse.
hijokpayne
Registered Member
Posts
25
Karma
0

Re: Euclidean Transformation

Tue Oct 30, 2012 11:09 pm
Thanks Oxyd. That solves my doubts.


Bookmarks



Who is online

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