Commit fd481cdd authored by Bryan Cazabonne's avatar Bryan Cazabonne
Browse files

Merge branch 'Issue-826' into pre-release

parents 7462f948 4541aa61
......@@ -1161,7 +1161,7 @@ abstract class PredefinedIAUPoles implements IAUPole {
public static PredefinedIAUPoles getIAUPole(final EphemerisType body,
final TimeScales timeScales) {
switch(body) {
switch (body) {
case SUN :
return new Sun(timeScales);
case MERCURY :
......
......@@ -80,7 +80,7 @@ public enum AttitudeType {
final RotationOrder eulerRotSequence,
final boolean isSpacecraftBodyRate,
final AbsoluteDate date,
final double...components) {
final double... components) {
Rotation rotation = isFirst ?
new Rotation(components[0], components[1], components[2], components[3], true) :
......@@ -142,7 +142,7 @@ public enum AttitudeType {
final RotationOrder eulerRotSequence,
final boolean isSpacecraftBodyRate,
final AbsoluteDate date,
final double...components) {
final double... components) {
FieldRotation<UnivariateDerivative1> rotation =
isFirst ?
new FieldRotation<>(new UnivariateDerivative1(components[0], components[4]),
......@@ -207,7 +207,7 @@ public enum AttitudeType {
final RotationOrder eulerRotSequence,
final boolean isSpacecraftBodyRate,
final AbsoluteDate date,
final double...components) {
final double... components) {
// Build the needed objects
final Rotation rotation = isFirst ?
new Rotation(components[0], components[1], components[2], components[3], true) :
......@@ -257,7 +257,7 @@ public enum AttitudeType {
final RotationOrder eulerRotSequence,
final boolean isSpacecraftBodyRate,
final AbsoluteDate date,
final double...components) {
final double... components) {
// Build the needed objects
Rotation rotation = new Rotation(eulerRotSequence, RotationConvention.FRAME_TRANSFORM,
......@@ -311,7 +311,7 @@ public enum AttitudeType {
final RotationOrder eulerRotSequence,
final boolean isSpacecraftBodyRate,
final AbsoluteDate date,
final double...components) {
final double... components) {
// Build the needed objects
final Rotation rotation = new Rotation(eulerRotSequence,
......@@ -374,7 +374,7 @@ public enum AttitudeType {
final RotationOrder eulerRotSequence,
final boolean isSpacecraftBodyRate,
final AbsoluteDate date,
final double...components) {
final double... components) {
// Build the needed objects
final Rotation rotation = new Rotation(RotationOrder.ZYZ,
......@@ -414,7 +414,7 @@ public enum AttitudeType {
final RotationOrder eulerRotSequence,
final boolean isSpacecraftBodyRate,
final AbsoluteDate date,
final double...components) {
final double... components) {
// Attitude parameters in the Specified Reference Frame for a Spin Stabilized Satellite
// are optional in CCSDS AEM format. Support for this attitude type is not implemented
// yet in Orekit.
......@@ -521,7 +521,7 @@ public enum AttitudeType {
*/
public abstract TimeStampedAngularCoordinates build(boolean isFirst, boolean isExternal2SpacecraftBody,
RotationOrder eulerRotSequence, boolean isSpacecraftBodyRate,
AbsoluteDate date, double...components);
AbsoluteDate date, double... components);
/**
* Get the angular derivative filter corresponding to the attitude data.
......
......@@ -188,7 +188,7 @@ public class SinexLoader {
// For now, only few keys are supported
// They represent the minimum set of parameters that are interesting to consider in a SINEX file
// Other keys can be added depending user needs
switch(line.trim()) {
switch (line.trim()) {
case "+SITE/ID" :
// Start of site id. data
inId = true;
......@@ -280,7 +280,7 @@ public class SinexLoader {
// check if this station exists
if (station != null) {
// switch on coordinates data
switch(parseString(line, 7, 6)) {
switch (parseString(line, 7, 6)) {
case "STAX":
// station X coordinate
final double x = parseDouble(line, 47, 22);
......
......@@ -214,7 +214,7 @@ public class AntexLoader {
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
++lineNumber;
switch(line.substring(LABEL_START).trim()) {
switch (line.substring(LABEL_START).trim()) {
case "COMMENT" :
// nothing to do
break;
......
......@@ -341,7 +341,7 @@ public enum RtcmDataField implements DataField {
@Override
public int intValue(final EncodedMessage message) {
// Word P1 indicates a time interval (in sec) between two adjacent values of tb parameter
switch(DataType.BIT_2.decode(message).intValue()) {
switch (DataType.BIT_2.decode(message).intValue()) {
case 0 : return 0;
case 1 : return 1800;
case 2 : return 2700;
......
......@@ -548,7 +548,7 @@ public class GlobalIonosphereMapModel extends AbstractSelfFeedingLoader
for (line = br.readLine(); line != null; line = br.readLine()) {
++lineNumber;
if (line.length() > LABEL_START) {
switch(line.substring(LABEL_START).trim()) {
switch (line.substring(LABEL_START).trim()) {
case "EPOCH OF FIRST MAP" :
firstEpoch = parseDate(line);
break;
......
......@@ -193,6 +193,16 @@ public class PropagatorsParallelizer {
} else {
// this was the last step
isLast = true;
/* For NumericalPropagators :
* After reaching the finalState with the selected monitor,
* we need to do the step with all remaining monitors to reach the target time.
* This also triggers the StoringStepHandler, producing ephemeris.
*/
for (PropagatorMonitoring monitor : monitors) {
if (monitor != selected) {
monitor.retrieveNextParameters();
}
}
}
previousDate = selectedStepEnd;
......@@ -407,6 +417,12 @@ public class PropagatorsParallelizer {
ParametersContainer params = null;
while (params == null && !future.isDone()) {
params = queue.poll(MAX_WAIT, TimeUnit.MILLISECONDS);
// Check to avoid loop on future not done, in the case of reached finalState.
if (parameters != null) {
if (parameters.finalState != null) {
break;
}
}
}
if (params == null) {
// call Future.get just for the side effect of retrieving the exception
......
......@@ -1048,6 +1048,9 @@ public abstract class AbstractIntegratedPropagator extends AbstractPropagator {
/** Generated ephemeris. */
private BoundedPropagator ephemeris;
/** Variable used to store the last interpolator handled by the object.*/
private ODEStateInterpolator lastInterpolator;
/** Set the end date.
* @param endDate end date
*/
......@@ -1065,11 +1068,15 @@ public abstract class AbstractIntegratedPropagator extends AbstractPropagator {
// ephemeris will be generated when last step is processed
this.ephemeris = null;
this.lastInterpolator = null;
}
/** {@inheritDoc} */
@Override
public BoundedPropagator getGeneratedEphemeris() {
// Each time we try to get the ephemeris, rebuild it using the last data.
buildEphemeris();
return ephemeris;
}
......@@ -1077,12 +1084,26 @@ public abstract class AbstractIntegratedPropagator extends AbstractPropagator {
@Override
public void handleStep(final ODEStateInterpolator interpolator) {
model.handleStep(interpolator);
lastInterpolator = interpolator;
}
/** {@inheritDoc} */
@Override
public void finish(final ODEStateAndDerivative finalState) {
buildEphemeris();
}
/** Method used to produce ephemeris at a given time.
* Can be used at multiple times, updating the ephemeris to
* its last state.
*/
private void buildEphemeris() {
// buildEphemeris was built in order to allow access to what was previously the finish method.
// This now allows to call it through getGeneratedEphemeris, therefore through an external call,
// which was not previously the case.
// Update the model's finalTime with the last interpolator.
model.finish(lastInterpolator.getCurrentState());
// set up the boundary dates
final double tI = model.getInitialTime();
final double tF = model.getFinalTime();
......
......@@ -378,7 +378,7 @@ public class AngularCoordinates implements TimeShiftable<AngularCoordinates>, Se
final DerivativeStructure q1DS;
final DerivativeStructure q2DS;
final DerivativeStructure q3DS;
switch(order) {
switch (order) {
case 0 :
factory = new DSFactory(1, order);
q0DS = factory.build(q0);
......
......@@ -379,7 +379,7 @@ public class FieldAngularCoordinates<T extends CalculusFieldElement<T>> {
final FieldDerivativeStructure<T> q1DS;
final FieldDerivativeStructure<T> q2DS;
final FieldDerivativeStructure<T> q3DS;
switch(order) {
switch (order) {
case 0 :
factory = new FDSFactory<>(q0.getField(), 1, order);
q0DS = factory.build(q0);
......
......@@ -356,7 +356,7 @@ public class FieldPVCoordinates<T extends CalculusFieldElement<T>>
final FieldDerivativeStructure<T> x;
final FieldDerivativeStructure<T> y;
final FieldDerivativeStructure<T> z;
switch(order) {
switch (order) {
case 0 :
factory = new FDSFactory<>(getPosition().getX().getField(), 1, order);
x = factory.build(position.getX());
......@@ -452,7 +452,7 @@ public class FieldPVCoordinates<T extends CalculusFieldElement<T>>
final FieldDerivativeStructure<T> x2;
final FieldDerivativeStructure<T> y2;
final FieldDerivativeStructure<T> z2;
switch(order) {
switch (order) {
case 0 :
factory = new FDSFactory<>(getPosition().getX().getField(), 1, order);
x0 = factory.build(position.getX());
......
......@@ -214,7 +214,7 @@ public class PVCoordinates implements TimeShiftable<PVCoordinates>, Serializable
final DerivativeStructure x;
final DerivativeStructure y;
final DerivativeStructure z;
switch(order) {
switch (order) {
case 0 :
factory = new DSFactory(1, order);
x = factory.build(position.getX());
......@@ -310,7 +310,7 @@ public class PVCoordinates implements TimeShiftable<PVCoordinates>, Serializable
final DerivativeStructure x2;
final DerivativeStructure y2;
final DerivativeStructure z2;
switch(order) {
switch (order) {
case 0 :
factory = new DSFactory(1, order);
x0 = factory.build(position.getX());
......
/* Copyright 2002-2022 CS GROUP
* Licensed to CS GROUP (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;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.hipparchus.ode.ODEIntegrator;
import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
import org.hipparchus.util.FastMath;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.attitudes.AttitudeProvider;
import org.orekit.attitudes.BodyCenterPointing;
import org.orekit.bodies.OneAxisEllipsoid;
import org.orekit.errors.OrekitException;
import org.orekit.forces.ForceModel;
import org.orekit.forces.gravity.HolmesFeatherstoneAttractionModel;
import org.orekit.forces.gravity.potential.GravityFieldFactory;
import org.orekit.forces.gravity.potential.ICGEMFormatReader;
import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
import org.orekit.frames.FramesFactory;
import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.Orbit;
import org.orekit.orbits.OrbitType;
import org.orekit.orbits.PositionAngle;
import org.orekit.propagation.analytical.EcksteinHechlerPropagator;
import org.orekit.propagation.events.DateDetector;
import org.orekit.propagation.numerical.NumericalPropagator;
import org.orekit.propagation.semianalytical.dsst.DSSTPropagator;
import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
import org.orekit.propagation.semianalytical.dsst.forces.DSSTZonal;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.TimeComponents;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
public class PropagatorsParallelizerEphemerisTest {
private double mass;
private Orbit orbit;
private AttitudeProvider attitudeLaw;
private UnnormalizedSphericalHarmonicsProvider unnormalizedGravityField;
private NormalizedSphericalHarmonicsProvider normalizedGravityField;
@Before
public void setUp() {
try {
Utils.setDataRoot("regular-data:potential/icgem-format");
unnormalizedGravityField = GravityFieldFactory.getUnnormalizedProvider(6, 0);
normalizedGravityField = GravityFieldFactory.getNormalizedProvider(6, 0);
mass = 2500;
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;
AbsoluteDate date = new AbsoluteDate(new DateComponents(2004, 01, 01),
TimeComponents.H00,
TimeScalesFactory.getUTC());
orbit = new KeplerianOrbit(a, e, i, omega, OMEGA, lv, PositionAngle.TRUE,
FramesFactory.getEME2000(), date, normalizedGravityField.getMu());
OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
Constants.WGS84_EARTH_FLATTENING,
FramesFactory.getITRF(IERSConventions.IERS_2010, true));
attitudeLaw = new BodyCenterPointing(orbit.getFrame(), earth);
} catch (OrekitException oe) {
Assert.fail(oe.getLocalizedMessage());
}
}
@After
public void tearDown() {
mass = Double.NaN;
orbit = null;
attitudeLaw = null;
unnormalizedGravityField = null;
normalizedGravityField = null;
}
/*
* Test set to check that ephemeris are produced at the end of the propagation parallelizer
* in the case of NuericalPropagators.
* Check existence of all ephemeris.
* Check end time of all ephemeris for varying step times.
*
* Should validate the modification, except for the retrieveNextParameters added check.
*
* Tests are based on Anne-Laure LUGAN's proposed test, and on PropagatorsParallelizerTest.
*/
@Test
public void testSeveralEphemeris() {
/*
* The closing behaviour is checked by verifying the presence of generated ephemeris as a result of the
* following process, using PropagatorsParallelizer.
*/
final AbsoluteDate startDate = orbit.getDate();
final AbsoluteDate endDate = startDate.shiftedBy(3600);
List<Propagator> propagators = Arrays.asList(buildNumerical(), buildNumerical(), buildDSST(), buildEcksteinHechler());
List<EphemerisGenerator> generators = propagators.stream().map(Propagator::getEphemerisGenerator).collect(Collectors.toList());
PropagatorsParallelizer parallelizer = new PropagatorsParallelizer(propagators, interpolators -> {
// Do nothing
});
parallelizer.propagate(startDate, endDate);
for ( EphemerisGenerator generator : generators ) {
Assert.assertNotNull(generator.getGeneratedEphemeris());
Assert.assertEquals(endDate, generator.getGeneratedEphemeris().getMaxDate());
Assert.assertEquals(startDate, generator.getGeneratedEphemeris().getMinDate());
}
}
@Test
public void testSeveralEphemerisDateDetector() {
/*
* The closing behaviour is checked for a stop event occuring during the propagation.
* The test isn't applied to analytical propagators as their behaviour differs.
* (Analytical propagator's ephemerides are the analytical propagators.)
*/
final AbsoluteDate startDate = orbit.getDate();
final AbsoluteDate endDate = startDate.shiftedBy(3600.015);
List<Propagator> propagators = Arrays.asList(buildNumerical(1,300), buildNumerical(0.001,300), buildDSST());
// Add new instance of event with same date. DateDetector behaviour at event is stop.
AbsoluteDate detectorDate = startDate.shiftedBy(1800);
propagators.stream().forEach(propagator -> propagator.addEventDetector(new DateDetector(detectorDate)));
List<EphemerisGenerator> generators = propagators.stream().map(Propagator::getEphemerisGenerator).collect(Collectors.toList());
PropagatorsParallelizer parallelizer = new PropagatorsParallelizer(propagators, interpolators -> {
// Do nothing
});
parallelizer.propagate(startDate, endDate);
// Check for all generators
for ( EphemerisGenerator generator : generators ) {
Assert.assertNotNull(generator.getGeneratedEphemeris());
Assert.assertEquals(startDate, generator.getGeneratedEphemeris().getMinDate());
Assert.assertEquals(detectorDate, generator.getGeneratedEphemeris().getMaxDate());
}
}
private EcksteinHechlerPropagator buildEcksteinHechler() {
return new EcksteinHechlerPropagator(orbit, attitudeLaw, mass, unnormalizedGravityField);
}
private DSSTPropagator buildDSST(final double minStep, final double maxStep) {
// Gravity
Utils.setDataRoot("regular-data:potential/icgem-format");
GravityFieldFactory.addPotentialCoefficientsReader(new ICGEMFormatReader("^eigen-6s-truncated$", false));
UnnormalizedSphericalHarmonicsProvider gravity = GravityFieldFactory.getUnnormalizedProvider(8, 8);
// Propagator
final double[][] tol = DSSTPropagator.tolerances(0.01, orbit);
final DSSTPropagator propagator = new DSSTPropagator(new DormandPrince853Integrator(minStep, maxStep, tol[0], tol[1]), PropagationType.MEAN);
// Force models
final DSSTForceModel zonal = new DSSTZonal(gravity, 4, 3, 9);
propagator.addForceModel(zonal);
propagator.setInitialState(new SpacecraftState(orbit));
return propagator;
}
private DSSTPropagator buildDSST() {
return buildDSST(0.01,300);
}
private NumericalPropagator buildNumerical() {
return buildNumerical(0.001,300);
}
private NumericalPropagator buildNumerical(double minStep, double maxStep) {
NumericalPropagator numericalPropagator = buildNotInitializedNumerical(minStep, maxStep);
numericalPropagator.setInitialState(new SpacecraftState(orbit,
attitudeLaw.getAttitude(orbit,
orbit.getDate(),
orbit.getFrame()),
mass));
return numericalPropagator;
}
private NumericalPropagator buildNotInitializedNumerical(double minStep, double maxStep) {
OrbitType type = OrbitType.CARTESIAN;
double[][] tolerances = NumericalPropagator.tolerances(10.0, orbit, type);
ODEIntegrator integrator = new DormandPrince853Integrator(minStep, maxStep, tolerances[0], tolerances[1]);
NumericalPropagator numericalPropagator = new NumericalPropagator(integrator);
ForceModel gravity = new HolmesFeatherstoneAttractionModel(FramesFactory.getITRF(IERSConventions.IERS_2010, true),
normalizedGravityField);
numericalPropagator.addForceModel(gravity);
return numericalPropagator;
}
}
......@@ -17,9 +17,11 @@
package org.orekit.propagation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import org.hipparchus.exception.LocalizedCoreFormats;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment