Search in sources :

Example 71 with AbsoluteDate

use of org.orekit.time.AbsoluteDate in project Orekit by CS-SI.

the class PVTest method testPVWithCovarianceMatrix.

/**
 * Test the PV constructor with one 6x6 covariance matrix as input.
 * @throws OrekitException
 */
@Test
public void testPVWithCovarianceMatrix() throws OrekitException {
    // Context
    Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
    // Dummy P, V, T
    final Vector3D position = context.initialOrbit.getPVCoordinates().getPosition();
    final Vector3D velocity = context.initialOrbit.getPVCoordinates().getVelocity();
    final AbsoluteDate date = context.initialOrbit.getDate();
    // Initialize standard deviations, weight and corr coeff
    final double[] sigmaPV = { 10., 20., 30., 0.1, 0.2, 0.3 };
    final double baseWeight = 0.5;
    final double[][] corrCoefRef = new double[6][6];
    for (int i = 0; i < 6; i++) {
        for (int j = 0; j < 6; j++) {
            if (i == j) {
                corrCoefRef[i][i] = 1.;
            } else {
                corrCoefRef[i][j] = i + j + 1;
            }
        }
    }
    // Reference covariance matrix
    final double[][] Pref = new double[6][6];
    for (int i = 0; i < 6; i++) {
        for (int j = 0; j < 6; j++) {
            Pref[i][j] = corrCoefRef[i][j] * sigmaPV[i] * sigmaPV[j];
        }
    }
    // Reference propagator numbers
    final int[] propNumRef = { 0, 2 };
    // Create PV measurements
    final PV[] pvs = new PV[2];
    pvs[0] = new PV(date, position, velocity, Pref, baseWeight);
    pvs[1] = new PV(date, position, velocity, Pref, baseWeight, propNumRef[1]);
    // Tolerance
    // tolerance
    final double eps = 1.8e-15;
    // Check data
    for (int k = 0; k < pvs.length; k++) {
        final PV pv = pvs[k];
        // Propagator numbers
        assertEquals(propNumRef[k], pv.getPropagatorsIndices().get(0), eps);
        // Weights
        for (int i = 0; i < 6; i++) {
            assertEquals(baseWeight, pv.getBaseWeight()[i], eps);
        }
        // Sigmas
        for (int i = 0; i < 6; i++) {
            assertEquals(sigmaPV[i], pv.getTheoreticalStandardDeviation()[i], eps);
        }
        // Covariances
        final double[][] P = pv.getCovarianceMatrix();
        // Substract with ref and get the norm
        final double normP = MatrixUtils.createRealMatrix(P).subtract(MatrixUtils.createRealMatrix(Pref)).getNorm();
        assertEquals(0., normP, eps);
        // Correlation coef
        final double[][] corrCoef = pv.getCorrelationCoefficientsMatrix();
        // Substract with ref and get the norm
        final double normCorrCoef = MatrixUtils.createRealMatrix(corrCoef).subtract(MatrixUtils.createRealMatrix(corrCoefRef)).getNorm();
        assertEquals(0., normCorrCoef, eps);
    }
}
Also used : Context(org.orekit.estimation.Context) Vector3D(org.hipparchus.geometry.euclidean.threed.Vector3D) AbsoluteDate(org.orekit.time.AbsoluteDate) Test(org.junit.Test)

Example 72 with AbsoluteDate

use of org.orekit.time.AbsoluteDate in project Orekit by CS-SI.

the class PVTest method testExceptions.

/**
 * Test exceptions raised if the covariance matrix does not have the proper size.
 */
