@Test public void testSpin() throws OrekitException { AbsoluteDate date = new AbsoluteDate( new DateComponents(1970, 01, 01), new TimeComponents(3, 25, 45.6789), TimeScalesFactory.getUTC()); KeplerianOrbit orbit = new KeplerianOrbit( 7178000.0, 1.e-4, FastMath.toRadians(50.), FastMath.toRadians(10.), FastMath.toRadians(20.), FastMath.toRadians(30.), PositionAngle.MEAN, FramesFactory.getEME2000(), date, 3.986004415e14); final AttitudeProvider law = new LofOffsetPointing( earthSpheric, new LofOffset(orbit.getFrame(), LOFType.VVLH, RotationOrder.XYX, 0.1, 0.2, 0.3), Vector3D.PLUS_K); Propagator propagator = new KeplerianPropagator(orbit, law); double h = 0.01; SpacecraftState sMinus = propagator.propagate(date.shiftedBy(-h)); SpacecraftState s0 = propagator.propagate(date); SpacecraftState sPlus = propagator.propagate(date.shiftedBy(h)); // check spin is consistent with attitude evolution double errorAngleMinus = Rotation.distance( sMinus.shiftedBy(h).getAttitude().getRotation(), s0.getAttitude().getRotation()); double evolutionAngleMinus = Rotation.distance(sMinus.getAttitude().getRotation(), s0.getAttitude().getRotation()); Assert.assertEquals(0.0, errorAngleMinus, 1.0e-6 * evolutionAngleMinus); double errorAnglePlus = Rotation.distance( s0.getAttitude().getRotation(), sPlus.shiftedBy(-h).getAttitude().getRotation()); double evolutionAnglePlus = Rotation.distance(s0.getAttitude().getRotation(), sPlus.getAttitude().getRotation()); Assert.assertEquals(0.0, errorAnglePlus, 1.0e-6 * evolutionAnglePlus); Vector3D spin0 = s0.getAttitude().getSpin(); Vector3D reference = AngularCoordinates.estimateRate( sMinus.getAttitude().getRotation(), sPlus.getAttitude().getRotation(), 2 * h); Assert.assertTrue(spin0.getNorm() > 1.0e-3); Assert.assertEquals(0.0, spin0.subtract(reference).getNorm(), 1.0e-10); }
/** * 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()); }
/** {@inheritDoc} */ public SpacecraftState apply(final SpacecraftState state1) { if (state1.getDate().compareTo(referenceDate) <= 0 && !applyBefore) { // the orbit change has not occurred yet, don't change anything return state1; } return new SpacecraftState( updateOrbit(state1.getOrbit()), state1.getAttitude(), state1.getMass()); }
/** * Compute mean state from osculating state. * * <p>Compute in a DSST sense the mean state corresponding to the input osculating state. * * <p>The computing is done through a fixed-point iteration process. * * @param osculating initial osculating state * @return mean state * @throws OrekitException if the underlying computation of short periodic variation fails */ private Orbit computeMeanOrbit(final SpacecraftState osculating) throws OrekitException { // rough initialization of the mean parameters EquinoctialOrbit meanOrbit = new EquinoctialOrbit(osculating.getOrbit()); // threshold for each parameter final double epsilon = 1.0e-13; final double thresholdA = epsilon * (1 + FastMath.abs(meanOrbit.getA())); final double thresholdE = epsilon * (1 + meanOrbit.getE()); final double thresholdAngles = epsilon * FastMath.PI; int i = 0; while (i++ < 200) { final SpacecraftState meanState = new SpacecraftState(meanOrbit, osculating.getAttitude(), osculating.getMass()); // recompute the osculating parameters from the current mean parameters final EquinoctialOrbit rebuilt = (EquinoctialOrbit) computeOsculatingOrbit(meanState); // adapted parameters residuals final double deltaA = osculating.getA() - rebuilt.getA(); final double deltaEx = osculating.getEquinoctialEx() - rebuilt.getEquinoctialEx(); final double deltaEy = osculating.getEquinoctialEy() - rebuilt.getEquinoctialEy(); final double deltaHx = osculating.getHx() - rebuilt.getHx(); final double deltaHy = osculating.getHy() - rebuilt.getHy(); final double deltaLm = MathUtils.normalizeAngle(osculating.getLM() - rebuilt.getLM(), 0.0); // check convergence if ((FastMath.abs(deltaA) < thresholdA) && (FastMath.abs(deltaEx) < thresholdE) && (FastMath.abs(deltaEy) < thresholdE) && (FastMath.abs(deltaLm) < thresholdAngles)) { return meanOrbit; } // update mean parameters meanOrbit = new EquinoctialOrbit( meanOrbit.getA() + deltaA, meanOrbit.getEquinoctialEx() + deltaEx, meanOrbit.getEquinoctialEy() + deltaEy, meanOrbit.getHx() + deltaHx, meanOrbit.getHy() + deltaHy, meanOrbit.getLM() + deltaLm, PositionAngle.MEAN, meanOrbit.getFrame(), meanOrbit.getDate(), meanOrbit.getMu()); } throw new PropagationException(OrekitMessages.UNABLE_TO_COMPUTE_DSST_MEAN_PARAMETERS, i); }
/** {@inheritDoc} */ public FieldVector3D<DerivativeStructure> accelerationDerivatives( final SpacecraftState s, final String paramName) throws OrekitException { complainIfNotSupported(paramName); final AbsoluteDate date = s.getDate(); final Frame frame = s.getFrame(); final Vector3D position = s.getPVCoordinates().getPosition(); final Vector3D sunSatVector = position.subtract(sun.getPVCoordinates(date, frame).getPosition()); final double r2 = sunSatVector.getNormSq(); // compute flux final double rawP = kRef * getLightningRatio(position, frame, date) / r2; final Vector3D flux = new Vector3D(rawP / FastMath.sqrt(r2), sunSatVector); return spacecraft.radiationPressureAcceleration( date, frame, position, s.getAttitude().getRotation(), s.getMass(), flux, paramName); }
private SpacecraftState shiftState( SpacecraftState state, OrbitType orbitType, PositionAngle angleType, double delta, int column) { double[] array = stateToArray(state, orbitType, angleType, true); array[column] += delta; return arrayToState( array, orbitType, angleType, state.getFrame(), state.getDate(), state.getMu(), state.getAttitude()); }
/** {@inheritDoc} */ public void addContribution(final SpacecraftState s, final TimeDerivativesEquations adder) throws OrekitException { final AbsoluteDate date = s.getDate(); final Frame frame = s.getFrame(); final Vector3D position = s.getPVCoordinates().getPosition(); final Vector3D sunSatVector = position.subtract(sun.getPVCoordinates(date, frame).getPosition()); final double r2 = sunSatVector.getNormSq(); // compute flux final double rawP = kRef * getLightningRatio(position, frame, date) / r2; final Vector3D flux = new Vector3D(rawP / FastMath.sqrt(r2), sunSatVector); final Vector3D acceleration = spacecraft.radiationPressureAcceleration( date, frame, position, s.getAttitude().getRotation(), s.getMass(), flux); // provide the perturbing acceleration to the derivatives adder adder.addAcceleration(acceleration, s.getFrame()); }