Skip to content

Significant numerical precision problem with Transform class

Summary

I am using Transforms and there inverse()s and I am experiencing significant problems when transforming back and forth.

An input vector of (0, 0, 0.5) transformed back and forth experiences a > 5% change in value and ends up as (7.61623e-05, -0.00129452,, 0.528492). Is this expected when using double?

The transform in question is a pure rotation.

t=
   0.81933   0.534046   0.309697          0
  -0.54007   0.870082 -0.0718602          0
 -0.299069  -0.107862   0.977705          0
         0          0          0          1
t_inv * t=
     1.05242 -8.70961e-05  0.000152325            0
-8.70961e-05      1.05388  -0.00258904            0
 0.000152325  -0.00258904      1.05698            0
           0            0            0            1
Point transformed:   0.154849 -0.0359301   0.488853
Point transformed back: 7.61623e-05 -0.00129452    0.528492
delta: 0.0570422

Even just computing T_inv * T shows a significant deviation from the identity. So I am wondering if I am doing something wrong or whether this level of inaccuracy is expected with floating point numbers.

The magnitude of the vector seems to be unrelated. If I multiply by 1000, the relative error is the same.

I also verified I am not using too few digits. The matrix in question was generated via

Isometry3d t(AngleAxisd(deg2rad(35), Vector3d(-0.03138390697137638519, 0.5306755320777536422, -0.936332369193589531)));

The Eigen version used here is 3147391d.

Environment

  • Operating System : macOS
  • Architecture : Arm64
  • Eigen Version : 3.3.9 (3147391d, but same with master)
  • Compiler Version : Apple Clang 14.0.1
  • Compile Flags : -g -std=gnu++20 -arch arm64 -ftemplate-backtrace-limit=0 -ffloat-store -mtune=native -Xclang -fopenmp -fPIC -MD -MT
  • Vector Extension : Neon (same result with -DEIGEN_DONT_VECTORIZE)

Minimal Example

   Isometry3d t;
  t.matrix() << 0.81933, 0.534046, 0.309697, 0, -0.54007, 0.870082, -0.0718602,
      0, -0.299069, -0.107862, 0.977705, 0, 0, 0, 0, 1;
  std::cout << "t=\n" << t.matrix() << std::endl;
  Isometry3d t_inv = t.inverse();
  std::cout << "t_inv * t=\n" << (t_inv * t).matrix() << std::endl;
  Vector3d p(0, 0, 0.5);
  Vector3d p2 = (t_inv * t) * p;
  std::cout << "Point transformed: " << (t * p).transpose() << std::endl;
  std::cout << "Point transformed back: " << p2.transpose() << std::endl;
  std::cout << "delta: " << (p - p2).norm() / p.norm() << std::endl;

Steps to reproduce

  1. Compile the code
  2. Run it
  3. inspect inaccuracy of result

What is the current bug behavior?

Significant loss of precision when computing T_inv * T-

What is the expected correct behavior?

Not as much loss of precision

Edited by Rasmus