package fr.cs.examples.propagation;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.ode.nonstiff.AdaptiveStepsizeIntegrator;
import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
import org.orekit.bodies.CelestialBodyFactory;
import org.orekit.bodies.OneAxisEllipsoid;
import org.orekit.data.DataProvidersManager;
import org.orekit.data.DirectoryCrawler;
import org.orekit.errors.OrekitException;
import org.orekit.files.ccsds.OEMWriter;
import org.orekit.files.ccsds.OEMWriter.InterpolationMethod;
import org.orekit.files.general.OrekitEphemerisFile;
import org.orekit.files.general.OrekitEphemerisFile.OrekitSatelliteEphemeris;
import org.orekit.forces.ForceModel;
import org.orekit.forces.drag.DragForce;
import org.orekit.forces.drag.IsotropicDrag;
import org.orekit.forces.drag.atmosphere.Atmosphere;
import org.orekit.forces.drag.atmosphere.DTM2000;
import org.orekit.forces.drag.atmosphere.data.MarshallSolarActivityFutureEstimation;
import org.orekit.forces.gravity.HolmesFeatherstoneAttractionModel;
import org.orekit.forces.gravity.ThirdBodyAttraction;
import org.orekit.forces.gravity.potential.GravityFieldFactory;
import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
import org.orekit.forces.radiation.IsotropicRadiationSingleCoefficient;
import org.orekit.forces.radiation.SolarRadiationPressure;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.orbits.CartesianOrbit;
import org.orekit.orbits.Orbit;
import org.orekit.orbits.OrbitType;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.analytical.tle.TLE;
import org.orekit.propagation.analytical.tle.TLEPropagator;
import org.orekit.propagation.numerical.NumericalPropagator;
import org.orekit.propagation.sampling.OrekitFixedStepHandler;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.PVCoordinates;
import org.orekit.utils.TimeStampedPVCoordinates;
/** Master propagation of an orbit, taking a maneuver into account
*
This class extends the step handler in order to save the spacecraft state at the given step.
* @author Nicolas ROL
*/
public class ManeuverPropagation_mastermode {
// Initialisation de la liste des états à enregistrer
static List states = new ArrayList();
public static void main(String[] args) throws IllegalArgumentException, OrekitException {
// TODO Auto-generated method stub
try {
// Configure Orekit data access
File orekitData = new File(System.getProperty("user.home"),"");
if (!orekitData.exists()) {
System.err.format(Locale.US, "Failed to find %s folder%n",
orekitData.getAbsolutePath());
System.err.format(Locale.US, "You need to download %s from the %s page and unzip it in %s for this tutorial to work%n",
"orekit-data.zip", "https://www.orekit.org/forge/projects/orekit/files",
System.getProperty("user.home"));
System.exit(1);
}
DataProvidersManager datamanager = DataProvidersManager.getInstance();
datamanager.addProvider(new DirectoryCrawler(orekitData));
/* ======================= PARAMETRES UTILISATEUR ======================= */
// Initial orbit
double x = 37727.9251691374e3;
double y = 18861.4712301990e3;
double z = -26.5028594459892e3;
double vx = -1.37284241956570e3;
double vy = 2.75000801092554e3;
double vz = 4.512254183365766E-002;
// Dates
final AbsoluteDate dateDebut = new AbsoluteDate(2018, 8, 31, 00, 00, 00, TimeScalesFactory.getUTC());
final AbsoluteDate dateManeuvre = new AbsoluteDate(2018, 9, 10, 00, 00, 00, TimeScalesFactory.getUTC());
final AbsoluteDate dateFin = new AbsoluteDate(2018, 9, 10, 00, 00, 00, TimeScalesFactory.getUTC());
// DV de la manoeuvre (m/s)
final double dVValue = 0;
// Output Folder
final String outputFolder = "";
// Name of the ephemeris file
final String outputFileName = "test_maneuverpropagator_dv0_9_10_tol0.oem";
// Pas de temps dans l'éphéméride (s)
final double stepSizeSeconds = 60.0*15;
// Satellite
final String satName = "satName";
final String cosparID = "cosparID";
// Créateur du fichier
final String creator = "Me";
/* ======================= DONNEES UNIVERS ======================= */
// Corps principal
final Frame bodyFrame = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
final double equatorialRadius = Constants.WGS84_EARTH_EQUATORIAL_RADIUS;
final double flattening = Constants.WGS84_EARTH_FLATTENING;
final OneAxisEllipsoid body = new OneAxisEllipsoid(equatorialRadius, flattening, bodyFrame);
// Champ de gravité
final NormalizedSphericalHarmonicsProvider gravityField = GravityFieldFactory.getNormalizedProvider(20, 20);
// Constante gravitationnelle
final double mu = gravityField.getMu();
/* ======================= INITIALISATION DE LA PROPAGATION ======================= */
// Création de l'orbite initiale
Vector3D vecteurPosition = new Vector3D(x,y,z);
Vector3D vecteurVitesse = new Vector3D(vx,vy,vz);
Orbit initialOrbit = new CartesianOrbit(new PVCoordinates(vecteurPosition,vecteurVitesse), FramesFactory.getGCRF(),
dateDebut, mu);
// Définition de l'état initial
SpacecraftState initialState = new SpacecraftState(initialOrbit);
// Intégrateur à pas adaptatif
final double minStep = 0.001;
final double maxstep = 1000.0;
final double positionTolerance = 1e-1;
final OrbitType propagationType = OrbitType.CARTESIAN;
final double[][] tolerances =
NumericalPropagator.tolerances(positionTolerance, initialOrbit, propagationType);
AdaptiveStepsizeIntegrator integrator =
new DormandPrince853Integrator(minStep, maxstep, tolerances[0], tolerances[1]);
// Propagateur
NumericalPropagator propagator = new NumericalPropagator(integrator);
propagator.setOrbitType(propagationType);
// Etat initial du propagateur
propagator.setInitialState(initialState);
// Sélection du mode "Master"
propagator.setMasterMode(stepSizeSeconds, new PropagationStepHandler());
// Modèle de champ de gravité
ForceModel holmesFeatherstone = new HolmesFeatherstoneAttractionModel(bodyFrame,gravityField);
propagator.addForceModel(holmesFeatherstone);
// Attraction liée à un 3e corps
propagator.addForceModel(new ThirdBodyAttraction(CelestialBodyFactory.getSun()));
propagator.addForceModel(new ThirdBodyAttraction(CelestialBodyFactory.getMoon()));
// Trainée
final double cd = 0;
final double area = 1;
MarshallSolarActivityFutureEstimation msafe =
new MarshallSolarActivityFutureEstimation("(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\\p{Digit}\\p{Digit}\\p{Digit}\\p{Digit}F10\\.(?:txt|TXT)",
MarshallSolarActivityFutureEstimation.StrengthLevel.AVERAGE);
DataProvidersManager manager = DataProvidersManager.getInstance();
manager.feed(msafe.getSupportedNames(), msafe);
Atmosphere atmosphere = new DTM2000(msafe, CelestialBodyFactory.getSun(), body);
propagator.addForceModel(new DragForce(atmosphere, new IsotropicDrag(area, cd)));
// Pression de la radiation solaire
final double cr = 1.65297718908878;
propagator.addForceModel(new SolarRadiationPressure(CelestialBodyFactory.getSun(),
body.getEquatorialRadius(),
new IsotropicRadiationSingleCoefficient(area, cr)));
/* ======================= PROPAGATION JUSQU'A LA MANOEUVRE ======================= */
// Extrapolation de la date initiale à la date de la manoeuvre
SpacecraftState beforeManeuverState = propagator.propagate(dateManeuvre);
/* ======================= MANOEUVRE ======================= */
// Coordonnées avant manoeuvre
TimeStampedPVCoordinates coordAvantManoeuvre = beforeManeuverState.getOrbit().getPVCoordinates();
Vector3D vitesse = coordAvantManoeuvre.getVelocity();
// Manoeuvre
Vector3D dVVector = vitesse.normalize().scalarMultiply(dVValue);
System.out.println("dV : " + dVVector);
// Position et vitesse après manoeuvre
TimeStampedPVCoordinates coordApresManoeuvre = new TimeStampedPVCoordinates(coordAvantManoeuvre.getDate(),
coordAvantManoeuvre.getPosition(),
coordAvantManoeuvre.getVelocity().add(dVVector));
// Orbite après manoeuvre
Orbit orbitApresManoeuvre = new CartesianOrbit(coordApresManoeuvre, FramesFactory.getGCRF(), mu);
// Affichage de l'orbite après manoeuvre
System.out.println(" Orbite après manoeuvre :");
System.out.println(" Date de la manoeuvre : " + orbitApresManoeuvre.getDate());
System.out.println(" " + orbitApresManoeuvre);
// Suppression du dernier état ajouté afin de ne pas avoir de doublon dans l'OEM
states.remove(states.size()-1);
/* ======================= PROPAGATION APRES LA MANOEUVRE ======================= */
// Définition de l'état initial après la manoeuvre
SpacecraftState ManeuverState = new SpacecraftState(orbitApresManoeuvre);
// Etat initial du propagateur après la manoeuvre
propagator.setInitialState(ManeuverState);
// Extrapolation de la date initiale à la date de la manoeuvre
SpacecraftState endState = propagator.propagate(dateFin);
// Affichage de l'orbite après manoeuvre
System.out.println(" Orbite finale :");
System.out.println(" Date de fin : " + endState.getDate());
System.out.println(" " + endState.getOrbit());
/* ======================= GENERATION DE L'EPHEMERIDE ======================= */
// Initialisation de l'éphéméride
OrekitEphemerisFile ephemerisFile = new OrekitEphemerisFile();
OrekitSatelliteEphemeris satellite = ephemerisFile.addSatellite(cosparID);
satellite.addNewSegment(states);
// Création de l'enregistreur OEM
OEMWriter writer = new OEMWriter(InterpolationMethod.LAGRANGE, creator, cosparID, satName);
// Ecriture du fichier
writer.write(outputFolder + outputFileName, ephemerisFile);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/** Specialized step handler.
* This class extends the step handler in order to save the spacecraft state at the given step.
* @author Nicolas ROL
*/
private static class PropagationStepHandler implements OrekitFixedStepHandler {
private PropagationStepHandler() {
//private constructor
}
public void init(final SpacecraftState s0, final AbsoluteDate t, final double step) {
// Affichage de l'orbite au début de la propagation
System.out.println(" Orbite initiale :");
System.out.println(" Date de début : " + s0.getDate());
System.out.println(" " + s0.getOrbit());
}
public void handleStep(SpacecraftState currentState, boolean isLast) {
states.add(currentState);
if (isLast) {
// Affichage de l'orbite à la fin de la propagation
System.out.println(" Orbite en fin de propagation :");
System.out.println(" Date de fin : " + currentState.getDate());
System.out.println(" " + currentState.getOrbit());
}
}
}
}