[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Orekit Developers] Resetting Additional States in Event Handler



Hi Luc,

Many thanks for your fast and constructive response, I have followed your approached and it works (see full at the end of the email).

Yes, I will create a bug report for this.

I just have one additional question:

A) I have implemented the AdditionalStatesProvider not storing the event epoch, but simply changing the value that should be provided. Is this solution also valid?

Thanks a lot,
Frank


public static class MyProvider implements AdditionalStateProvider {
private double value = -1;
@Override
public String getName() {
return "A";
}

@Override
public double[] getAdditionalState(SpacecraftState state) throws OrekitException {
return new double[] {value};
}
public void setValue(double value) {
this.value = value;
}
}
public static class MyHandler implements EventHandler<DateDetector> {
private final MyProvider myProvider;

public MyHandler(MyProvider myProvider) {
this.myProvider = myProvider;
}
@Override
public Action eventOccurred(SpacecraftState s, DateDetector detector, boolean increasing)
throws OrekitException {
myProvider.setValue(+1);
return Action.CONTINUE;
}
}
public static void main(String[] args) throws OrekitException {

// Load Orekit data
DataProvidersManager.getInstance()
.addProvider(new DirectoryCrawler(new File("OREKIT_DATA_PATH_HERE")));

// Build orbit
AbsoluteDate date0 = new AbsoluteDate(2000, 1, 1, TimeScalesFactory.getUTC());
Orbit orbit = new KeplerianOrbit(7.1E6, 0, 0, 0, 0, 0, PositionAngle.TRUE, FramesFactory.getGCRF(), date0,
Constants.WGS84_EARTH_MU);

// Build propagator
ODEIntegrator odeIntegrator = new DormandPrince853Integrator(1E-3, 1E3, 1E-6, 1E-6);
NumericalPropagator propagator = new NumericalPropagator(odeIntegrator);


// Create initial state and add it to the propagator
SpacecraftState initialState = new SpacecraftState(orbit).addAdditionalState("A", -1);

propagator.setInitialState(initialState);
//Create provider and handler
MyProvider myProvider = new MyProvider();
EventHandler<DateDetector> myHandler = new MyHandler(myProvider);
// Create date detector and handler
DateDetector dateDetector = new DateDetector(date0.shiftedBy(3)).withHandler(myHandler);

propagator.addEventDetector(dateDetector);
propagator.addAdditionalStateProvider(myProvider);

// Set the propagator mode
propagator.setMasterMode(1, new OrekitFixedStepHandler() {

@Override
public void handleStep(SpacecraftState currentState, boolean isLast) throws OrekitException {
String line = currentState.getDate().toString();

for (Entry<String, double[]> entry : currentState.getAdditionalStates().entrySet()) {
line += " " + entry.getKey();

for (double d : entry.getValue()) {
line += " " + d;
}
}
System.out.println(line);
}
});

// Propagate
propagator.propagate(date0, date0.shiftedBy(5));
}




On Mon, Jul 9, 2018 at 3:00 PM, MAISONOBE Luc <luc.maisonobe@c-s.fr> wrote:

Frank Mason <frankmason1992@gmail.com> a écrit :

Hi,

Hi Frank,


I am trying to use an Event Handler to reset an additional state (called
"A"), changing its value from -1 to +1 when the event is detected. The new
state built inside the handler contains the proper value (+1), however,
when the propagator goes on, it seems to ignore it and keeps its original
value of "-1". Console output looks like this:

*2000-01-01T00:00:00.000 A -1.0*
*2000-01-01T00:00:01.000 A -1.0*
*Additional state A set to +1*
*2000-01-01T00:00:02.000 A -1.0*

The value -1 at 00:00:02.000 is normal. The state is really changed
at 00:00:03.000. the fact the print statement from event handler
and the print statement from step handler are out of order is a
know limitation of Orekit which we cannot fix.

*2000-01-01T00:00:03.000 A -1.0*
*2000-01-01T00:00:04.000 A -1.0*

The value -1 at 00:00:03.000 *could* be considered normal, as at that
time the value changes, so both -1 or +1 could be acceptable.

The value -1 at 00:00:04.000 is a bug! It is due to the fact this
additional state as no corresponding provider. I.E. it was set up
un the initial state, but theaddAdditionalStateProvider method from
the Propagator interface was never called. Therefore, the propagator
considers the additional state is fixed and that when creating
complete states throughout the propagation it simply copies the
value from initial state. This is done in the protected method
updateAdditionalStates in the AbstractPropagator class.

Could you file a bug on the forge so we do not forget to fix this?

You may try as a workaround to set up an AdditionalStateProvider and
in the eventOccurred event of your event handler, you could remember
the date of the last switch, and return either -1 or +1 depending on
the state date being before or after the switch date. Beware that
the AdditionalStateProvider.getAdditionalState method *could*
potentially be called out of order, so you really should store
the event date and use it.


* // Instantiate additional states*
* Map<String, double[]> additionalStates = new HashMap<String, double[]>();*
* additionalStates.put("A", new double[] { -1 });*

* // Create initial state and add it to the propagator*
* SpacecraftState initialState = new SpacecraftState(orbit,
additionalStates);*

Rather than dealing directly with Map, I would suggest that you use
the fluent API of Spacecraftstate and directly use:

SpacecraftState initialState = new SpacecraftState(orbit).addAdditionalState("A", -1);


* @Override*
* public SpacecraftState resetState(DateDetector detector, SpacecraftState
oldState) {*
* Map<String, double[]> newAdditionalStates = new HashMap<String,
double[]>();*
* newAdditionalStates.put("A", new double[] { +1 });*

* SpacecraftState newSpacecraftState = new
SpacecraftState(oldState.getOrbit(), oldState.getAttitude(),*
* oldState.getMass(), newAdditionalStates);*

* System.out.println("Additional state A set to +1");*
* return newSpacecraftState;*
* }*
* });*


Here, creating the Map by yourself is probably an error. It assumes there are
no other additional states. If for example another part of the code had added
another state (for example partial derivative equations in orbit determination
do add some additional state by themselves), then these would be lost and only
your "A" state would be present. You should really be

  public SpacecraftState resetState(DateDetector detector, SpacecraftState oldState) {
      SpacecraftState newSpacecraftState = oldState.addAdditionalState("A", +1);
      System.out.println("Additional state A set to +1 at " + oldState.getDate());
      return newSpacecraftState;
  }

best regards,
Luc