/* Copyright 2002-2017 CS Systèmes d'Information * Licensed to CS Systèmes d'Information (CS) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * CS licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.orekit.estimation.leastsquares; import java.util.ArrayList; import java.util.List; import org.hipparchus.exception.LocalizedCoreFormats; import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem.Evaluation; import org.hipparchus.optim.nonlinear.vector.leastsquares.LevenbergMarquardtOptimizer; import org.junit.Assert; import org.junit.Test; import org.orekit.errors.OrekitException; import org.orekit.errors.OrekitMessages; import org.orekit.estimation.Context; import org.orekit.estimation.EstimationTestUtils; import org.orekit.estimation.measurements.EstimationsProvider; import org.orekit.estimation.measurements.ObservedMeasurement; import org.orekit.estimation.measurements.PVMeasurementCreator; import org.orekit.estimation.measurements.RangeMeasurementCreator; import org.orekit.estimation.measurements.RangeRateMeasurementCreator; import org.orekit.orbits.Orbit; import org.orekit.orbits.OrbitType; import org.orekit.orbits.PositionAngle; import org.orekit.propagation.Propagator; import org.orekit.propagation.conversion.NumericalPropagatorBuilder; import org.orekit.time.AbsoluteDate; import org.orekit.utils.ParameterDriver; import org.orekit.utils.ParameterDriversList; public class BatchLSEstimatorTest { @Test public void testKeplerPV() throws OrekitException { Context context = EstimationTestUtils.eccentricContext(); final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 1.0); // create perfect PV measurements final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder); final List<ObservedMeasurement<?>> measurements = EstimationTestUtils.createMeasurements(propagator, new PVMeasurementCreator(), 0.0, 1.0, 300.0); // create orbit estimator final BatchLSEstimator estimator = new BatchLSEstimator(propagatorBuilder, new LevenbergMarquardtOptimizer()); for (final ObservedMeasurement<?> measurement : measurements) { estimator.addMeasurement(measurement); } estimator.setParametersConvergenceThreshold(1.0e-2); estimator.setMaxIterations(10); estimator.setMaxEvaluations(20); EstimationTestUtils.checkFit(context, estimator, 1, 4, 0.0, 1.2e-8, 0.0, 5.5e-8, 0.0, 8.4e-9, 0.0, 3.2e-12); } @Test public void testKeplerRange() throws OrekitException { Context context = EstimationTestUtils.eccentricContext(); final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 1.0); // 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); // create orbit estimator final BatchLSEstimator estimator = new BatchLSEstimator(propagatorBuilder, new LevenbergMarquardtOptimizer()); for (final ObservedMeasurement<?> range : measurements) { estimator.addMeasurement(range); } estimator.setParametersConvergenceThreshold(1.0e-2); estimator.setMaxIterations(10); estimator.setMaxEvaluations(20); estimator.setObserver(new BatchLSObserver() { int lastIter = 0; int lastEval = 0; /** {@inheritDoc} */ @Override public void evaluationPerformed(int iterationsCount, int evaluationscount, Orbit orbit, ParameterDriversList estimatedOrbitalParameters, ParameterDriversList estimatedPropagatorParameters, ParameterDriversList estimatedMeasurementsParameters, EstimationsProvider evaluationsProvider, Evaluation lspEvaluation) throws OrekitException { if (iterationsCount == lastIter) { Assert.assertEquals(lastEval + 1, evaluationscount); } else { Assert.assertEquals(lastIter + 1, iterationsCount); } lastIter = iterationsCount; lastEval = evaluationscount; Assert.assertEquals(measurements.size(), evaluationsProvider.getNumber()); try { evaluationsProvider.getEstimatedMeasurement(-1); Assert.fail("an exception should have been thrown"); } catch (OrekitException oe) { Assert.assertEquals(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE, oe.getSpecifier()); } try { evaluationsProvider.getEstimatedMeasurement(measurements.size()); Assert.fail("an exception should have been thrown"); } catch (OrekitException oe) { Assert.assertEquals(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE, oe.getSpecifier()); } AbsoluteDate previous = AbsoluteDate.PAST_INFINITY; for (int i = 0; i < evaluationsProvider.getNumber(); ++i) { AbsoluteDate current = evaluationsProvider.getEstimatedMeasurement(i).getDate(); Assert.assertTrue(current.compareTo(previous) >= 0); previous = current; } } }); ParameterDriver aDriver = estimator.getOrbitalParametersDrivers(true).getDrivers().get(0); Assert.assertEquals("a", aDriver.getName()); aDriver.setValue(aDriver.getValue() + 1.2); EstimationTestUtils.checkFit(context, estimator, 2, 3, 0.0, 9.5e-7, 0.0, 2.8e-6, 0.0, 3.5e-7, 0.0, 2.2e-10); } @Test public void testWrappedException() throws OrekitException { Context context = EstimationTestUtils.eccentricContext(); final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 1.0); // 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); // create orbit estimator final BatchLSEstimator estimator = new BatchLSEstimator(propagatorBuilder, new LevenbergMarquardtOptimizer()); for (final ObservedMeasurement<?> range : measurements) { estimator.addMeasurement(range); } estimator.setParametersConvergenceThreshold(1.0e-2); estimator.setMaxIterations(10); estimator.setMaxEvaluations(20); estimator.setObserver(new BatchLSObserver() { /** {@inheritDoc} */ @Override public void evaluationPerformed(int iterationsCount, int evaluationscount, Orbit orbit, ParameterDriversList estimatedOrbitalParameters, ParameterDriversList estimatedPropagatorParameters, ParameterDriversList estimatedMeasurementsParameters, EstimationsProvider evaluationsProvider, Evaluation lspEvaluation) throws DummyException { throw new DummyException(); } }); try { EstimationTestUtils.checkFit(context, estimator, 3, 4, 0.0, 1.5e-6, 0.0, 3.2e-6, 0.0, 3.8e-7, 0.0, 1.5e-10); Assert.fail("an exception should have been thrown"); } catch (DummyException de) { // expected } } private static class DummyException extends OrekitException { private static final long serialVersionUID = 1L; public DummyException() { super(OrekitMessages.INTERNAL_ERROR); } } @Test public void testKeplerRangeRate() throws OrekitException { Context context = EstimationTestUtils.eccentricContext(); final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 1.0); // create perfect range measurements final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder); final List<ObservedMeasurement<?>> measurements1 = EstimationTestUtils.createMeasurements(propagator, new RangeRateMeasurementCreator(context, false), 1.0, 3.0, 300.0); final List<ObservedMeasurement<?>> measurements = new ArrayList<ObservedMeasurement<?>>(); measurements.addAll(measurements1); // create orbit estimator final BatchLSEstimator estimator = new BatchLSEstimator(propagatorBuilder, new LevenbergMarquardtOptimizer()); for (final ObservedMeasurement<?> rangerate : measurements) { estimator.addMeasurement(rangerate); } estimator.setParametersConvergenceThreshold(1.0e-3); estimator.setMaxIterations(10); estimator.setMaxEvaluations(20); EstimationTestUtils.checkFit(context, estimator, 3, 4, 0.0, 1.6e-2, 0.0, 3.4e-2, 0.0, 170.0, // we only have range rate... 0.0, 6.5e-2); } @Test public void testKeplerRangeAndRangeRate() throws OrekitException { Context context = EstimationTestUtils.eccentricContext(); final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 1.0); // create perfect range measurements final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder); final List<ObservedMeasurement<?>> measurementsRange = EstimationTestUtils.createMeasurements(propagator, new RangeMeasurementCreator(context), 1.0, 3.0, 300.0); final List<ObservedMeasurement<?>> measurementsRangeRate = EstimationTestUtils.createMeasurements(propagator, new RangeRateMeasurementCreator(context, false), 1.0, 3.0, 300.0); // concat measurements final List<ObservedMeasurement<?>> measurements = new ArrayList<ObservedMeasurement<?>>(); measurements.addAll(measurementsRange); measurements.addAll(measurementsRangeRate); // create orbit estimator final BatchLSEstimator estimator = new BatchLSEstimator(propagatorBuilder, new LevenbergMarquardtOptimizer()); for (final ObservedMeasurement<?> meas : measurements) { estimator.addMeasurement(meas); } estimator.setParametersConvergenceThreshold(1.0e-3); estimator.setMaxIterations(10); estimator.setMaxEvaluations(20); // we have low correlation between the two types of measurement. We can expect a good estimate. EstimationTestUtils.checkFit(context, estimator, 1, 2, 0.0, 0.16, 0.0, 0.40, 0.0, 2.1e-3, 0.0, 8.1e-7); } }