/* Copyright 2002-2017 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.propagation.analytical;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.attitudes.LofOffset;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.LOFType;
import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.Orbit;
import org.orekit.orbits.PositionAngle;
import org.orekit.propagation.AdditionalStateProvider;
import org.orekit.propagation.Propagator;
import org.orekit.propagation.SpacecraftState;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.TimeComponents;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.TimeStampedPVCoordinates;
public class EphemerisTest {
private AbsoluteDate initDate;
private AbsoluteDate finalDate;
private Frame inertialFrame;
private Propagator propagator;
@Test
public void testAttitudeOverride() throws IllegalArgumentException, OrekitException {
final double positionTolerance = 1e-6;
final double velocityTolerance = 1e-5;
final double attitudeTolerance = 1e-6;
int numberOfInterals = 1440;
double deltaT = finalDate.durationFrom(initDate)/((double)numberOfInterals);
propagator.setAttitudeProvider(new LofOffset(inertialFrame, LOFType.VVLH));
List<SpacecraftState> states = new ArrayList<SpacecraftState>(numberOfInterals + 1);
for (int j = 0; j<= numberOfInterals; j++) {
states.add(propagator.propagate(initDate.shiftedBy((j * deltaT))));
}
int numInterpolationPoints = 2;
Ephemeris ephemPropagator = new Ephemeris(states, numInterpolationPoints);
Assert.assertEquals(0, ephemPropagator.getManagedAdditionalStates().length);
//First test that we got position, velocity and attitude nailed
int numberEphemTestIntervals = 2880;
deltaT = finalDate.durationFrom(initDate)/((double)numberEphemTestIntervals);
for (int j = 0; j <= numberEphemTestIntervals; j++) {
AbsoluteDate currentDate = initDate.shiftedBy(j * deltaT);
SpacecraftState ephemState = ephemPropagator.propagate(currentDate);
SpacecraftState keplerState = propagator.propagate(currentDate);
double positionDelta = calculatePositionDelta(ephemState, keplerState);
double velocityDelta = calculateVelocityDelta(ephemState, keplerState);
double attitudeDelta = calculateAttitudeDelta(ephemState, keplerState);
Assert.assertEquals("VVLH Unmatched Position at: " + currentDate, 0.0, positionDelta, positionTolerance);
Assert.assertEquals("VVLH Unmatched Velocity at: " + currentDate, 0.0, velocityDelta, velocityTolerance);
Assert.assertEquals("VVLH Unmatched Attitude at: " + currentDate, 0.0, attitudeDelta, attitudeTolerance);
}
//Now force an override on the attitude and check it against a Keplerian propagator
//setup identically to the first but with a different attitude
//If override isn't working this will fail.
propagator = new KeplerianPropagator(propagator.getInitialState().getOrbit());
propagator.setAttitudeProvider(new LofOffset(inertialFrame, LOFType.QSW));
ephemPropagator.setAttitudeProvider(new LofOffset(inertialFrame,LOFType.QSW));
for (int j = 0; j <= numberEphemTestIntervals; j++) {
AbsoluteDate currentDate = initDate.shiftedBy(j * deltaT);
SpacecraftState ephemState = ephemPropagator.propagate(currentDate);
SpacecraftState keplerState = propagator.propagate(currentDate);
double positionDelta = calculatePositionDelta(ephemState, keplerState);
double velocityDelta = calculateVelocityDelta(ephemState, keplerState);
double attitudeDelta = calculateAttitudeDelta(ephemState, keplerState);
Assert.assertEquals("QSW Unmatched Position at: " + currentDate, 0.0, positionDelta, positionTolerance);
Assert.assertEquals("QSW Unmatched Velocity at: " + currentDate, 0.0, velocityDelta, velocityTolerance);
Assert.assertEquals("QSW Unmatched Attitude at: " + currentDate, 0.0, attitudeDelta, attitudeTolerance);
}
}
@Test
public void testSerialization() throws OrekitException, IOException, ClassNotFoundException {
propagator.setAttitudeProvider(new LofOffset(inertialFrame, LOFType.VVLH));
int numberOfIntervals = 150;
double deltaT = finalDate.durationFrom(initDate) / numberOfIntervals;
List<SpacecraftState> states = new ArrayList<SpacecraftState>(numberOfIntervals + 1);
for (int j = 0; j<= numberOfIntervals; j++) {
states.add(propagator.propagate(initDate.shiftedBy((j * deltaT))));
}
int numInterpolationPoints = 2;
Ephemeris ephemPropagator = new Ephemeris(states, numInterpolationPoints);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(ephemPropagator);
Assert.assertTrue(bos.size() > 30000);
Assert.assertTrue(bos.size() < 31000);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Ephemeris deserialized = (Ephemeris) ois.readObject();
Assert.assertEquals(deserialized.getMinDate(), deserialized.getMinDate());
Assert.assertEquals(deserialized.getMaxDate(), deserialized.getMaxDate());
for (double dt = 0; dt < finalDate.durationFrom(initDate); dt += 10.0) {
AbsoluteDate date = initDate.shiftedBy(dt);
TimeStampedPVCoordinates pvRef = ephemPropagator.getPVCoordinates(date, inertialFrame);
TimeStampedPVCoordinates pv = deserialized.getPVCoordinates(date, inertialFrame);
Assert.assertEquals(0.0, Vector3D.distance(pvRef.getPosition(), pv.getPosition()), 1.0e-15);
Assert.assertEquals(0.0, Vector3D.distance(pvRef.getVelocity(), pv.getVelocity()), 1.0e-15);
Assert.assertEquals(0.0, Vector3D.distance(pvRef.getAcceleration(), pv.getAcceleration()), 1.0e-15);
}
}
@Test
public void testNonResettableState() {
try {
propagator.setAttitudeProvider(new LofOffset(inertialFrame, LOFType.VVLH));
List<SpacecraftState> states = new ArrayList<SpacecraftState>();
for (double dt = 0; dt >= -1200; dt -= 60.0) {
states.add(propagator.propagate(initDate.shiftedBy(dt)));
}
new Ephemeris(states, 2).resetInitialState(propagator.getInitialState());
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.NON_RESETABLE_STATE, oe.getSpecifier());
}
}
@Test
public void testAdditionalStates() throws OrekitException {
final String name1 = "dt0";
final String name2 = "dt1";
propagator.setAttitudeProvider(new LofOffset(inertialFrame, LOFType.VVLH));
List<SpacecraftState> states = new ArrayList<SpacecraftState>();
for (double dt = 0; dt >= -1200; dt -= 60.0) {
final SpacecraftState original = propagator.propagate(initDate.shiftedBy(dt));
final SpacecraftState expanded = original.addAdditionalState(name2, original.getDate().durationFrom(finalDate));
states.add(expanded);
}
final Propagator ephem = new Ephemeris(states, 2);
ephem.addAdditionalStateProvider(new AdditionalStateProvider() {
public String getName() {
return name1;
}
public double[] getAdditionalState(SpacecraftState state) {
return new double[] { state.getDate().durationFrom(initDate) };
}
});
final String[] additional = ephem.getManagedAdditionalStates();
Arrays.sort(additional);
Assert.assertEquals(2, additional.length);
Assert.assertEquals(name1, ephem.getManagedAdditionalStates()[0]);
Assert.assertEquals(name2, ephem.getManagedAdditionalStates()[1]);
Assert.assertTrue(ephem.isAdditionalStateManaged(name1));
Assert.assertTrue(ephem.isAdditionalStateManaged(name2));
Assert.assertFalse(ephem.isAdditionalStateManaged("not managed"));
SpacecraftState s = ephem.propagate(initDate.shiftedBy(-270.0));
Assert.assertEquals(-270.0, s.getAdditionalState(name1)[0], 1.0e-15);
Assert.assertEquals(-86670.0, s.getAdditionalState(name2)[0], 1.0e-15);
}
@Test
public void testProtectedMethods()
throws OrekitException, SecurityException, NoSuchMethodException,
InvocationTargetException, IllegalAccessException {
propagator.setAttitudeProvider(new LofOffset(inertialFrame, LOFType.VVLH));
List<SpacecraftState> states = new ArrayList<SpacecraftState>();
for (double dt = 0; dt >= -1200; dt -= 60.0) {
final SpacecraftState original = propagator.propagate(initDate.shiftedBy(dt));
final SpacecraftState modified = new SpacecraftState(original.getOrbit(),
original.getAttitude(),
original.getMass() - 0.0625 * dt);
states.add(modified);
}
final Propagator ephem = new Ephemeris(states, 2);
Method propagateOrbit = Ephemeris.class.getDeclaredMethod("propagateOrbit", AbsoluteDate.class);
propagateOrbit.setAccessible(true);
Method getMass = Ephemeris.class.getDeclaredMethod("getMass", AbsoluteDate.class);
getMass.setAccessible(true);
SpacecraftState s = ephem.propagate(initDate.shiftedBy(-270.0));
Orbit o = (Orbit) propagateOrbit.invoke(ephem, s.getDate());
double m = ((Double) getMass.invoke(ephem, s.getDate())).doubleValue();
Assert.assertEquals(0.0,
Vector3D.distance(s.getPVCoordinates().getPosition(),
o.getPVCoordinates().getPosition()),
1.0e-15);
Assert.assertEquals(s.getMass(), m, 1.0e-15);
}
@Before
public void setUp() throws IllegalArgumentException, OrekitException {
Utils.setDataRoot("regular-data");
initDate = new AbsoluteDate(new DateComponents(2004, 01, 01),
TimeComponents.H00,
TimeScalesFactory.getUTC());
finalDate = new AbsoluteDate(new DateComponents(2004, 01, 02),
TimeComponents.H00,
TimeScalesFactory.getUTC());
double a = 7187990.1979844316;
double e = 0.5e-4;
double i = 1.7105407051081795;
double omega = 1.9674147913622104;
double OMEGA = FastMath.toRadians(261);
double lv = 0;
double mu = 3.9860047e14;
inertialFrame = FramesFactory.getEME2000();
Orbit initialState = new KeplerianOrbit(a, e, i, omega, OMEGA, lv, PositionAngle.TRUE,
inertialFrame, initDate, mu);
propagator = new KeplerianPropagator(initialState);
}
private double calculatePositionDelta(SpacecraftState state1, SpacecraftState state2) {
return Vector3D.distance(state1.getPVCoordinates().getPosition(), state2.getPVCoordinates().getPosition());
}
private double calculateVelocityDelta(SpacecraftState state1, SpacecraftState state2) {
return Vector3D.distance(state1.getPVCoordinates().getVelocity(), state2.getPVCoordinates().getVelocity());
}
private double calculateAttitudeDelta(SpacecraftState state1, SpacecraftState state2) {
return Rotation.distance(state1.getAttitude().getRotation(), state2.getAttitude().getRotation());
}
}