/** {@inheritDoc} */ @Override public SpacecraftState mapArrayToState(final double t, final double[] y, final boolean meanOnly) throws OrekitException { final AbsoluteDate date = mapDoubleToDate(t); // add short periodic variations to mean elements to get osculating elements // (the loop may not be performed if there are no force models and in the // case we want to remain in mean parameters only) final double[] elements = y.clone(); if (!meanOnly) { for (final DSSTForceModel forceModel : forceModels) { final double[] shortPeriodic = forceModel.getShortPeriodicVariations(date, y); for (int i = 0; i < shortPeriodic.length; i++) { elements[i] += shortPeriodic[i]; } } } final double mass = elements[6]; if (mass <= 0.0) { throw new PropagationException(OrekitMessages.SPACECRAFT_MASS_BECOMES_NEGATIVE, mass); } final Orbit orbit = OrbitType.EQUINOCTIAL.mapArrayToOrbit( elements, PositionAngle.MEAN, date, getMu(), getFrame()); final Attitude attitude = getAttitudeProvider().getAttitude(orbit, date, getFrame()); return new SpacecraftState(orbit, attitude, mass); }
/** {@inheritDoc} */ @Override public double[] computeDerivatives(final SpacecraftState state) throws OrekitException { // compute common auxiliary elements final AuxiliaryElements aux = new AuxiliaryElements(state.getOrbit(), I); // initialize all perturbing forces for (final DSSTForceModel force : mapper.getForceModels()) { force.initializeStep(aux); } Arrays.fill(yDot, 0.0); // compute the contributions of all perturbing forces for (final DSSTForceModel forceModel : mapper.getForceModels()) { final double[] daidt = forceModel.getMeanElementRate(state); for (int i = 0; i < daidt.length; i++) { yDot[i] += daidt[i]; } } // finalize derivatives by adding the Kepler contribution final EquinoctialOrbit orbit = (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(state.getOrbit()); orbit.addKeplerContribution(PositionAngle.MEAN, getMu(), yDot); return yDot.clone(); }
/** * Method called just before integration. * * <p>The default implementation does nothing, it may be specialized in subclasses. * * @param initialState initial state * @param tEnd target date at which state should be propagated * @exception OrekitException if hook cannot be run */ @Override protected void beforeIntegration(final SpacecraftState initialState, final AbsoluteDate tEnd) throws OrekitException { // compute common auxiliary elements final AuxiliaryElements aux = new AuxiliaryElements(initialState.getOrbit(), I); // check if only mean elements must be used final boolean meanOnly = isMeanOrbit(); // initialize all perturbing forces for (final DSSTForceModel force : mapper.getForceModels()) { force.initialize(aux, meanOnly); } // if required, insert the special short periodics step handler if (!meanOnly) { final InterpolationGrid grid = new VariableStepInterpolationGrid(INTERPOLATION_POINTS_PER_STEP); final ShortPeriodicsHandler spHandler = new ShortPeriodicsHandler(grid); final Collection<StepHandler> stepHandlers = new ArrayList<StepHandler>(); stepHandlers.add(spHandler); final AbstractIntegrator integrator = getIntegrator(); final Collection<StepHandler> existing = integrator.getStepHandlers(); stepHandlers.addAll(existing); integrator.clearStepHandlers(); // add back the existing handlers after the short periodics one for (final StepHandler sp : stepHandlers) { integrator.addStepHandler(sp); } } }
/** * Conversion from osculating to mean, orbit. * * <p>Compute osculating state <b>in a DSST sense</b>, corresponding to the mean SpacecraftState * in input, and according to the Force models taken into account. * * <p>Since the osculating state is obtained with the computation of short-periodic variation of * each force model, the resulting output will depend on the force models parametrized in input. * * <p>The computing is done through a fixed-point iteration process. * * @param osculating Osculating state to convert * @param forces Forces to take into account * @return mean state in a DSST sense * @throws OrekitException if computation of short periodics fails or iteration algorithm does not * converge */ public static SpacecraftState computeMeanState( final SpacecraftState osculating, final Collection<DSSTForceModel> forces) throws OrekitException { // Creation of a DSSTPropagator instance final AbstractIntegrator integrator = new ClassicalRungeKuttaIntegrator(43200.); final DSSTPropagator dsst = new DSSTPropagator(integrator, false); // Create the auxiliary object final AuxiliaryElements aux = new AuxiliaryElements(osculating.getOrbit(), I); // Set the force models for (final DSSTForceModel force : forces) { force.initialize(aux, false); dsst.addForceModel(force); } dsst.setInitialState(osculating, true); final Orbit meanOrbit = dsst.mapper.computeMeanOrbit(osculating); return new SpacecraftState( meanOrbit, osculating.getAttitude(), osculating.getMass(), osculating.getAdditionalStates()); }
/** * Launch the computation of short periodics coefficients. * * @param state input state * @throws OrekitException if the computation of a short periodic coefficient fails * @see {@link DSSTForceModel#computeShortPeriodicsCoefficients(AuxiliaryElements)} */ private void computeShortPeriodicsCoefficients(final SpacecraftState state) throws OrekitException { final AuxiliaryElements aux = new AuxiliaryElements(state.getOrbit(), I); for (final DSSTForceModel forceModel : forceModels) { forceModel.initializeStep(aux); forceModel.computeShortPeriodicsCoefficients(state); } }
/** {@inheritDoc} */ @Override public void setAttitudeProvider(final AttitudeProvider attitudeProvider) { super.setAttitudeProvider(attitudeProvider); // Register the attitude provider for each force model for (final DSSTForceModel force : mapper.getForceModels()) { force.registerAttitudeProvider(attitudeProvider); } }
/** * Simple constructor. * * @param integrator numerical integrator to use for propagation. */ Main(final AbstractIntegrator integrator) { yDot = new double[7]; for (final DSSTForceModel forceModel : mapper.getForceModels()) { final EventDetector[] modelDetectors = forceModel.getEventsDetectors(); if (modelDetectors != null) { for (final EventDetector detector : modelDetectors) { setUpEventDetector(integrator, detector); } } } }
/** * Compute osculating state from mean state. * * <p>Compute and add the short periodic variation to the mean {@link SpacecraftState}. * * @param meanState initial mean state * @return osculating state * @throws OrekitException if the computation of the short-periodic variation fails */ private Orbit computeOsculatingOrbit(final SpacecraftState meanState) throws OrekitException { resetShortPeriodicsCoefficients(); computeShortPeriodicsCoefficients(meanState); final double[] mean = new double[6]; OrbitType.EQUINOCTIAL.mapOrbitToArray(meanState.getOrbit(), PositionAngle.MEAN, mean); final double[] y = mean.clone(); for (final DSSTForceModel forceModel : this.forceModels) { final double[] shortPeriodic = forceModel.getShortPeriodicVariations(meanState.getDate(), mean); for (int i = 0; i < shortPeriodic.length; i++) { y[i] += shortPeriodic[i]; } } return OrbitType.EQUINOCTIAL.mapArrayToOrbit( y, PositionAngle.MEAN, meanState.getDate(), meanState.getMu(), meanState.getFrame()); }
/** * Replace the instance with a data transfer object for serialization. * * @return data transfer object that will be serialized * @exception NotSerializableException if one of the force models cannot be serialized */ private Object writeReplace() throws NotSerializableException { // Check the force models can be serialized final DSSTForceModel[] serializableorceModels = new DSSTForceModel[forceModels.size()]; for (int i = 0; i < serializableorceModels.length; ++i) { final DSSTForceModel forceModel = forceModels.get(i); if (forceModel instanceof Serializable) { serializableorceModels[i] = forceModel; } else { throw new NotSerializableException(forceModel.getClass().getName()); } } return new DataTransferObject( getReferenceDate(), getMu(), getAttitudeProvider(), getFrame(), initialIsOsculating, serializableorceModels, satelliteRevolution); }
/** * Reset the short periodics coefficient for each {@link DSSTForceModel}. * * @see DSSTForceModel#resetShortPeriodicsCoefficients() */ private void resetShortPeriodicsCoefficients() { for (final DSSTForceModel forceModel : forceModels) { forceModel.resetShortPeriodicsCoefficients(); } }
/** * Add a force model to the global perturbation model. * * <p>If this method is not called at all, the integrated orbit will follow a keplerian evolution * only. * * @param force perturbing {@link DSSTForceModel force} to add * @see #removeForceModels() */ public void addForceModel(final DSSTForceModel force) { mapper.addForceModel(force); force.registerAttitudeProvider(getAttitudeProvider()); }