Significant numerical precision problem with Transform class
Summary
I am using Transform
s 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
- Compile the code
- Run it
- 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