Data initialization : Différence entre versions

De Wiki
Aller à : navigation, rechercher
(Integration)
Ligne 276 : Ligne 276 :
 
final double step = 5.;
 
final double step = 5.;
 
final RK4data integrationData = new RK4data(propagationData, step);
 
final RK4data integrationData = new RK4data(propagationData, step);
<syntaxhighlight>
+
</syntaxhighlight>
  
 
… or with the <font color=#FF8C00>DOP</font> integrator …
 
… or with the <font color=#FF8C00>DOP</font> integrator …

Version du 7 août 2017 à 09:20

Orbit

To initialize an orbit, we simply have to build it using [PATRIUS] object. For example:

final TimeScale TUC = TimeScalesFactory.getUTC();
final AbsoluteDate date = new AbsoluteDate("2010-01-01T12:00:00.000", TUC);       
final double sma = Constants.WGS84_EARTH_EQUATORIAL_RADIUS + 250.e3;
final double ecc = 0.;
final double inc = FastMath.toRadians(51.6);
final double raan = FastMath.toRadians(0.);
final double pa  = FastMath.toRadians(0.);
final double ano = FastMath.toRadians(0.);
final Frame GCRF = FramesFactory.getGCRF();
final KeplerianOrbit iniOrbit =
  new KeplerianOrbit(sma, ecc, inc, raan, pa, ano, PositionAngle.MEAN, GCRF, date, MU);

Earth features

Data equivalent to the “Earth features” tab are distributed via two arguments:

1. A ExtendedOneAxisEllipsoid object which will define the shape of the planet
final ExtendedOneAxisEllipsoid EARTH =
   new ExtendedOneAxisEllipsoid(REQ, FLAT, ITRF, "EARTH");
2. A type of enumerates that will propose some pre-defined configurations as:
  • NOTHING (all options set to null)
  • ONLY_PREC_NUT (only precession and nutation)
  • FACTORY (equivalent to the most complete definition as in the GUI)
  • IGNORE (nothing is define internally by PSIMU which will take into account the user parametrization previously done)

Vehicle

In fact, we need to pass both an Assembly and a MassProvider. It could seem curious but it is due to the fact that, if we have maneuvers, it will be mandatory to initialize them with the same MassProvider (see example here). To get them, we could use the AssemblyBuilder given by [PATRIUS] or the CustomVehicle class coming from [GENOPUS] waiting for the next Vehicle class that will appear from [PATRIUS] V3.4. In the example below, we will use the CustomVehicle class initializing mass and aerodynamic properties (here no engines and no tanks):

// Dry mass
final double dryMass = 1000.;
final MassProperty dryMassProperty = new MassProperty(dryMass);
// Shape
final CustomSphere sphere = new CustomSphere(5.0);
final CustomVehicleSurfaceModel vehicleRefSurface =
   new CustomVehicleSurfaceModel(sphere);
// Aerodynamic properties
final double cd = 2.0;
final double cl = 0.;
final CustomAerodynamicProperties aerodynamicProperties =
   new CustomAerodynamicProperties(vehicleRefSurface, cd, cl);
 
final CustomVehicle vehicle =
   new CustomVehicle(dryMassProperty, aerodynamicProperties, null, null, null);
final Assembly assembly = vehicle.getAssembly(GCRF);
final MassProvider mm = new MassModel(assembly);

Note : be careful that the frame (GCRF in the previous example), mandatory in the construction of the vehicle must be exactly the same that the one used for the propagation (limitation due to PATRIUS).

Forces

To define, which forces will be applied along the trajectory, we use the CustomForceModels class (waiting for the equivalent [PATRIUS] class).

Potential

In the following example, we will initialize the potential model (mandatory).

// Potential
final ForceModel potential =  createPot("grim4s4_gr", 8, 8);
 
final CustomForceModels forces = new CustomForceModels(potential, null, null, null, null, null, null, null, null, null, null);

Note that the createPot() static method is the following one (waiting for such utility from V3.4.1 of [PATRIUS]):

