/** {@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(); }
/** * 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()); }
/** {@inheritDoc} */ @Override public void mapStateToArray(final SpacecraftState state, final double[] y) throws OrekitException { final Orbit meanOrbit; if (!initialIsOsculating) { // the state is considered to be already a mean state meanOrbit = state.getOrbit(); } else { // the state is considered to be an osculating state meanOrbit = computeMeanState(state, forceModels).getOrbit(); } OrbitType.EQUINOCTIAL.mapOrbitToArray(meanOrbit, PositionAngle.MEAN, y); y[6] = state.getMass(); }
/** * Compute the differential effect of J2 on an orbit. * * @param orbit1 original orbit at t₁, without differential J2 * @return orbit at t₁, always taking the effect into account */ private Orbit updateOrbit(final Orbit orbit1) { // convert current orbital state to equinoctial elements final EquinoctialOrbit original = (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(orbit1); // compute differential effect final AbsoluteDate date = original.getDate(); final double dt = date.durationFrom(referenceDate); final double dPaRaan = (dPaDot + dRaanDot) * dt; final double cPaRaan = FastMath.cos(dPaRaan); final double sPaRaan = FastMath.sin(dPaRaan); final double dRaan = dRaanDot * dt; final double cRaan = FastMath.cos(dRaan); final double sRaan = FastMath.sin(dRaan); final double ex = original.getEquinoctialEx() * cPaRaan - original.getEquinoctialEy() * sPaRaan; final double ey = original.getEquinoctialEx() * sPaRaan + original.getEquinoctialEy() * cPaRaan; final double hx = original.getHx() * cRaan - original.getHy() * sRaan; final double hy = original.getHx() * sRaan + original.getHy() * cRaan; final double lambda = original.getLv() + dPaRaan; // build updated orbit final EquinoctialOrbit updated = new EquinoctialOrbit( original.getA(), ex, ey, hx, hy, lambda, PositionAngle.TRUE, original.getFrame(), date, original.getMu()); // convert to required type return orbit1.getType().convertType(updated); }
/** {@inheritDoc} */ @Override public double[] getShortPeriodicVariations(final AbsoluteDate date, final double[] meanElements) throws OrekitException { // Initialise the short periodic variations final double[] shortPeriodicVariation = new double[] {0., 0., 0., 0., 0., 0.}; // Compute only if there is at least one non-resonant tesseral or // only the m-daily tesseral should be taken into account if (!nonResOrders.isEmpty() || mDailiesOnly) { // Build an Orbit object from the mean elements final Orbit meanOrbit = OrbitType.EQUINOCTIAL.mapArrayToOrbit( meanElements, PositionAngle.MEAN, date, provider.getMu(), this.frame); // Build an auxiliary object final AuxiliaryElements aux = new AuxiliaryElements(meanOrbit, I); // Central body rotation angle from equation 2.7.1-(3)(4). final Transform t = bodyFrame.getTransformTo(aux.getFrame(), aux.getDate()); final Vector3D xB = t.transformVector(Vector3D.PLUS_I); final Vector3D yB = t.transformVector(Vector3D.PLUS_J); final double currentTheta = FastMath.atan2( -f.dotProduct(yB) + I * g.dotProduct(xB), f.dotProduct(xB) + I * g.dotProduct(yB)); // Add the m-daily contribution for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) { // Phase angle final double jlMmt = -m * currentTheta; final double sinPhi = FastMath.sin(jlMmt); final double cosPhi = FastMath.cos(jlMmt); // compute contribution for each element for (int i = 0; i < 6; i++) { shortPeriodicVariation[i] += tesseralSPCoefs.getCijm(i, 0, m, date) * cosPhi + tesseralSPCoefs.getSijm(i, 0, m, date) * sinPhi; } } // loop through all non-resonant (j,m) pairs for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) { final int m = entry.getKey(); final List<Integer> listJ = entry.getValue(); for (int j : listJ) { // Phase angle final double jlMmt = j * meanElements[5] - m * currentTheta; final double sinPhi = FastMath.sin(jlMmt); final double cosPhi = FastMath.cos(jlMmt); // compute contribution for each element for (int i = 0; i < 6; i++) { shortPeriodicVariation[i] += tesseralSPCoefs.getCijm(i, j, m, date) * cosPhi + tesseralSPCoefs.getSijm(i, j, m, date) * sinPhi; } } } } return shortPeriodicVariation; }