Describe the bug
HitResult.get_at() raises ArithmeticError: Trajectory does not reach distance when the requested value is infinitesimally larger than the last trajectory point, rather than returning that last point.
To Reproduce
- Fire a trajectory with a maximum distance that produces a final trajectory point of
39370.07874015748 inches
- Call
get_at("distance", value) where value is 39370.078740157485 (a floating point epsilon larger than the last point)
- See error:
ArithmeticError: Trajectory does not reach distance
Expected behavior
get_at should return the last TrajectoryData point when the requested value is within floating point precision of the final trajectory point. The epsilon parameter is intended to handle this case, but is never reached because the forward search loop condition key_value <= next_val filters out any value greater than the last trajectory point before any epsilon comparison can occur, causing target_idx to remain -1 and the error to be raised unconditionally.
Root Cause
In the forward search loop:
for i in range(start_idx, n - 1):
if (curr_val < key_value <= next_val) or (next_val <= key_value < curr_val):
target_idx = i + 1
break
When key_value is fractionally greater than the last point, no bracketing pair is found and target_idx stays -1. The fix would be to add an epsilon check against traj[-1] before raising:
if target_idx == -1:
if abs(get_key_val(traj[-1]) - key_value) < epsilon:
return traj[-1]
raise ArithmeticError(f"Trajectory does not reach {key_attribute} = {value}")
Environment:
- OS: [Linux]
- Python3 version: [3.10]
- Release [2.2.8]
Additional context
The difference between the last trajectory point and the requested value is ~4.9e-13 inches, which is a floating point precision artifact of unit conversion (meters → inches). Passing a larger epsilon to get_at does not work around this issue since the epsilon check is never reached — the only current workaround is to clamp the input value to the last trajectory point before calling get_at.
Describe the bug
HitResult.get_at()raisesArithmeticError: Trajectory does not reach distancewhen the requested value is infinitesimally larger than the last trajectory point, rather than returning that last point.To Reproduce
39370.07874015748inchesget_at("distance", value)wherevalueis39370.078740157485(a floating point epsilon larger than the last point)ArithmeticError: Trajectory does not reach distanceExpected behavior
get_atshould return the lastTrajectoryDatapoint when the requested value is within floating point precision of the final trajectory point. Theepsilonparameter is intended to handle this case, but is never reached because the forward search loop conditionkey_value <= next_valfilters out any value greater than the last trajectory point before any epsilon comparison can occur, causingtarget_idxto remain-1and the error to be raised unconditionally.Root Cause
In the forward search loop:
When
key_valueis fractionally greater than the last point, no bracketing pair is found andtarget_idxstays-1. The fix would be to add an epsilon check againsttraj[-1]before raising:Environment:
Additional context
The difference between the last trajectory point and the requested value is
~4.9e-13inches, which is a floating point precision artifact of unit conversion (meters → inches). Passing a largerepsilontoget_atdoes not work around this issue since the epsilon check is never reached — the only current workaround is to clamp the input value to the last trajectory point before callingget_at.