@Test
public void testExceptions() throws OrekitException {
    // Context
    Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
    // Dummy P, V, T
    final Vector3D position = context.initialOrbit.getPVCoordinates().getPosition();
    final Vector3D velocity = context.initialOrbit.getPVCoordinates().getVelocity();
    final AbsoluteDate date = context.initialOrbit.getDate();
    final double weight = 1.;
    // Build with two 3-sized vectors
    try {
        new PV(date, position, velocity, new double[] { 0., 0., 0. }, new double[] { 1. }, weight);
        Assert.fail("An OrekitException should have been thrown");
    } catch (OrekitException e) {
    // An exception should indeed be raised here
    }
    // Build with one 6-sized vector
    try {
        new PV(date, position, velocity, new double[] { 0., 0., 0. }, weight);
        Assert.fail("An OrekitException should have been thrown");
    } catch (OrekitException e) {
    // An exception should indeed be raised here
    }
    // Build with two 3x3 matrices
    try {
        new PV(date, position, velocity, new double[][] { { 0., 0. }, { 0., 0. } }, new double[][] { { 0., 0. }, { 0., 0. } }, weight);
        Assert.fail("An OrekitException should have been thrown");
    } catch (OrekitException e) {
    // An exception should indeed be raised here
    }
    // Build with one 6x6 matrix
    try {
        new PV(date, position, velocity, new double[][] { { 0., 0. }, { 0., 0. } }, weight);
        Assert.fail("An OrekitException should have been thrown");
    } catch (OrekitException e) {
    // An exception should indeed be raised here
    }
}
Also used : Context(org.orekit.estimation.Context) Vector3D(org.hipparchus.geometry.euclidean.threed.Vector3D) OrekitException(org.orekit.errors.OrekitException) AbsoluteDate(org.orekit.time.AbsoluteDate) Test(org.junit.Test)

Example 73 with AbsoluteDate

use of org.orekit.time.AbsoluteDate in project Orekit by CS-SI.

the class RangeAnalytic method theoreticalEvaluationAnalytic.

/**
 * Analytical version of the theoreticalEvaluation function in Range class
 * The derivative structures are not used, an analytical computation is used instead.
 * @param iteration current LS estimator iteration
 * @param evaluation current LS estimator evaluation
 * @param state spacecraft state. At measurement date on first iteration then close to emission date on further iterations
 * @param interpolator Orekit step interpolator
 * @return
 * @throws OrekitException
 */
