Data initialization : Différence entre versions

De Wiki
Aller à : navigation, rechercher
(Aerodynamic)
(Aerodynamic)
Ligne 87 : Ligne 87 :
 
=== Aerodynamic ===
 
=== Aerodynamic ===
  
Then we could add an aerodynamic force model
+
Then we could add an aerodynamic force model. Since V11.3, it is no more necessary to use "Custom" classes.
  
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">

Version du 14 décembre 2018 à 08:43

PAGE UNDER MODIFICATION ...

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

Since V11.3, it is no more necessary to pass an Assembly object but a Vehicle one. Anyway, it is allways mandatory to pass a MassProvider object, issued from the Vehicle one. 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).

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 will use the createAssembly() method given by Vehicle class.

        final Assembly assembly = vehicle.createAssembly(GCRF);
        final MassProvider mm = new MassModel(assembly);

In the example below, we will then use the Vehicle 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 double sref = 5.0;
        Sphere sphere = new Sphere(sref);
        final RightParallelepiped solarPanels = new RightParallelepiped(10., 0., 0.);
        VehicleSurfaceModel vehicleRefSurface = new VehicleSurfaceModel(sphere, solarPanels);
 
        // Aerodynamic properties
        final double cd = 2.0;
        final double cl = 0.;
        final AerodynamicProperties aerodynamicProperties = new AerodynamicProperties(vehicleRefSurface, cd, cl);
 
        final Vehicle vehicle = new Vehicle(vehicleRefSurface, null, dryMassProperty, aerodynamicProperties, null, null, null);
 
        final Assembly assembly = vehicle.createAssembly(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

Since V11.3, to define, which forces will be applied along the trajectory, we use the PATRIUS ForceModelsData class (no more necessary to use the specific CustomForceModels class which does not exist anymore).

Potential

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

// Potential
final ForceModel potential = EarthGravitationalModelFactory.getDroziner(GravityFieldNames.GRGS, "grim4s4_gr", 8, 8, true);
 
final ForceModelsData forces = new ForceModelsData(potential, null, null, null, null, null, null, null, null, null, null, null, null,  null, null);

Aerodynamic

Then we could add an aerodynamic force model. Since V11.3, it is no more necessary to use "Custom" classes.

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 Atmosphere atmosphere = new US76(EARTH);
final DragForce dragForce = new DragForce(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.

This example shows how to define a single law (available since V11.1):

final AttitudeLaw attitudeLaw = new LofOffset(LOFType.TNW);

This other example uses a switching possibility:

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, null, seqAtt);