Skip to content

Commit be65ef7

Browse files
committed
Fix behaviour of eigen33 function if smallest eigenvalue is not unique
The documentation of the eigen33 function says: "if the smallest eigenvalue is not unique, this function may return any eigenvector that is consistent to the eigenvalue" Currently however, in that case the returned eigenvector is usually a vector of NaNs. This commit applies the same logic as the other eigen33 function below. The effect on run time is minimal (one subtraction and one comparison). In practice, it is rare that the smallest eigenvalue is not unique but it can happen, for example when normals are estimated with a very small neighbourhood. In the PCL tests, this is the case in the NormalRefinement test in test_filters.cpp
1 parent 9481fd9 commit be65ef7

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed

common/include/pcl/common/impl/eigen.hpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,10 +308,21 @@ eigen33 (const Matrix& mat, typename Matrix::Scalar& eigenvalue, Vector& eigenve
308308
computeRoots (scaledMat, eigenvalues);
309309

310310
eigenvalue = eigenvalues (0) * scale;
311-
312-
scaledMat.diagonal ().array () -= eigenvalues (0);
313-
314-
eigenvector = detail::getLargest3x3Eigenvector<Vector> (scaledMat).vector;
311+
if ( (eigenvalues (1) - eigenvalues (0)) > Eigen::NumTraits < Scalar > ::epsilon ()) {
312+
// usual case: first and second are not equal (so first and third are also not equal).
313+
// second and third could be equal, but that does not matter here
314+
scaledMat.diagonal ().array () -= eigenvalues (0);
315+
eigenvector = detail::getLargest3x3Eigenvector<Vector> (scaledMat).vector;
316+
}
317+
else if ( (eigenvalues (2) - eigenvalues (0)) > Eigen::NumTraits < Scalar > ::epsilon ()) {
318+
// first and second equal: choose any unit vector that is orthogonal to third eigenvector
319+
scaledMat.diagonal ().array () -= eigenvalues (2);
320+
eigenvector = detail::getLargest3x3Eigenvector<Vector> (scaledMat).vector.unitOrthogonal ();
321+
}
322+
else {
323+
// all three equal: just use an arbitrary unit vector
324+
eigenvector << Scalar (1.0), Scalar (0.0), Scalar (0.0);
325+
}
315326
}
316327

317328

0 commit comments

Comments
 (0)