protected EstimatedMeasurement<Range> theoreticalEvaluationAnalytic(final int iteration, final int evaluation, final SpacecraftState state) throws OrekitException {
    // Station attribute from parent Range class
    final GroundStation groundStation = this.getStation();
    // Station position at signal arrival
    final AbsoluteDate downlinkDate = getDate();
    final Transform topoToInertDownlink = groundStation.getOffsetToInertial(state.getFrame(), downlinkDate);
    final TimeStampedPVCoordinates stationDownlink = topoToInertDownlink.transformPVCoordinates(new TimeStampedPVCoordinates(downlinkDate, PVCoordinates.ZERO));
    // Take propagation time into account
    // (if state has already been set up to pre-compensate propagation delay,
    // we will have offset == downlinkDelay and transitState will be
    // the same as state)
    // Downlink time of flight
    final double tauD = signalTimeOfFlight(state.getPVCoordinates(), stationDownlink.getPosition(), downlinkDate);
    final double delta = downlinkDate.durationFrom(state.getDate());
    final double dt = delta - tauD;
    // Transit state position
    final SpacecraftState transitState = state.shiftedBy(dt);
    final AbsoluteDate transitDate = transitState.getDate();
    final Vector3D transitP = transitState.getPVCoordinates().getPosition();
    // Station position at transit state date
    final Transform topoToInertAtTransitDate = groundStation.getOffsetToInertial(state.getFrame(), transitDate);
    final TimeStampedPVCoordinates stationAtTransitDate = topoToInertAtTransitDate.transformPVCoordinates(new TimeStampedPVCoordinates(transitDate, PVCoordinates.ZERO));
    // Uplink time of flight
    final double tauU = signalTimeOfFlight(stationAtTransitDate, transitP, transitDate);
    final double tau = tauD + tauU;
    // Real date and position of station at signal departure
    final AbsoluteDate uplinkDate = downlinkDate.shiftedBy(-tau);
    final TimeStampedPVCoordinates stationUplink = topoToInertDownlink.shiftedBy(-tau).transformPVCoordinates(new TimeStampedPVCoordinates(uplinkDate, PVCoordinates.ZERO));
    // Prepare the evaluation
    final EstimatedMeasurement<Range> estimated = new EstimatedMeasurement<Range>(this, iteration, evaluation, new SpacecraftState[] { transitState }, new TimeStampedPVCoordinates[] { stationUplink, transitState.getPVCoordinates(), stationDownlink });
    // Set range value
    final double cOver2 = 0.5 * Constants.SPEED_OF_LIGHT;
    estimated.setEstimatedValue(tau * cOver2);
    // Partial derivatives with respect to state
    // The formulas below take into account the fact the measurement is at fixed reception date.
    // When spacecraft position is changed, the downlink delay is changed, and in order
    // to still have the measurement arrive at exactly the same date on ground, we must
    // take the spacecraft-station relative velocity into account.
    final Vector3D v = state.getPVCoordinates().getVelocity();
    final Vector3D qv = stationDownlink.getVelocity();
    final Vector3D downInert = stationDownlink.getPosition().subtract(transitP);
    final double dDown = Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT * tauD - Vector3D.dotProduct(downInert, v);
    final Vector3D upInert = transitP.subtract(stationUplink.getPosition());
    // test
    // final double   dUp       = Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT * tauU -
    // Vector3D.dotProduct(upInert, qv);
    // test
    final double dUp = Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT * tauU - Vector3D.dotProduct(upInert, stationUplink.getVelocity());
    // derivatives of the downlink time of flight
    final double dTauDdPx = -downInert.getX() / dDown;
    final double dTauDdPy = -downInert.getY() / dDown;
    final double dTauDdPz = -downInert.getZ() / dDown;
    // Derivatives of the uplink time of flight
    final double dTauUdPx = 1. / dUp * upInert.dotProduct(Vector3D.PLUS_I.add((qv.subtract(v)).scalarMultiply(dTauDdPx)));
    final double dTauUdPy = 1. / dUp * upInert.dotProduct(Vector3D.PLUS_J.add((qv.subtract(v)).scalarMultiply(dTauDdPy)));
    final double dTauUdPz = 1. / dUp * upInert.dotProduct(Vector3D.PLUS_K.add((qv.subtract(v)).scalarMultiply(dTauDdPz)));
    // derivatives of the range measurement
    final double dRdPx = (dTauDdPx + dTauUdPx) * cOver2;
    final double dRdPy = (dTauDdPy + dTauUdPy) * cOver2;
    final double dRdPz = (dTauDdPz + dTauUdPz) * cOver2;
    estimated.setStateDerivatives(0, new double[] { dRdPx, dRdPy, dRdPz, dRdPx * dt, dRdPy * dt, dRdPz * dt });
    if (groundStation.getEastOffsetDriver().isSelected() || groundStation.getNorthOffsetDriver().isSelected() || groundStation.getZenithOffsetDriver().isSelected()) {
        // Downlink tme of flight derivatives / station position in topocentric frame
        final AngularCoordinates ac = topoToInertDownlink.getAngular().revert();
        // final Rotation rotTopoToInert = ac.getRotation();
        final Vector3D omega = ac.getRotationRate();
        // Inertial frame
        final double dTauDdQIx = downInert.getX() / dDown;
        final double dTauDdQIy = downInert.getY() / dDown;
        final double dTauDdQIz = downInert.getZ() / dDown;
        // Uplink tme of flight derivatives / station position in topocentric frame
        // Inertial frame
        final double dTauUdQIx = 1 / dUp * upInert.dotProduct(Vector3D.MINUS_I.add((qv.subtract(v)).scalarMultiply(dTauDdQIx)).subtract(Vector3D.PLUS_I.crossProduct(omega).scalarMultiply(tau)));
        final double dTauUdQIy = 1 / dUp * upInert.dotProduct(Vector3D.MINUS_J.add((qv.subtract(v)).scalarMultiply(dTauDdQIy)).subtract(Vector3D.PLUS_J.crossProduct(omega).scalarMultiply(tau)));
        final double dTauUdQIz = 1 / dUp * upInert.dotProduct(Vector3D.MINUS_K.add((qv.subtract(v)).scalarMultiply(dTauDdQIz)).subtract(Vector3D.PLUS_K.crossProduct(omega).scalarMultiply(tau)));
        // Range partial derivatives
        // with respect to station position in inertial frame
        final Vector3D dRdQI = new Vector3D((dTauDdQIx + dTauUdQIx) * cOver2, (dTauDdQIy + dTauUdQIy) * cOver2, (dTauDdQIz + dTauUdQIz) * cOver2);
        // convert to topocentric frame, as the station position
        // offset parameter is expressed in this frame
        final Vector3D dRdQT = ac.getRotation().applyTo(dRdQI);
        if (groundStation.getEastOffsetDriver().isSelected()) {
            estimated.setParameterDerivatives(groundStation.getEastOffsetDriver(), dRdQT.getX());
        }
        if (groundStation.getNorthOffsetDriver().isSelected()) {
            estimated.setParameterDerivatives(groundStation.getNorthOffsetDriver(), dRdQT.getY());
        }
        if (groundStation.getZenithOffsetDriver().isSelected()) {
            estimated.setParameterDerivatives(groundStation.getZenithOffsetDriver(), dRdQT.getZ());
        }
    }
    return estimated;
}
Also used : SpacecraftState(org.orekit.propagation.SpacecraftState) Vector3D(org.hipparchus.geometry.euclidean.threed.Vector3D) FieldVector3D(org.hipparchus.geometry.euclidean.threed.FieldVector3D) AngularCoordinates(org.orekit.utils.AngularCoordinates) Transform(org.orekit.frames.Transform) FieldTransform(org.orekit.frames.FieldTransform) TimeStampedPVCoordinates(org.orekit.utils.TimeStampedPVCoordinates) FieldAbsoluteDate(org.orekit.time.FieldAbsoluteDate) AbsoluteDate(org.orekit.time.AbsoluteDate)

