humanoid-path-planner/hpp-fcl

Interpretation of Assertions

cologne86 opened this issue ยท 8 comments

Hi,
Using this library without NDEBUG set i am experiencing crashes caused by assert calls.

I am getting assertions using two hpp::fcl::BVHModel<hpp::fcl::OBBRSS> objects as input
calling hpp::fcl::collide. Depending on transformations those would sometimes cause one of the following asserts:

assert(NeedNormalizedDir || dir.cwiseAbs().maxCoeff() >= 1e-6);

assert(false);

assert(!(da * ca_da + dc * da_aa - dd * ca_aa <=

However, when looking at the surrounding code here:

       if (la > lb) {
          assert(false);
          w0 = b0;
          w1 = b1;

it seems that these assertions are not explicitly error states,but the algorithm does handle the input in that case. Constraints in other cases also seem to me quite strict.

When building the software with NDEBUG, results still look valid and i have not experienced any crashes.
The question is:
Should the assertions never be triggered with a valid input, or is it OK to go on without debug information?

I guess this is related to an ill-formated shape with degenerated faces (e.g., aligned points belonging to a triangle).
@lmontaut WHat is your thoughts?

Hi @cologne86,
Could you please provide an example of code to replicate and fix the bugs?

The asserts correspond to degenerate cases that can happen with a valid input.

assert(NeedNormalizedDir || dir.cwiseAbs().maxCoeff() >= 1e-6);

This assert failing is due to GJK currently using a relative convergence criterion making the value 1e-6 arbitrary. This will be fixed in hppfcl3x notably by switching to an absolute convergence criterion.

assert(false);

This assert signals a rare behavior when computing nearest points between two shapes, related to how GJK constructs the simplex leading to the computation of nearest points. The code after the assert is the fallback behavior of hppfcl. The computed nearest points remain valid however.

assert(!(da * ca_da + dc * da_aa - dd * ca_aa <=

This assert can trigger if the simplex is degenerate (a tetrahedron with 0 volume).

Thanks a lot for your quick replies, code and mesh generation is included in a larger context.
I will work on a small example test to trigger these asserts, will need a bit of time.

It seems i was wrong about:

assert(false);

I was not able to trigger that assert but another one:
assert(result.distance_lower_bound <= 0);

Created a pull request that adds a test cpp. However i did not include it as it would result in tests failing.

I have another question regarding this statement:

This assert failing is due to GJK currently using a relative convergence criterion making the value 1e-6 arbitrary. This will be fixed in hppfcl3x notably by switching to an absolute convergence criterion.

Is there a risk in the current implementation, that the algorithm wont converge?

It will converge as it is a convex optimization problem, and we have a limit on the number of iterations. It is just that the check values are not properly aligned together and they are mostly here for developing purposes.

No, the algorithm will converge. At the end of the day GJK is an algorithm with solves a convex optimization problem, up to a certain tolerance w.r.t the optimal solution of this optimization problem.
Switching from a relative to an absolute convergence criterion simply changes the mathematical guarantees of the algorithm in terms of distance to the optimal solution.
The reason why this is not already done is because if we switch from a relative to an absolute convergence criterion, then the tolerance of the algo (the default is 1e-6) does not have the same geometrical interpretation.

At the end of the day using an absolute convergence criterion rather than a relative one makes it much easier to work with in the code and it is also much simpler to interpret geometrically, I have already done some tests in the past and this seems to resolve a lot of the asserts I have encountered.

Similar as @cologne86 I am getting these assertions when the library is compiled in debug mode. Specifically from the collide function inside collision_node.cpp when enable_contact is set to true

assert(result.distance_lower_bound * result.distance_lower_bound -
                   sqrDistLowerBound <
               1e-8);

when is it expected that result.distance_lower_bound * result.distance_lower_bound does not match sqrDistLowerBound ?