The next 4 tutorials detail some elementary usages of the propagation package described in the propagation section of the library architecture documentation.
Three different operational modes are available for all propagators. They are mutually exclusive.
This is the default mode. It doesn't need to be explicitly set, but it can be to recover from any other mode.
This tutorial shows how to propagate from an initial state to a target date.
In this case, the calling application coordinates all the tasks, the propagator just propagates.
Let's define the EME2000 inertial frame as reference frame:
Frame inertialFrame = FramesFactory.getEME2000();
Let's set up an initial state as:
TimeScale utc = TimeScalesFactory.getUTC(); AbsoluteDate initialDate = new AbsoluteDate(2004, 01, 01, 23, 30, 00.000, utc); double mu = 3.986004415e+14; double a = 24396159; // semi major axis in meters double e = 0.72831215; // eccentricity double i = Math.toRadians(7); // inclination double omega = Math.toRadians(180); // perigee argument double raan = Math.toRadians(261); // right ascension of ascending node double lM = 0; // mean anomaly
The initial orbit is defined as a KeplerianOrbit.
More details on the orbit representation can be found in the orbits section of the library architecture documentation.
Orbit initialOrbit = new KeplerianOrbit(a, e, i, omega, raan, lM, PositionAngle.MEAN, inertialFrame, initialDate, mu);
We choose to use a very simple KeplerianPropagator to compute basic keplerian motion.
It could be any of the available propagators.
KeplerianPropagator kepler = new KeplerianPropagator(initialOrbit);
Let's set the propagator to slave mode for the purpose of this tutorial, but keep in mind that it can be omitted here as it is the default mode.
kepler.setSlaveMode();
Finally, the propagation features of duration and step size are defined and a propagation loop is performed in order to print the results at each step:
double duration = 600.; AbsoluteDate finalDate = new AbsoluteDate(initialDate, duration, utc); double stepT = 60.; int cpt = 1; AbsoluteDate extrapDate = initialDate; while (extrapDate.compareTo(finalDate) <= 0) { SpacecraftState currentState = kepler.propagate(extrapDate); System.out.println("step " + cpt++); System.out.println(" time : " + currentState.getDate()); System.out.println(" " + currentState.getOrbit()); extrapDate = new AbsoluteDate(extrapDate, stepT, utc); }
The printed results are shown below (lines have been wrapped for better presentation)
step 1 time : 2004-01-01T23:30:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 441.0;} step 2 time : 2004-01-01T23:31:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 446.2813836335737;} step 3 time : 2004-01-01T23:32:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 451.5252613094112;} step 4 time : 2004-01-01T23:33:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 456.6958768398235;} step 5 time : 2004-01-01T23:34:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 461.7607703551739;} step 6 time : 2004-01-01T23:35:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 466.6919614270639;} step 7 time : 2004-01-01T23:36:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 471.4666804605399;} step 8 time : 2004-01-01T23:37:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 476.0676390794578;} step 9 time : 2004-01-01T23:38:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 480.4828961502498;} step 10 time : 2004-01-01T23:39:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 484.70541689946305;} step 11 time : 2004-01-01T23:40:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 488.7324362945905;}
In this mode, the propagator, as a master, calls some callback methods provided by the application throughout its internal integration loop.
As in the slave mode tutorial above, let's define some initial state with:
// Inertial frame Frame inertialFrame = FramesFactory.getEME2000(); // Initial date TimeScale utc = TimeScalesFactory.getUTC(); AbsoluteDate initialDate = new AbsoluteDate(2004, 01, 01, 23, 30, 00.000,utc); // Central attraction coefficient double mu = 3.986004415e+14; // Initial orbit double a = 24396159; // semi major axis in meters double e = 0.72831215; // eccentricity double i = Math.toRadians(7); // inclination double omega = Math.toRadians(180); // perigee argument double raan = Math.toRadians(261); // right ascention of ascending node double lM = 0; // mean anomaly Orbit initialOrbit = new KeplerianOrbit(a, e, i, omega, raan, lM, PositionAngle.MEAN, inertialFrame, initialDate, mu); // Initial state definition SpacecraftState initialState = new SpacecraftState(initialOrbit);
Here we use a more sophisticated NumericalPropagator based on an adaptive step integrator provided by the underlying Apache Commons Math library, but it doesn't matter which integrator is used.
// Adaptive step integrator // with a minimum step of 0.001 and a maximum step of 1000 double minStep = 0.001; double maxstep = 1000.0; double positionTolerance = 10.0; OrbitType propagationType = OrbitType.KEPLERIAN; double[][] tolerances = NumericalPropagator.tolerances(positionTolerance, initialOrbit, propagationType); AdaptiveStepsizeIntegrator integrator = new DormandPrince853Integrator(minStep, maxstep, tolerances[0], tolerances[1]);
We set up the integrator, and force it to use Keplerian parameters for propagation.
NumericalPropagator propagator = new NumericalPropagator(integrator); propagator.setOrbitType(propagationType);
A force model, reduced here to a single perturbing gravity field, is taken into account.
More details on force models can be found in the forces section of the library architecture documentation.
NormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getNormalizedProvider(10, 10); ForceModel holmesFeatherstone = new HolmesFeatherstoneAttractionModel(FramesFactory.getITRF2005(), provider);
This force model is simply added to the propagator:
propagator.addForceModel(holmesFeatherstone);
The propagator operating mode is set to master mode with fixed step and a TutorialStepHandler which implements the interface OrekitFixedStepHandler in order to fulfill the handleStep method to be called within the loop. For the purpose of this tutorial, the handleStep method will just print the current state at the moment.
propagator.setMasterMode(60., new TutorialStepHandler());
Then, the initial state is set for the propagator:
propagator.setInitialState(initialState);
Finally, the propagator is just asked to propagate, from the initial state, for a given duration.
SpacecraftState finalState = propagator.propagate(new AbsoluteDate(initialDate, 630.));
Clearly, with a few lines of code, the main application delegates to the propagator the care of handling regular outputs through a variable step integration loop.
All that is needed is to derive some class from the interface OrekitFixedStepHandler to realize a handleStep method, as follows:
private static class TutorialStepHandler implements OrekitFixedStepHandler { public void handleStep(SpacecraftState currentState, boolean isLast) { System.out.println(" time : " + currentState.getDate()); System.out.println(" " + currentState.getOrbit()); if (isLast) { System.out.println(" this was the last step "); } } }
The same result, with the slave mode, would have required much more programming.
The printed results are shown below:
time : 2004-01-01T23:30:00.000 keplerian parameters: {a: 2.4396159E7; e: 0.72831215; i: 7.0; pa: 180.0; raan: 261.0; v: 0.0;} time : 2004-01-01T23:31:00.000 keplerian parameters: {a: 2.439567294825084E7; e: 0.7283057298312567; i: 6.999926685028417; pa: 180.01099164196964; raan: 260.99996584983745; v: 5.270439090625698;} time : 2004-01-01T23:32:00.000 keplerian parameters: {a: 2.4394149109752804E7; e: 0.7282857977588459; i: 6.99975751751188; pa: 180.02188512355906; raan: 260.99976714716615; v: 10.503709968446776;} time : 2004-01-01T23:33:00.000 keplerian parameters: {a: 2.4391676555104487E7; e: 0.7282535195349812; i: 6.999506209571202; pa: 180.03255680755524; raan: 260.9992813856247; v: 15.664370104675593;} time : 2004-01-01T23:34:00.000 keplerian parameters: {a: 2.4388396500723846E7; e: 0.7282107346735237; i: 6.999190042362488; pa: 180.0428888146681; raan: 260.99842196418786; v: 20.72021960510703;} time : 2004-01-01T23:35:00.000 keplerian parameters: {a: 2.4384487471361116E7; e: 0.7281597572442904; i: 6.998827000702349; pa: 180.05278514952087; raan: 260.9971388510754; v: 25.64346271824545;} time : 2004-01-01T23:36:00.000 keplerian parameters: {a: 2.4380142510199904E7; e: 0.7281030828502557; i: 6.998434411462986; pa: 180.06218152381527; raan: 260.99541571200984; v: 30.411432652540466;} time : 2004-01-01T23:37:00.000 keplerian parameters: {a: 2.4375546778893556E7; e: 0.7280431044846278; i: 6.998028559931812; pa: 180.07104290690677; raan: 260.99326768361715; v: 35.00686637309839;} time : 2004-01-01T23:38:00.000 keplerian parameters: {a: 2.4370861667637732E7; e: 0.7279819115221708; i: 6.997624284331928; pa: 180.07935436842862; raan: 260.99073821046767; v: 39.41778587831865;} time : 2004-01-01T23:39:00.000 keplerian parameters: {a: 2.436621695941882E7; e: 0.7279211902927675; i: 6.997234270379576; pa: 180.08711236321756; raan: 260.98789263896447; v: 43.637076468122785;} time : 2004-01-01T23:40:00.000 keplerian parameters: {a: 2.4361709735003237E7; e: 0.7278622093554471; i: 6.996868366835913; pa: 180.0943202041507; raan: 260.9848087367962; v: 47.661864572695;} this was the last step Final date : 2004-01-01T23:40:30.000 Final state : keplerian parameters: {a: 2.4359529815906595E7; e: 0.7278336627402863; i: 6.9966966687030006; pa: 180.09772043784898; raan: 260.98320261084; v: 49.60140721108459;}
This third mode may be used when the user needs random access to the orbit state at any time between some initial and final dates.
As in the two tutorials above, let's first define some initial state with:
// Inertial frame Frame inertialFrame = FramesFactory.getEME2000(); // Initial date TimeScale utc = TimeScalesFactory.getUTC(); AbsoluteDate initialDate = new AbsoluteDate(2004, 01, 01, 23, 30, 00.000,utc); // Central attraction coefficient double mu = 3.986004415e+14; // Initial orbit double a = 24396159; // semi major axis in meters double e = 0.72831215; // eccentricity double i = Math.toRadians(7); // inclination double omega = Math.toRadians(180); // perigee argument double raan = Math.toRadians(261); // right ascention of ascending node double lM = 0; // mean anomaly Orbit initialOrbit = new KeplerianOrbit(a, e, i, omega, raan, lM, PositionAngle.MEAN, inertialFrame, initialDate, mu); // Initial state definition SpacecraftState initialState = new SpacecraftState(initialOrbit);
Here we use a simple NumericalPropagator, without perturbation, based on a classical fixed step Runge-Kutta integrator provided by the underlying commons-math library.
double stepSize = 10; FirstOrderIntegrator integrator = new ClassicalRungeKuttaIntegrator(stepSize); NumericalPropagator propagator = new NumericalPropagator(integrator);
The initial state is set for this propagator:
propagator.setInitialState(initialState);
Then, the propagator operating mode is simply set to ephemeris mode:
propagator.setEphemerisMode();
And the propagation is performed for a given duration.
SpacecraftState finalState = propagator.propagate(new AbsoluteDate(initialDate, 6000));
This finalState can be used for anything, to be printed, for example as shown below:
Numerical propagation : Final date : 2004-01-02T01:10:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 583.1250344407331;}
Throughout the propagation, intermediate states are stored within an ephemeris which can now be recovered with a single call:
BoundedPropagator ephemeris = propagator.getGeneratedEphemeris(); System.out.println(" Ephemeris defined from " + ephemeris.getMinDate() + " to " + ephemeris.getMaxDate());
The ephemeris is defined as a BoundedPropagator, which means that it is valid only between the propagation initial and final dates. The code above give the following result:
Ephemeris defined from 2004-01-01T23:30:00.000 to 2004-01-02T01:10:00.000
Between these dates, the ephemeris can be used as any propagator to propagate the orbital state towards any intermediate date with a single call:
SpacecraftState intermediateState = ephemeris.propagate(intermediateDate);
Here are results obtained with intermediate dates set to 3000 seconds after start date and to exactly the final date:
Ephemeris propagation : date : 2004-01-02T00:20:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 559.0092657655284;} date : 2004-01-02T01:10:00.000 equinoctial parameters: {a: 2.4396159E7; ex: 0.11393312156755062; ey: 0.719345418868777; hx: -0.009567941763699867; hy: -0.06040960680288257; lv: 583.1250344407331;}
The following shows the error message we get when we try to use a date outside of the ephemeris range (in this case, the intermediate date was set to 1000 seconds before ephemeris start:
out of range date for ephemerides: 2004-01-01T23:13:20.000
This tutorial aims to demonstrate the power and simplicity of the event-handling mechanism.
One needs to check the visibility between a satellite and a ground station during some time range.
We will use, and extend, the predefined ElevationDetector to perform the task.
First, let's set up an initial state for the satellite defined by a position and a velocity at one date in some inertial frame.
Vector3D position = new Vector3D(-6142438.668, 3492467.560, -25767.25680); Vector3D velocity = new Vector3D(505.8479685, 942.7809215, 7435.922231); PVCoordinates pvCoordinates = new PVCoordinates(position, velocity); AbsoluteDate initialDate = new AbsoluteDate(2004, 01, 01, 23, 30, 00.000, TimeScalesFactory.getUTC()); Frame inertialFrame = FramesFactory.getEME2000();
We also need to set the central attraction coefficient to define the initial orbit as a KeplerianOrbit.
double mu = 3.986004415e+14; Orbit initialOrbit = new KeplerianOrbit(pvCoordinates, inertialFrame, initialDate, mu);
More details on the orbit representation can be found in the orbits section of the library architecture documentation.
As a propagator, we consider a KeplerianPropagator to compute the simple keplerian motion. It could be more elaborate without modifying the general purpose of this tutorial.
Propagator kepler = new KeplerianPropagator(initialOrbit);
Then, let's define the ground station by its coordinates as a GeodeticPoint:
double longitude = Math.toRadians(45.); double latitude = Math.toRadians(25.); double altitude = 0.; GeodeticPoint station1 = new GeodeticPoint(latitude, longitude, altitude);
And let's associate to it a TopocentricFrame related to a BodyShape in some terrestrial frame.
double ae = 6378137.0; // equatorial radius in meter double f = 1.0 / 298.257223563; // flattening Frame ITRF2005 = FramesFactory.getITRF2005(); // terrestrial frame at an arbitrary date BodyShape earth = new OneAxisEllipsoid(ae, f, ITRF2005); TopocentricFrame sta1Frame = new TopocentricFrame(earth, station1, "station1");
More details on BodyShape and GeodeticPoint can be found in the bodies section of the library architecture documentation.
More details on TopocentricFrame can be found in the frames section of the library architecture documentation.
An EventDetector is defined as a VisibilityDetector which is derived from an ElevationDetector with the same specific parameters.
double maxcheck = 1.; double elevation = Math.toRadians(5.); EventDetector sta1Visi = new VisibilityDetector(maxcheck, elevation, sta1Frame);
This EventDetector is added to the propagator:
kepler.addEventDetector(sta1Visi);
Finally, the propagator is simply asked to perform until some final date, in slave mode by default.
It will propagate from the initial date to the first raising or for the fixed duration according to the behavior implemented in the VisibilityDetector class.
SpacecraftState finalState = kepler.propagate(new AbsoluteDate(initialDate, 1500.));
The main application code is very simple, all the work is done inside the propagator thanks to the VisibilityDetector class especially created for the purpose.
This class extends the ElevationDetector class, furnished by OREKIT, by overriding the eventOccurred method with the special ability to print the results of the visibility check, both the raising and the setting time, and to stop the propagation just after the setting detection.
The printed result is shown below. We can see that the propagation stopped just after detecting the raising:
Visibility on station1 begins at 2004-01-01T23:31:52.097 Visibility on station1 ends at 2004-01-01T23:42:48.850 Final state : 2004-01-01T23:42:48.850