public static ForceModel createPot ( String namePot, int nzo, int nte) throws IOException, ParseException, OrekitException {
 
// Adding « reader » for gravity models
GravityFieldFactory.addPotentialCoefficientsReader(
    new GRGSFormatReader(namePot, true));
 
// Getting gravity model from « namePot » model
final PotentialCoefficientsProvider provider =
    GravityFieldFactory.getPotentialProvider();
 
// Getting zonal and tesseral terms
final int n = nzo; // max zonal degree
final int m = nte; // max tesseral order
 
int ntmp = 1;
if ( n != 0 ) ntmp = nzo;
 
final double[][] C = provider.getC(ntmp, m, false);
final double[][] S = provider.getS(ntmp, m, false);
 
// Force model creation
ForceModel pot = new DrozinerAttractionModel(FramesFactory.getITRF(),
                    provider.getAe(), provider.getMu(), C, S);
 
return pot;
 
}

Aerodynamic

Then we could add an aerodynamic force model

final double REQ  = Constants.WGS84_EARTH_EQUATORIAL_RADIUS;
final double FLAT = Constants.WGS84_EARTH_FLATTENING;
final Frame ITRF = FramesFactory.getITRF();
final ExtendedOneAxisEllipsoid EARTH =
   new ExtendedOneAxisEllipsoid(REQ, FLAT, ITRF, "EARTH");
 
final CustomAtmosphere atmosphere = new CustomUS76(EARTH);
final CustomDragForce dragForce = new CustomDragForce(1., atmosphere, assembly);
 
forces.setDragForce(dragForce);

Solar adiative pressure

Here are explained how to use both radiative pressure and rediffused radiative pressure force models:

final CelestialBody sunBody = new MeeusSun();
final double dRef = 1.4959787E11;
final double pRef = 4.5605E-6;
final ExtendedOneAxisEllipsoid EARTH =
   new ExtendedOneAxisEllipsoid(REQ, FLAT, ITRF, "EARTH");
 
final CustomPatriusSolarRadiationPressure radPres =
   new CustomPatriusSolarRadiationPressure(dRef, pRef, sunBody, EARTH, assembly, 1.);
 
forces.setSolarRadiationPressure(radPres);
 
// By default values used when GUI mode ...
final int inCorona = 1;
final int inMeridian = 10;
final IEmissivityModel inEmissivityModel = new KnockeRiesModel();
// Value accessible via GUI mode
final boolean inAlbedo = false;
final boolean inIr = false;
final double coefAlbedo = 1.;
final double coefIr = 1.;
 
final CustomRediffusedRadiationPressure rediffusedRadiationPressure =
   new CustomRediffusedRadiationPressure(sunBody, GCRF, inCorona, inMeridian,
                                         inEmissivityModel, inAlbedo, inIr,
                                         coefAlbedo, coefK0Ir, assembly);
 
forces.setRediffusedSolarRadiationPressure(rediffusedRadiationPressure);

Specific forces

It is also possible to add specific forces via the addForceModel() method as below:

final Psimu test = new Psimu(...);
test.addForceModel(myForce);

Maneuvers

If the user wants to add some maneuvers, it will have to do it using the [GENOPUS] Custom ManeuverSequence class. Indeed, this class is derivated from the PATRIUS ManeuverSequence but allows taking into account Engines and Tanks notion. From [PATRIUS] V3.4, it will be possible to directly use [PATRIUS] class.

Propulsive properties

First, the user will have to define propulsive properties with engine(s) and tank(s):

// Propulsive properties
final CustomEngine engine = new CustomEngine("ENGINE", 320., 400.);
final ArrayList<CustomEngine> listOfEngines = new ArrayList<CustomEngine>();
listOfEngines.add(engine);
final CustomFuelTank tank = new CustomFuelTank("TANK", 100.);
final ArrayList<CustomFuelTank> listOfTanks = new ArrayList<CustomFuelTank>();
listOfTanks.add(tank);
 
final CustomVehicle vehicle =
   new CustomVehicle(dryMassProperty, null, null, listOfEngines, listOfTanks);

Sequence

Then, a maneuver sequence will be created thanks to the CustomManeuverSequence (the [PATRIUS] ManeuverSequence is not directly used as it does not still manage engines and tanks; it will be available with V3.4.1).

Impulsive maneuver

Here we have an example of a 10m/s impulse maneuver in TNW:

final double aol = FastMath.toRadians(180.);
final CustomAOLDetector eventImp =
   new CustomAOLDetector(aol, PositionAngle.TRUE, GCRF, 1, maxCheck, threshold,
                         Action.STOP, true);
