/* 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);
}
}