/* 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.attitudes;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
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.RotationConvention;
import org.hipparchus.geometry.euclidean.threed.RotationOrder;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.random.RandomGenerator;
import org.hipparchus.random.Well19937a;
import org.hipparchus.util.FastMath;
import org.hipparchus.util.MathUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.bodies.OneAxisEllipsoid;
import org.orekit.errors.OrekitException;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.LOFType;
import org.orekit.orbits.CircularOrbit;
import org.orekit.orbits.PositionAngle;
import org.orekit.propagation.BoundedPropagator;
import org.orekit.propagation.Propagator;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.analytical.KeplerianPropagator;
import org.orekit.propagation.sampling.OrekitFixedStepHandler;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.TimeComponents;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.AngularDerivativesFilter;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.PVCoordinates;
import org.orekit.utils.TimeStampedAngularCoordinates;
public class TabulatedLofOffsetTest {
// Computation date
private AbsoluteDate date;
// Body mu
private double mu;
// Reference frame = ITRF
private Frame itrf;
// Earth shape
OneAxisEllipsoid earth;
// Satellite position
CircularOrbit orbit;
PVCoordinates pvSatEME2000;
@Test
public void testConstantOffset() throws OrekitException {
RandomGenerator random = new Well19937a(0x1199d4bb8f53d2b6l);
for (LOFType type : LOFType.values()) {
for (int i = 0; i < 100; ++i) {
double a1 = random.nextDouble() * MathUtils.TWO_PI;
double a2 = random.nextDouble() * MathUtils.TWO_PI;
double a3 = random.nextDouble() * MathUtils.TWO_PI;
LofOffset law = new LofOffset(orbit.getFrame(), type, RotationOrder.XYZ, a1, a2, a3);
Rotation offsetAtt = law.getAttitude(orbit, orbit.getDate(), orbit.getFrame()).getRotation();
LofOffset aligned = new LofOffset(orbit.getFrame(), type);
Rotation alignedAtt = aligned.getAttitude(orbit, orbit.getDate(), orbit.getFrame()).getRotation();
Rotation offsetProper = offsetAtt.compose(alignedAtt.revert(), RotationConvention.VECTOR_OPERATOR);
TabulatedLofOffset tabulated =
new TabulatedLofOffset(orbit.getFrame(), type,
Arrays.asList(new TimeStampedAngularCoordinates(orbit.getDate().shiftedBy(-10),
offsetProper,
Vector3D.ZERO,
Vector3D.ZERO),
new TimeStampedAngularCoordinates(orbit.getDate().shiftedBy(0),
offsetProper,
Vector3D.ZERO,
Vector3D.ZERO),
new TimeStampedAngularCoordinates(orbit.getDate().shiftedBy(+10),
offsetProper,
Vector3D.ZERO,
Vector3D.ZERO)),
2, AngularDerivativesFilter.USE_R);
Rotation rebuilt = tabulated.getAttitude(orbit, orbit.getDate(), orbit.getFrame()).getRotation();
Assert.assertEquals(0.0, Rotation.distance(offsetAtt, rebuilt), 1.2e-15);
}
}
}
@Test
public void testYawCompensation() throws OrekitException {
// create a sample from Yaw compensation law
final LOFType type = LOFType.VNC;
final List<TimeStampedAngularCoordinates> sample = new ArrayList<TimeStampedAngularCoordinates>();
final AttitudeProvider yawCompensLaw =
new YawCompensation(orbit.getFrame(), new NadirPointing(orbit.getFrame(), earth));
final Propagator originalPropagator = new KeplerianPropagator(orbit);
originalPropagator.setAttitudeProvider(yawCompensLaw);
originalPropagator.setMasterMode(1.0, new OrekitFixedStepHandler() {
public void handleStep(final SpacecraftState currentState, final boolean isLast)
throws OrekitException {
Rotation offsetAtt = currentState.getAttitude().getRotation();
LofOffset aligned = new LofOffset(currentState.getFrame(), type);
Rotation alignedAtt = aligned.getAttitude(currentState.getOrbit(), currentState.getDate(),
currentState.getFrame()).getRotation();
Rotation offsetProper = offsetAtt.compose(alignedAtt.revert(), RotationConvention.VECTOR_OPERATOR);
sample.add(new TimeStampedAngularCoordinates(currentState.getDate(),
offsetProper, Vector3D.ZERO, Vector3D.ZERO));
}
});
originalPropagator.propagate(orbit.getDate().shiftedBy(2000));
originalPropagator.setSlaveMode();
// use the sample and compare it to original
final AttitudeProvider tabulated = new TabulatedLofOffset(orbit.getFrame(),type, sample,
6, AngularDerivativesFilter.USE_RR);
final Propagator rebuildingPropagator = new KeplerianPropagator(orbit);
rebuildingPropagator.setAttitudeProvider(tabulated);
rebuildingPropagator.setMasterMode(0.3, new OrekitFixedStepHandler() {
public void handleStep(final SpacecraftState currentState, final boolean isLast)
throws OrekitException {
final SpacecraftState rebuilt = originalPropagator.propagate(currentState.getDate());
final Rotation r1 = currentState.getAttitude().getRotation();
final Rotation r2 = rebuilt.getAttitude().getRotation();
Assert.assertEquals(0.0, Rotation.distance(r1, r2), 7.0e-6);
}
});
rebuildingPropagator.propagate(orbit.getDate().shiftedBy(50), orbit.getDate().shiftedBy(1950));
}
@Test
public void testSerialization() throws OrekitException, IOException, ClassNotFoundException {
// create a sample from Yaw compensation law
final LOFType type = LOFType.VNC;
final List<TimeStampedAngularCoordinates> sample = new ArrayList<TimeStampedAngularCoordinates>();
final AttitudeProvider yawCompensLaw =
new YawCompensation(orbit.getFrame(), new NadirPointing(orbit.getFrame(), earth));
final Propagator originalPropagator = new KeplerianPropagator(orbit);
originalPropagator.setAttitudeProvider(yawCompensLaw);
originalPropagator.setMasterMode(10.0, new OrekitFixedStepHandler() {
public void handleStep(final SpacecraftState currentState, final boolean isLast)
throws OrekitException {
Rotation offsetAtt = currentState.getAttitude().getRotation();
LofOffset aligned = new LofOffset(currentState.getFrame(), type);
Rotation alignedAtt = aligned.getAttitude(currentState.getOrbit(), currentState.getDate(),
currentState.getFrame()).getRotation();
Rotation offsetProper = offsetAtt.compose(alignedAtt.revert(), RotationConvention.VECTOR_OPERATOR);
sample.add(new TimeStampedAngularCoordinates(currentState.getDate(),
offsetProper, Vector3D.ZERO, Vector3D.ZERO));
}
});
originalPropagator.propagate(orbit.getDate().shiftedBy(2000));
originalPropagator.setSlaveMode();
// use the sample and generate an ephemeris
final AttitudeProvider tabulated = new TabulatedLofOffset(orbit.getFrame(),type, sample,
6, AngularDerivativesFilter.USE_RR);
final Propagator rebuildingPropagator = new KeplerianPropagator(orbit);
rebuildingPropagator.setAttitudeProvider(tabulated);
rebuildingPropagator.setEphemerisMode();
rebuildingPropagator.propagate(orbit.getDate().shiftedBy(5));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(rebuildingPropagator.getGeneratedEphemeris());
// even despite we propagated only 5 seconds, the attitude sample is huge
Assert.assertTrue(bos.size() > 17000);
Assert.assertTrue(bos.size() < 18000);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
TabulatedLofOffset deserialized = (TabulatedLofOffset) ((BoundedPropagator) ois.readObject()).getAttitudeProvider();
Assert.assertEquals(sample.size(), deserialized.getTable().size());
}
@Before
public void setUp() {
try {
Utils.setDataRoot("regular-data");
// Computation date
date = new AbsoluteDate(new DateComponents(2008, 04, 07),
TimeComponents.H00,
TimeScalesFactory.getUTC());
// Body mu
mu = 3.9860047e14;
// Reference frame = ITRF
itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
// Elliptic earth shape
earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
Constants.WGS84_EARTH_FLATTENING,
itrf);
// Satellite position
orbit =
new CircularOrbit(7178000.0, 0.5e-8, -0.5e-8, FastMath.toRadians(50.), FastMath.toRadians(150.),
FastMath.toRadians(5.300), PositionAngle.MEAN,
FramesFactory.getEME2000(), date, mu);
pvSatEME2000 = orbit.getPVCoordinates();
} catch (OrekitException oe) {
Assert.fail(oe.getMessage());
}
}
@After
public void tearDown() {
date = null;
itrf = null;
earth = null;
}
}