final GenericCodingEventDetector codingEvent =
   eventImp.getGenericCodingEventDetector("imp man", "imp man");
 
final Vector3D deltaV = new Vector3D(10., 0., 0.);
 
final CustomImpulseManeuver imp =
   new CustomImpulseManeuver("Impulse maneuver", engine, tank, LOFType.TNW, eventImp, deltaV, mm, codingEvent);

Note: it is mandatory to define the maneuver with a Coding Event detector to allow to PSIMU to manage events.

Note: it is also mandatory to configure the event with a STOP action (needed by [PATRIUS]) as the Coding event must have a CONTINUE action (automatically done if using the getGenericCodingEventDetector () method).

At last, the user will create the maneuver sequence to pass to PSIMU:

final ArrayList<CustomManeuverInterface> listOfMan =
   new ArrayList<CustomManeuverInterface>();
listOfMan.add(imp);
final CustomManeuverSequence manSeq = new CustomManeuverSequence(listOfMan, 0., 0.);

Constant thrust maneuver

The next source code shows how to define a constant thrust maneuver …

final double start = iniOrbit.getKeplerianPeriod();
final AbsoluteDate startDate = date.shiftedBy(start);
final CustomDateDetector startEvent =
   new CustomDateDetector(startDate, maxCheck, threshold, Action.STOP);
final GenericCodingEventDetector startEventCoding =
   startEvent.getGenericCodingEventDetector("start", "start");
final double thrustDuration = 1000.;
 
final AbsoluteDate endDate = startDate.shiftedBy(thrustDuration);
final CustomDateDetector stopEvent =
   new CustomDateDetector(endDate, maxCheck, threshold, Action.STOP);
final GenericCodingEventDetector stopEventCoding =
   stopEvent.getGenericCodingEventDetector("stop", "stop");
 
final Vector3D direction = new Vector3D(-1., 0., 0.);
final CustomConstantManeuver cont =
   new CustomConstantManeuver("Continuous maneuver", engine, tank, LOFType.TNW,
                              startEvent, startEventCoding, stopEvent, stopEventCoding,
                              direction, mm);

Attitude

It is mandatory to get at least one attitude law. With the V11.0, it is not possible to have only one law and it is mandatory to use the “switch” possibility by using the [PATRIUS] AttitudesSequence class.

final AttitudeLaw law = new LofOffset(LOFType.TNW, RotationOrder.ZYX, 0., 0., 0.);
final double maxCheck = AbstractDetector.DEFAULT_MAXCHECK;
final double threshold = AbstractDetector.DEFAULT_THRESHOLD;
final EventDetector event =
   new DateDetector(date, maxCheck, threshold, Action.RESET_STATE);
final AttitudesSequence seqAtt = new AttitudesSequence();
seqAtt.addSwitchingCondition(law, event, true, false, law);

Note : be very careful not to use by default constructors for event detectors as they introduce a STOP event, so your propagation will stop anyway !

Integration

Then integration data have to be defined. Here an example with RK4 integrator …

final double duration = 86400.;
final double hStop = 120.e+3;
final PsimuPropagationData propagationData =
   new PsimuPropagationData(duration, GCRF, hStop);
final double step = 5.;
final RK4data integrationData = new RK4data(propagationData, step);

… or with the DOP integrator …

final double minStep = 0.1;
final double maxStep = 30.;
final double[] vecAbsoluteTolerance =
   { 1.0E-5, 1.0E-5, 1.0E-5, 1.0E-8, 1.0E-8, 1.0E-8 };
final double[] vecRelativeTolerance =
   { 1.0E-8, 1.0E-8, 1.0E-8, 1.0E-8, 1.0E-8, 1.0E-8 };
final double absMassTolerance = 1.0E-3;
final double relMassTolerance = 1.0E-2;
final double positionError = 0.;
final DopData intData = new DopData(propagationData, minStep, maxStep, vecAbsoluteTolerance, vecRelativeTolerance, absMassTolerance, relMassTolerance);

PSIMU object

As we have all mandatory data to initialize PSIMU, we can build such an object (note that in this example there is a “null” argument for the sequence of maneuvers.

final Psimu test =
   new Psimu(iniOrbit, EARTH, UserFramesConfsEnum.IGNORE, integrationData, assembly, mm, forces, manSeq, seqAtt);