Example 74 with AbsoluteDate

use of org.orekit.time.AbsoluteDate in project Orekit by CS-SI.

the class RangeAnalyticTest method genericTestStateDerivatives.

/**
 * Generic test function for derivatives with respect to state
 * @param isModifier Use of atmospheric modifiers
 * @param isFiniteDifferences Finite differences reference calculation if true, Range class otherwise
 * @param printResults Print the results ?
 * @throws OrekitException
 */
void genericTestStateDerivatives(final boolean isModifier, final boolean isFiniteDifferences, final boolean printResults, final double refErrorsPMedian, final double refErrorsPMean, final double refErrorsPMax, final double refErrorsVMedian, final double refErrorsVMean, final double refErrorsVMax) throws OrekitException {
    Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
    final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 0.001);
    // Create perfect range measurements
    final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder);
    final List<ObservedMeasurement<?>> measurements = EstimationTestUtils.createMeasurements(propagator, new RangeMeasurementCreator(context), 1.0, 3.0, 300.0);
    // Lists for results' storage - Used only for derivatives with respect to state
    // "final" value to be seen by "handleStep" function of the propagator
    final List<Double> errorsP = new ArrayList<Double>();
    final List<Double> errorsV = new ArrayList<Double>();
    // Set master mode
    // Use a lambda function to implement "handleStep" function
    propagator.setMasterMode((OrekitStepInterpolator interpolator, boolean isLast) -> {
        for (final ObservedMeasurement<?> measurement : measurements) {
            // Play test if the measurement date is between interpolator previous and current date
            if ((measurement.getDate().durationFrom(interpolator.getPreviousState().getDate()) > 0.) && (measurement.getDate().durationFrom(interpolator.getCurrentState().getDate()) <= 0.)) {
                // Add modifiers if test implies it
                final RangeTroposphericDelayModifier modifier = new RangeTroposphericDelayModifier(SaastamoinenModel.getStandardModel());
                if (isModifier) {
                    ((Range) measurement).addModifier(modifier);
                }
                // We intentionally propagate to a date which is close to the
                // real spacecraft state but is *not* the accurate date, by
                // compensating only part of the downlink delay. This is done
                // in order to validate the partial derivatives with respect
                // to velocity. If we had chosen the proper state date, the
                // range would have depended only on the current position but
                // not on the current velocity.
                final double meanDelay = measurement.getObservedValue()[0] / Constants.SPEED_OF_LIGHT;
                final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
                final SpacecraftState state = interpolator.getInterpolatedState(date);
                final EstimatedMeasurement<Range> range = new RangeAnalytic((Range) measurement).theoreticalEvaluationAnalytic(0, 0, state);
                if (isModifier) {
                    modifier.modify(range);
                }
                final double[][] jacobian = range.getStateDerivatives(0);
                // Jacobian reference value
                final double[][] jacobianRef;
                if (isFiniteDifferences) {
                    // Compute a reference value using finite differences
                    jacobianRef = Differentiation.differentiate(new StateFunction() {

                        public double[] value(final SpacecraftState state) throws OrekitException {
                            return measurement.estimate(0, 0, new SpacecraftState[] { state }).getEstimatedValue();
                        }
                    }, measurement.getDimension(), propagator.getAttitudeProvider(), OrbitType.CARTESIAN, PositionAngle.TRUE, 2.0, 3).value(state);
                } else {
                    // Compute a reference value using Range class function
                    jacobianRef = ((Range) measurement).theoreticalEvaluation(0, 0, new SpacecraftState[] { state }).getStateDerivatives(0);
                }
                // //Test: Test point by point with the debugger
                // if (!isFiniteDifferences && !isModifier) {
                // final EstimatedMeasurement<Range> test =
                // new RangeAnalytic((Range)measurement).theoreticalEvaluationValidation(0, 0, state);
                // }
                // //Test
                Assert.assertEquals(jacobianRef.length, jacobian.length);
                Assert.assertEquals(jacobianRef[0].length, jacobian[0].length);
                // Errors & relative errors on the jacobian
                double[][] dJacobian = new double[jacobian.length][jacobian[0].length];
                double[][] dJacobianRelative = new double[jacobian.length][jacobian[0].length];
                for (int i = 0; i < jacobian.length; ++i) {
                    for (int j = 0; j < jacobian[i].length; ++j) {
                        dJacobian[i][j] = jacobian[i][j] - jacobianRef[i][j];
                        dJacobianRelative[i][j] = FastMath.abs(dJacobian[i][j] / jacobianRef[i][j]);
                        if (j < 3) {
                            errorsP.add(dJacobianRelative[i][j]);
                        } else {
                            errorsV.add(dJacobianRelative[i][j]);
                        }
                    }
                }
                // Print values in console ?
                if (printResults) {
                    String stationName = ((Range) measurement).getStation().getBaseFrame().getName();
                    System.out.format(Locale.US, "%-15s  %-23s  %-23s  " + "%10.3e  %10.3e  %10.3e  " + "%10.3e  %10.3e  %10.3e  " + "%10.3e  %10.3e  %10.3e  " + "%10.3e  %10.3e  %10.3e%n", stationName, measurement.getDate(), date, dJacobian[0][0], dJacobian[0][1], dJacobian[0][2], dJacobian[0][3], dJacobian[0][4], dJacobian[0][5], dJacobianRelative[0][0], dJacobianRelative[0][1], dJacobianRelative[0][2], dJacobianRelative[0][3], dJacobianRelative[0][4], dJacobianRelative[0][5]);
                }
            }
        // End if measurement date between previous and current interpolator step
        }
    // End for loop on the measurements
    });
    // Print results on console ?
    if (printResults) {
        System.out.format(Locale.US, "%-15s  %-23s  %-23s  " + "%10s  %10s  %10s  " + "%10s  %10s  %10s  " + "%10s  %10s  %10s  " + "%10s  %10s  %10s%n", "Station", "Measurement Date", "State Date", "ΔdPx", "ΔdPy", "ΔdPz", "ΔdVx", "ΔdVy", "ΔdVz", "rel ΔdPx", "rel ΔdPy", "rel ΔdPz", "rel ΔdVx", "rel ΔdVy", "rel ΔdVz");
    }
    // Rewind the propagator to initial date
    propagator.propagate(context.initialOrbit.getDate());
    // Sort measurements chronologically
    measurements.sort(new ChronologicalComparator());
    // Propagate to final measurement's date
    propagator.propagate(measurements.get(measurements.size() - 1).getDate());
    // Convert lists to double[] and evaluate some statistics
    final double[] relErrorsP = errorsP.stream().mapToDouble(Double::doubleValue).toArray();
    final double[] relErrorsV = errorsV.stream().mapToDouble(Double::doubleValue).toArray();
    final double errorsPMedian = new Median().evaluate(relErrorsP);
    final double errorsPMean = new Mean().evaluate(relErrorsP);
    final double errorsPMax = new Max().evaluate(relErrorsP);
    final double errorsVMedian = new Median().evaluate(relErrorsV);
    final double errorsVMean = new Mean().evaluate(relErrorsV);
    final double errorsVMax = new Max().evaluate(relErrorsV);
    // Print the results on console ?
    if (printResults) {
        System.out.println();
        System.out.format(Locale.US, "Relative errors dR/dP -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n", errorsPMedian, errorsPMean, errorsPMax);
        System.out.format(Locale.US, "Relative errors dR/dV -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n", errorsVMedian, errorsVMean, errorsVMax);
    }
    // Reference comparison with Range class
    Assert.assertEquals(0.0, errorsPMedian, refErrorsPMedian);
    Assert.assertEquals(0.0, errorsPMean, refErrorsPMean);
    Assert.assertEquals(0.0, errorsPMax, refErrorsPMax);
    Assert.assertEquals(0.0, errorsVMedian, refErrorsVMedian);
    Assert.assertEquals(0.0, errorsVMean, refErrorsVMean);
    Assert.assertEquals(0.0, errorsVMax, refErrorsVMax);
}
Also used : Mean(org.hipparchus.stat.descriptive.moment.Mean) Max(org.hipparchus.stat.descriptive.rank.Max) ArrayList(java.util.ArrayList) Median(org.hipparchus.stat.descriptive.rank.Median) AbsoluteDate(org.orekit.time.AbsoluteDate) SpacecraftState(org.orekit.propagation.SpacecraftState) Propagator(org.orekit.propagation.Propagator) OrekitException(org.orekit.errors.OrekitException) Context(org.orekit.estimation.Context) RangeTroposphericDelayModifier(org.orekit.estimation.measurements.modifiers.RangeTroposphericDelayModifier) OrekitStepInterpolator(org.orekit.propagation.sampling.OrekitStepInterpolator) NumericalPropagatorBuilder(org.orekit.propagation.conversion.NumericalPropagatorBuilder) StateFunction(org.orekit.utils.StateFunction) ChronologicalComparator(org.orekit.time.ChronologicalComparator)

