use of org.orekit.propagation.sampling.FieldOrekitFixedStepHandler in project Orekit by CS-SI.
the class AttitudesSequenceTest method doTestDayNightSwitchField.
private <T extends RealFieldElement<T>> void doTestDayNightSwitchField(final Field<T> field) throws OrekitException {
// Initial state definition : date, orbit
final FieldAbsoluteDate<T> initialDate = new FieldAbsoluteDate<>(field, 2004, 01, 01, 23, 30, 00.000, TimeScalesFactory.getUTC());
final FieldVector3D<T> position = new FieldVector3D<>(field, new Vector3D(-6142438.668, 3492467.560, -25767.25680));
final FieldVector3D<T> velocity = new FieldVector3D<>(field, new Vector3D(505.8479685, 942.7809215, 7435.922231));
final FieldOrbit<T> initialOrbit = new FieldKeplerianOrbit<>(new FieldPVCoordinates<>(position, velocity), FramesFactory.getEME2000(), initialDate, Constants.EIGEN5C_EARTH_MU);
// Attitudes sequence definition
EventsLogger logger = new EventsLogger();
final AttitudesSequence attitudesSequence = new AttitudesSequence();
final AttitudeProvider dayObservationLaw = new LofOffset(initialOrbit.getFrame(), LOFType.VVLH, RotationOrder.XYZ, FastMath.toRadians(20), FastMath.toRadians(40), 0);
final AttitudeProvider nightRestingLaw = new LofOffset(initialOrbit.getFrame(), LOFType.VVLH);
final PVCoordinatesProvider sun = CelestialBodyFactory.getSun();
final PVCoordinatesProvider earth = CelestialBodyFactory.getEarth();
final EclipseDetector ed = new EclipseDetector(sun, 696000000., earth, Constants.WGS84_EARTH_EQUATORIAL_RADIUS).withHandler(new ContinueOnEvent<EclipseDetector>() {
private static final long serialVersionUID = 1L;
int count = 0;
public EventHandler.Action eventOccurred(final SpacecraftState s, final EclipseDetector d, final boolean increasing) {
setInEclipse(s.getDate(), !increasing);
if (count++ == 7) {
return Action.STOP;
} else {
switch(count % 3) {
case 0:
return Action.CONTINUE;
case 1:
return Action.RESET_DERIVATIVES;
default:
return Action.RESET_STATE;
}
}
}
});
final EventDetector monitored = logger.monitorDetector(ed);
final Handler dayToNightHandler = new Handler(dayObservationLaw, nightRestingLaw);
final Handler nightToDayHandler = new Handler(nightRestingLaw, dayObservationLaw);
attitudesSequence.addSwitchingCondition(dayObservationLaw, nightRestingLaw, monitored, false, true, 300.0, AngularDerivativesFilter.USE_RRA, dayToNightHandler);
attitudesSequence.addSwitchingCondition(nightRestingLaw, dayObservationLaw, monitored, true, false, 300.0, AngularDerivativesFilter.USE_RRA, nightToDayHandler);
FieldSpacecraftState<T> initialState = new FieldSpacecraftState<>(initialOrbit);
initialState = initialState.addAdditionalState("fortyTwo", field.getZero().add(42.0));
if (ed.g(initialState.toSpacecraftState()) >= 0) {
// initial position is in daytime
setInEclipse(initialDate.toAbsoluteDate(), false);
attitudesSequence.resetActiveProvider(dayObservationLaw);
} else {
// initial position is in nighttime
setInEclipse(initialDate.toAbsoluteDate(), true);
attitudesSequence.resetActiveProvider(nightRestingLaw);
}
// Propagator : consider the analytical Eckstein-Hechler model
final FieldPropagator<T> propagator = new FieldEcksteinHechlerPropagator<T>(initialOrbit, attitudesSequence, Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS, Constants.EIGEN5C_EARTH_MU, Constants.EIGEN5C_EARTH_C20, Constants.EIGEN5C_EARTH_C30, Constants.EIGEN5C_EARTH_C40, Constants.EIGEN5C_EARTH_C50, Constants.EIGEN5C_EARTH_C60);
// Register the switching events to the propagator
attitudesSequence.registerSwitchEvents(field, propagator);
propagator.setMasterMode(field.getZero().add(60.0), new FieldOrekitFixedStepHandler<T>() {
public void handleStep(FieldSpacecraftState<T> currentState, boolean isLast) throws OrekitException {
// the Earth position in spacecraft frame should be along spacecraft Z axis
// during night time and away from it during day time due to roll and pitch offsets
final FieldVector3D<T> earth = currentState.toTransform().transformPosition(Vector3D.ZERO);
final T pointingOffset = FieldVector3D.angle(earth, Vector3D.PLUS_K);
// the g function is the eclipse indicator, its an angle between Sun and Earth limb,
// positive when Sun is outside of Earth limb, negative when Sun is hidden by Earth limb
final double eclipseAngle = ed.g(currentState.toSpacecraftState());
if (currentState.getDate().durationFrom(lastChange).getReal() > 300) {
if (inEclipse) {
Assert.assertTrue(eclipseAngle <= 0);
Assert.assertEquals(0.0, pointingOffset.getReal(), 1.0e-6);
} else {
Assert.assertTrue(eclipseAngle >= 0);
Assert.assertEquals(0.767215, pointingOffset.getReal(), 1.0e-6);
}
} else {
// we are in transition
Assert.assertTrue(pointingOffset.getReal() + " " + (0.767215 - pointingOffset.getReal()), pointingOffset.getReal() <= 0.7672155);
}
}
});
// Propagate from the initial date for the fixed duration
propagator.propagate(initialDate.shiftedBy(12600.));
// as we have 2 switch events (even if they share the same underlying event detector),
// and these events are triggered at both eclipse entry and exit, we get 8
// raw events on 2 orbits
Assert.assertEquals(8, logger.getLoggedEvents().size());
// we have 4 attitudes switch on 2 orbits, 2 of each type
Assert.assertEquals(2, dayToNightHandler.dates.size());
Assert.assertEquals(2, nightToDayHandler.dates.size());
}
Aggregations