use of org.orekit.utils.ParameterDriver in project Orekit by CS-SI.
the class ModelTest method testBackwardPropagation.
@Test
public void testBackwardPropagation() throws OrekitException {
final 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);
final NumericalPropagatorBuilder[] builders = { propagatorBuilder };
// 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);
final ParameterDriversList estimatedMeasurementsParameters = new ParameterDriversList();
for (ObservedMeasurement<?> measurement : measurements) {
for (final ParameterDriver driver : measurement.getParametersDrivers()) {
if (driver.isSelected()) {
estimatedMeasurementsParameters.add(driver);
}
}
}
// create model
final ModelObserver modelObserver = new ModelObserver() {
/**
* {@inheritDoc}
*/
@Override
public void modelCalled(final Orbit[] newOrbits, final Map<ObservedMeasurement<?>, EstimatedMeasurement<?>> newEvaluations) {
// Do nothing here
}
};
final Model model = new Model(builders, measurements, estimatedMeasurementsParameters, modelObserver);
// Test forward propagation flag to false
assertEquals(false, model.isForwardPropagation());
}
use of org.orekit.utils.ParameterDriver in project Orekit by CS-SI.
the class AngularRaDecTest method testParameterDerivatives.
@Test
public void testParameterDerivatives() throws OrekitException {
Context context = EstimationTestUtils.geoStationnaryContext("regular-data:potential:tides");
final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(OrbitType.EQUINOCTIAL, PositionAngle.TRUE, false, 1.0e-6, 60.0, 0.001);
// create perfect azimuth-elevation 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 AngularRaDecMeasurementCreator(context), 0.25, 3.0, 600.0);
propagator.setSlaveMode();
for (final ObservedMeasurement<?> measurement : measurements) {
// parameter corresponding to station position offset
final GroundStation stationParameter = ((AngularRaDec) 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
// angular would have depended only on the current position but
// not on the current velocity.
final AbsoluteDate datemeas = measurement.getDate();
final SpacecraftState stateini = propagator.propagate(datemeas);
final Vector3D stationP = stationParameter.getOffsetToInertial(stateini.getFrame(), datemeas).transformPosition(Vector3D.ZERO);
final double meanDelay = AbstractMeasurement.signalTimeOfFlight(stateini.getPVCoordinates(), stationP, datemeas);
final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
final SpacecraftState state = propagator.propagate(date);
final ParameterDriver[] drivers = new ParameterDriver[] { stationParameter.getEastOffsetDriver(), stationParameter.getNorthOffsetDriver(), stationParameter.getZenithOffsetDriver() };
for (int i = 0; i < 3; ++i) {
final double[] gradient = measurement.estimate(0, 0, new SpacecraftState[] { state }).getParameterDerivatives(drivers[i]);
Assert.assertEquals(2, measurement.getDimension());
Assert.assertEquals(2, gradient.length);
for (final int k : new int[] { 0, 1 }) {
final ParameterFunction dMkdP = Differentiation.differentiate(new ParameterFunction() {
/**
* {@inheritDoc}
*/
@Override
public double value(final ParameterDriver parameterDriver) throws OrekitException {
return measurement.estimate(0, 0, new SpacecraftState[] { state }).getEstimatedValue()[k];
}
}, drivers[i], 3, 50.0);
final double ref = dMkdP.value(drivers[i]);
if (ref > 1.e-12) {
Assert.assertEquals(ref, gradient[k], 3e-9 * FastMath.abs(ref));
}
}
}
}
}
use of org.orekit.utils.ParameterDriver in project Orekit by CS-SI.
the class KalmanEstimatorTest method testKeplerianRangeWithOnBoardAntennaOffset.
/**
* Perfect range measurements with a biased start and an on-board antenna range offset
* Keplerian formalism
* @throws OrekitException
*/
@Test
public void testKeplerianRangeWithOnBoardAntennaOffset() throws OrekitException {
// Create context
Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
// Create initial orbit and propagator builder
final OrbitType orbitType = OrbitType.KEPLERIAN;
final PositionAngle positionAngle = PositionAngle.TRUE;
final boolean perfectStart = true;
final double minStep = 1.e-6;
final double maxStep = 60.;
final double dP = 1.;
final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(orbitType, positionAngle, perfectStart, minStep, maxStep, dP);
propagatorBuilder.setAttitudeProvider(new LofOffset(propagatorBuilder.getFrame(), LOFType.LVLH));
// Antenna phase center definition
final Vector3D antennaPhaseCenter = new Vector3D(-1.2, 2.3, -0.7);
// Create perfect range measurements with antenna offset
final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder);
final List<ObservedMeasurement<?>> measurements = EstimationTestUtils.createMeasurements(propagator, new RangeMeasurementCreator(context, antennaPhaseCenter), 1.0, 3.0, 300.0);
// Add antenna offset to the measurements
final OnBoardAntennaRangeModifier obaModifier = new OnBoardAntennaRangeModifier(antennaPhaseCenter);
for (final ObservedMeasurement<?> range : measurements) {
((Range) range).addModifier(obaModifier);
}
// Reference propagator for estimation performances
final NumericalPropagator referencePropagator = propagatorBuilder.buildPropagator(propagatorBuilder.getSelectedNormalizedParameters());
// Reference position/velocity at last measurement date
final Orbit refOrbit = referencePropagator.propagate(measurements.get(measurements.size() - 1).getDate()).getOrbit();
// Change semi-major axis of 1.2m as in the batch test
ParameterDriver aDriver = propagatorBuilder.getOrbitalParametersDrivers().getDrivers().get(0);
aDriver.setValue(aDriver.getValue() + 1.2);
aDriver.setReferenceDate(AbsoluteDate.GALILEO_EPOCH);
// Cartesian covariance matrix initialization
// 100m on position / 1e-2m/s on velocity
final RealMatrix cartesianP = MatrixUtils.createRealDiagonalMatrix(new double[] { 10., 10., 10., 1e-3, 1e-3, 1e-3 });
// Jacobian of the orbital parameters w/r to Cartesian
final Orbit initialOrbit = OrbitType.KEPLERIAN.convertType(context.initialOrbit);
final double[][] dYdC = new double[6][6];
initialOrbit.getJacobianWrtCartesian(PositionAngle.TRUE, dYdC);
final RealMatrix Jac = MatrixUtils.createRealMatrix(dYdC);
// Keplerian initial covariance matrix
final RealMatrix initialP = Jac.multiply(cartesianP.multiply(Jac.transpose()));
// Process noise matrix is set to 0 here
RealMatrix Q = MatrixUtils.createRealMatrix(6, 6);
// Build the Kalman filter
final KalmanEstimatorBuilder kalmanBuilder = new KalmanEstimatorBuilder();
kalmanBuilder.builder(propagatorBuilder);
kalmanBuilder.estimatedMeasurementsParameters(new ParameterDriversList());
kalmanBuilder.initialCovarianceMatrix(initialP);
kalmanBuilder.processNoiseMatrixProvider(new ConstantProcessNoise(Q));
final KalmanEstimator kalman = kalmanBuilder.build();
// Filter the measurements and check the results
final double expectedDeltaPos = 0.;
final double posEps = 4.57e-3;
final double expectedDeltaVel = 0.;
final double velEps = 7.29e-6;
final double[] expectedSigmasPos = { 1.105194, 0.930785, 1.254579 };
final double sigmaPosEps = 1e-6;
final double[] expectedSigmasVel = { 6.193718e-4, 4.088774e-4, 3.299135e-4 };
final double sigmaVelEps = 1e-10;
EstimationTestUtils.checkKalmanFit(context, kalman, measurements, refOrbit, positionAngle, expectedDeltaPos, posEps, expectedDeltaVel, velEps, expectedSigmasPos, sigmaPosEps, expectedSigmasVel, sigmaVelEps);
}
use of org.orekit.utils.ParameterDriver in project Orekit by CS-SI.
the class BatchLSEstimatorTest method testMultiSatWithParameters.
/**
* A modified version of the previous test with a selection of propagation drivers to estimate
* One common (µ)
* Some specifics for each satellite (Cr and Ca)
*
* @throws OrekitException
*/
@Test
public void testMultiSatWithParameters() throws OrekitException {
// Test: Set the propagator drivers to estimate for each satellite
final boolean muEstimated = true;
final boolean crEstimated1 = true;
final boolean caEstimated1 = true;
final boolean crEstimated2 = true;
final boolean caEstimated2 = false;
// Builder sat 1
final Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
final NumericalPropagatorBuilder propagatorBuilder1 = context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 1.0, Force.POTENTIAL, Force.SOLAR_RADIATION_PRESSURE);
// Adding selection of parameters
String satName = "sat 1";
for (DelegatingDriver driver : propagatorBuilder1.getPropagationParametersDrivers().getDrivers()) {
if (driver.getName().equals("central attraction coefficient")) {
driver.setSelected(muEstimated);
}
if (driver.getName().equals(RadiationSensitive.REFLECTION_COEFFICIENT)) {
driver.setName(driver.getName() + " " + satName);
driver.setSelected(crEstimated1);
}
if (driver.getName().equals(RadiationSensitive.ABSORPTION_COEFFICIENT)) {
driver.setName(driver.getName() + " " + satName);
driver.setSelected(caEstimated1);
}
}
// Builder for sat 2
final Context context2 = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
final NumericalPropagatorBuilder propagatorBuilder2 = context2.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 1.0, Force.POTENTIAL, Force.SOLAR_RADIATION_PRESSURE);
// Adding selection of parameters
satName = "sat 2";
for (ParameterDriver driver : propagatorBuilder2.getPropagationParametersDrivers().getDrivers()) {
if (driver.getName().equals("central attraction coefficient")) {
driver.setSelected(muEstimated);
}
if (driver.getName().equals(RadiationSensitive.REFLECTION_COEFFICIENT)) {
driver.setName(driver.getName() + " " + satName);
driver.setSelected(crEstimated2);
}
if (driver.getName().equals(RadiationSensitive.ABSORPTION_COEFFICIENT)) {
driver.setName(driver.getName() + " " + satName);
driver.setSelected(caEstimated2);
}
}
// Create perfect inter-satellites range measurements
final TimeStampedPVCoordinates original = context.initialOrbit.getPVCoordinates();
final Orbit closeOrbit = new CartesianOrbit(new TimeStampedPVCoordinates(context.initialOrbit.getDate(), original.getPosition().add(new Vector3D(1000, 2000, 3000)), original.getVelocity().add(new Vector3D(-0.03, 0.01, 0.02))), context.initialOrbit.getFrame(), context.initialOrbit.getMu());
final Propagator closePropagator = EstimationTestUtils.createPropagator(closeOrbit, propagatorBuilder2);
closePropagator.setEphemerisMode();
closePropagator.propagate(context.initialOrbit.getDate().shiftedBy(3.5 * closeOrbit.getKeplerianPeriod()));
final BoundedPropagator ephemeris = closePropagator.getGeneratedEphemeris();
Propagator propagator1 = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder1);
final List<ObservedMeasurement<?>> r12 = EstimationTestUtils.createMeasurements(propagator1, new InterSatellitesRangeMeasurementCreator(ephemeris), 1.0, 3.0, 300.0);
// create perfect range measurements for first satellite
propagator1 = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder1);
final List<ObservedMeasurement<?>> r1 = EstimationTestUtils.createMeasurements(propagator1, new RangeMeasurementCreator(context), 1.0, 3.0, 300.0);
// create orbit estimator
final BatchLSEstimator estimator = new BatchLSEstimator(new LevenbergMarquardtOptimizer(), propagatorBuilder1, propagatorBuilder2);
for (final ObservedMeasurement<?> interSat : r12) {
estimator.addMeasurement(interSat);
}
for (final ObservedMeasurement<?> range : r1) {
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[] orbits, 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;
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;
}
}
});
List<DelegatingDriver> parameters = estimator.getOrbitalParametersDrivers(true).getDrivers();
ParameterDriver a0Driver = parameters.get(0);
Assert.assertEquals("a[0]", a0Driver.getName());
a0Driver.setValue(a0Driver.getValue() + 1.2);
a0Driver.setReferenceDate(AbsoluteDate.GALILEO_EPOCH);
ParameterDriver a1Driver = parameters.get(6);
Assert.assertEquals("a[1]", a1Driver.getName());
a1Driver.setValue(a1Driver.getValue() - 5.4);
a1Driver.setReferenceDate(AbsoluteDate.GALILEO_EPOCH);
final Orbit before = new KeplerianOrbit(parameters.get(6).getValue(), parameters.get(7).getValue(), parameters.get(8).getValue(), parameters.get(9).getValue(), parameters.get(10).getValue(), parameters.get(11).getValue(), PositionAngle.TRUE, closeOrbit.getFrame(), closeOrbit.getDate(), closeOrbit.getMu());
Assert.assertEquals(4.7246, Vector3D.distance(closeOrbit.getPVCoordinates().getPosition(), before.getPVCoordinates().getPosition()), 1.0e-3);
Assert.assertEquals(0.0010514, Vector3D.distance(closeOrbit.getPVCoordinates().getVelocity(), before.getPVCoordinates().getVelocity()), 1.0e-6);
EstimationTestUtils.checkFit(context, estimator, 4, 5, 0.0, 6.0e-06, 0.0, 1.7e-05, 0.0, 4.4e-07, 0.0, 1.7e-10);
final Orbit determined = new KeplerianOrbit(parameters.get(6).getValue(), parameters.get(7).getValue(), parameters.get(8).getValue(), parameters.get(9).getValue(), parameters.get(10).getValue(), parameters.get(11).getValue(), PositionAngle.TRUE, closeOrbit.getFrame(), closeOrbit.getDate(), closeOrbit.getMu());
Assert.assertEquals(0.0, Vector3D.distance(closeOrbit.getPVCoordinates().getPosition(), determined.getPVCoordinates().getPosition()), 5.8e-6);
Assert.assertEquals(0.0, Vector3D.distance(closeOrbit.getPVCoordinates().getVelocity(), determined.getPVCoordinates().getVelocity()), 3.5e-9);
// got a default one
for (final ParameterDriver driver : estimator.getOrbitalParametersDrivers(true).getDrivers()) {
if (driver.getName().startsWith("a[")) {
// user-specified reference date
Assert.assertEquals(0, driver.getReferenceDate().durationFrom(AbsoluteDate.GALILEO_EPOCH), 1.0e-15);
} else {
// default reference date
Assert.assertEquals(0, driver.getReferenceDate().durationFrom(propagatorBuilder1.getInitialOrbitDate()), 1.0e-15);
}
}
}
use of org.orekit.utils.ParameterDriver 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);
}
Aggregations