Example 75 with AbsoluteDate

use of org.orekit.time.AbsoluteDate in project Orekit by CS-SI.

the class RangeAnalyticTest method genericTestParameterDerivatives.

/**
 * Generic test function for derivatives with respect to parameters (station's position in station's topocentric frame)
 * @param isModifier Use of atmospheric modifiers
 * @param isFiniteDifferences Finite differences reference calculation if true, Range class otherwise
 * @param printResults Print the results ?
 * @throws OrekitException
 */
void genericTestParameterDerivatives(final boolean isModifier, final boolean isFiniteDifferences, final boolean printResults) throws OrekitException {
    Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
    final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 0.001);
    // Create perfect range measurements
    for (final GroundStation station : context.stations) {
        station.getEastOffsetDriver().setSelected(true);
        station.getNorthOffsetDriver().setSelected(true);
        station.getZenithOffsetDriver().setSelected(true);
    }
    final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder);
    final List<ObservedMeasurement<?>> measurements = EstimationTestUtils.createMeasurements(propagator, new RangeMeasurementCreator(context), 1.0, 3.0, 300.0);
    // List to store the results
    final List<Double> relErrorList = new ArrayList<Double>();
    // Set master mode
    // Use a lambda function to implement "handleStep" function
    propagator.setMasterMode((OrekitStepInterpolator interpolator, boolean isLast) -> {
        for (final ObservedMeasurement<?> measurement : measurements) {
            // Play test if the measurement date is between interpolator previous and current date
            if ((measurement.getDate().durationFrom(interpolator.getPreviousState().getDate()) > 0.) && (measurement.getDate().durationFrom(interpolator.getCurrentState().getDate()) <= 0.)) {
                // Add modifiers if test implies it
                final RangeTroposphericDelayModifier modifier = new RangeTroposphericDelayModifier(SaastamoinenModel.getStandardModel());
                if (isModifier) {
                    ((Range) measurement).addModifier(modifier);
                }
                // Parameter corresponding to station position offset
                final GroundStation stationParameter = ((Range) measurement).getStation();
                // We intentionally propagate to a date which is close to the
                // real spacecraft state but is *not* the accurate date, by
                // compensating only part of the downlink delay. This is done
                // in order to validate the partial derivatives with respect
                // to velocity. If we had chosen the proper state date, the
                // range would have depended only on the current position but
                // not on the current velocity.
                final double meanDelay = measurement.getObservedValue()[0] / Constants.SPEED_OF_LIGHT;
                final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
                final SpacecraftState state = interpolator.getInterpolatedState(date);
                final ParameterDriver[] drivers = new ParameterDriver[] { stationParameter.getEastOffsetDriver(), stationParameter.getNorthOffsetDriver(), stationParameter.getZenithOffsetDriver() };
                if (printResults) {
                    String stationName = ((Range) measurement).getStation().getBaseFrame().getName();
                    System.out.format(Locale.US, "%-15s  %-23s  %-23s  ", stationName, measurement.getDate(), date);
                }
                for (int i = 0; i < 3; ++i) {
                    final double[] gradient = measurement.estimate(0, 0, new SpacecraftState[] { state }).getParameterDerivatives(drivers[i]);
                    Assert.assertEquals(1, measurement.getDimension());
                    Assert.assertEquals(1, gradient.length);
                    // Compute a reference value using analytical formulas
                    final EstimatedMeasurement<Range> rangeAnalytic = new RangeAnalytic((Range) measurement).theoreticalEvaluationAnalytic(0, 0, state);
                    if (isModifier) {
                        modifier.modify(rangeAnalytic);
                    }
                    final double ref = rangeAnalytic.getParameterDerivatives(drivers[i])[0];
                    if (printResults) {
                        System.out.format(Locale.US, "%10.3e  %10.3e  ", gradient[0] - ref, FastMath.abs((gradient[0] - ref) / ref));
                    }
                    final double relError = FastMath.abs((ref - gradient[0]) / ref);
                    relErrorList.add(relError);
                // Assert.assertEquals(ref, gradient[0], 6.1e-5 * FastMath.abs(ref));
                }
                if (printResults) {
                    System.out.format(Locale.US, "%n");
                }
            }
        // End if measurement date between previous and current interpolator step
        }
    // End for loop on the measurements
    });
    // Rewind the propagator to initial date
    propagator.propagate(context.initialOrbit.getDate());
    // Sort measurements chronologically
    measurements.sort(new ChronologicalComparator());
    // Print results ? Header
    if (printResults) {
        System.out.format(Locale.US, "%-15s  %-23s  %-23s  " + "%10s  %10s  %10s  " + "%10s  %10s  %10s%n", "Station", "Measurement Date", "State Date", "ΔdQx", "rel ΔdQx", "ΔdQy", "rel ΔdQy", "ΔdQz", "rel ΔdQz");
    }
    // Propagate to final measurement's date
    propagator.propagate(measurements.get(measurements.size() - 1).getDate());
    // Convert error list to double[]
    final double[] relErrors = relErrorList.stream().mapToDouble(Double::doubleValue).toArray();
    // Compute statistics
    final double relErrorsMedian = new Median().evaluate(relErrors);
    final double relErrorsMean = new Mean().evaluate(relErrors);
    final double relErrorsMax = new Max().evaluate(relErrors);
    // Print the results on console ?
    if (printResults) {
        System.out.println();
        System.out.format(Locale.US, "Relative errors dR/dQ -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n", relErrorsMedian, relErrorsMean, relErrorsMax);
    }
    // Assert the results / max values depend on the test
    double refErrorsMedian, refErrorsMean, refErrorsMax;
    // Analytic references
    refErrorsMedian = 1.55e-06;
    refErrorsMean = 3.64e-06;
    refErrorsMax = 6.1e-05;
    Assert.assertEquals(0.0, relErrorsMedian, refErrorsMedian);
    Assert.assertEquals(0.0, relErrorsMean, refErrorsMean);
    Assert.assertEquals(0.0, relErrorsMax, refErrorsMax);
}
Also used : Mean(org.hipparchus.stat.descriptive.moment.Mean) Max(org.hipparchus.stat.descriptive.rank.Max) ArrayList(java.util.ArrayList) Median(org.hipparchus.stat.descriptive.rank.Median) AbsoluteDate(org.orekit.time.AbsoluteDate) SpacecraftState(org.orekit.propagation.SpacecraftState) Propagator(org.orekit.propagation.Propagator) Context(org.orekit.estimation.Context) ParameterDriver(org.orekit.utils.ParameterDriver) RangeTroposphericDelayModifier(org.orekit.estimation.measurements.modifiers.RangeTroposphericDelayModifier) OrekitStepInterpolator(org.orekit.propagation.sampling.OrekitStepInterpolator) NumericalPropagatorBuilder(org.orekit.propagation.conversion.NumericalPropagatorBuilder) ChronologicalComparator(org.orekit.time.ChronologicalComparator)

