Extract second-to-last SpacecraftState after event triggering

Hello all,

I am using the FieldNumericalPropagator in Master mode with a simple FieldEventDetector that stops the integration at the first occurrence (eventOccurred always returns Action.STOP) and I am looking for a particular implementation of the detector to do the following:

  1. check for an occurrence at each integrator-defined propagation step without limits on its size
  2. trigger Action.STOP each time an event occurs
  3. do NOT trigger any root finding algorithm to precisely locate the event in time
  4. retrieve the SpacecraftState (date, coordinates) at the last integration step just before the event has been triggered (normally the second-to-last step of the integrator when stopped by the step handler)

Also, the G function of the event detector is a switching function assuming only 2 discrete values (+1, -1) and is not continuous since I do not need to precisely locate the event.

Is it possible to implement such kind of detector (I am particularly interested in point 4) ?

Thank you very much,

Alberto

Hi @Alberto

You cannot prevent the root finding algorithm to be triggered, but you can make sure that it does not iterate too much by just specifying a sloopy convergence threshold. Beware not to make it too large, though otherwise you may end up with difficult problems if it is larger than the other checks. I would suggest something like 60 s or larger for maxCheck and maxCheck/2 for the convergence threshold.

In order to preserve a previous SpacecraftState, one simple solution would be to set up a step handler that just saves the last few steps and has some getters. When propagation completes your code could ask the handler for the previous steps it has seen.

You should be able to set maxCheck to a very large value and still check every integrator step. Current code assumes tolerance < maxCheck and that tolerance is small compared to the dynamics of the g function.

The code will also skip checking any integrator steps that are shorter than tolerance. That means the existing code probably has some bugs when the tolerance is greater than the integrator step size. I’ll create an issue to test that.

Thank you @luc and @evan.ward for the suggestions.

Indeed, using a StepHandler with getters enables to recover the last state just prior to the event.

Regarding the convergence threshold and the maxCheck parameter, I did some investigations setting both parameters equal to Double.POSITIVE_INFINITY which is my use case since I do not want to refine the root location. The EventState class is not used by Orekit numerical propagators, which rather wrap the equivalent FieldEventState of hipparchus-ode (I am using DerivativeStructure objects in my code), and all tests have been performed with these settings.

Indeed, the problem raised in issue #771 by @evan.ward occurs in this case, since the condition dt.abs().subtract(convergence).getReal() < 0 in evaluateStep() is satisfied. However, the event I am looking for is still correctly caught by the if statement if (state.tryAdvance(currentState, interpolator)) at line 422 of AbstractFieldIntegrator. Then the block of code at lines 443-447 of FieldEventState.tryAdvance() triggers the root finding and sets meFirst = true, which in turn allows a correct handling of the event action Action.STOP stopping the integration as expected.

Hope this can help you to decide if some changes are needed in the code.

Alberto

surprising, even for me who wrote that code. :slight_smile: But it makes sense. tryAdvance will always be called before processing another event or ending the step, and that method is designed to catch roots that weren’t found in evaluateStep.

I’ll post your analysis to the issue.