Aggregations

AbsoluteDate (org.orekit.time.AbsoluteDate)840 Test (org.junit.Test)632 Vector3D (org.hipparchus.geometry.euclidean.threed.Vector3D)321 FieldAbsoluteDate (org.orekit.time.FieldAbsoluteDate)283 SpacecraftState (org.orekit.propagation.SpacecraftState)279 KeplerianOrbit (org.orekit.orbits.KeplerianOrbit)204 PVCoordinates (org.orekit.utils.PVCoordinates)193 Orbit (org.orekit.orbits.Orbit)157 Frame (org.orekit.frames.Frame)152 OrekitException (org.orekit.errors.OrekitException)141 DateComponents (org.orekit.time.DateComponents)134 TimeStampedPVCoordinates (org.orekit.utils.TimeStampedPVCoordinates)106 CartesianOrbit (org.orekit.orbits.CartesianOrbit)104 EquinoctialOrbit (org.orekit.orbits.EquinoctialOrbit)97 ArrayList (java.util.ArrayList)96 Propagator (org.orekit.propagation.Propagator)90 TimeScale (org.orekit.time.TimeScale)90 OneAxisEllipsoid (org.orekit.bodies.OneAxisEllipsoid)88 TimeComponents (org.orekit.time.TimeComponents)88 FieldVector3D (org.hipparchus.geometry.euclidean.threed.FieldVector3D)87