/* 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.measurements; import java.util.List; import org.hipparchus.geometry.euclidean.threed.Vector3D; import org.hipparchus.util.MathUtils; import org.hipparchus.util.Precision; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.orekit.bodies.GeodeticPoint; import org.orekit.errors.OrekitException; import org.orekit.errors.OrekitIllegalArgumentException; import org.orekit.errors.OrekitMessages; import org.orekit.estimation.Context; import org.orekit.estimation.EstimationTestUtils; import org.orekit.estimation.measurements.modifiers.AngularIonosphericDelayModifier; import org.orekit.estimation.measurements.modifiers.RangeIonosphericDelayModifier; import org.orekit.estimation.measurements.modifiers.RangeRateIonosphericDelayModifier; import org.orekit.estimation.measurements.modifiers.TurnAroundRangeIonosphericDelayModifier; import org.orekit.models.earth.KlobucharIonoModel; import org.orekit.orbits.OrbitType; import org.orekit.orbits.PositionAngle; import org.orekit.propagation.Propagator; import org.orekit.propagation.SpacecraftState; import org.orekit.propagation.conversion.NumericalPropagatorBuilder; import org.orekit.time.AbsoluteDate; import org.orekit.utils.ParameterDriver; public class IonoModifierTest { /** ionospheric model. */ private KlobucharIonoModel model; @Before public void setUp() throws Exception { // Navigation message data // .3820D-07 .1490D-07 -.1790D-06 .0000D-00 ION ALPHA // .1430D+06 .0000D+00 -.3280D+06 .1130D+06 ION BETA model = new KlobucharIonoModel(new double[]{.3820e-07, .1490e-07, -.1790e-06,0}, new double[]{.1430e+06, 0, -.3280e+06, .1130e+06}); } @After public void tearDown() { } @Test public void testRangeIonoModifier() throws OrekitException { Context context = EstimationTestUtils.eccentricContext(); 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); propagator.setSlaveMode(); final RangeIonosphericDelayModifier modifier = new RangeIonosphericDelayModifier(model); for (final ObservedMeasurement<?> measurement : measurements) { final AbsoluteDate date = measurement.getDate(); final SpacecraftState refstate = propagator.propagate(date); Range range = (Range) measurement; EstimatedMeasurement<Range> evalNoMod = range.estimate(12, 17, refstate); Assert.assertEquals(12, evalNoMod.getIteration()); Assert.assertEquals(17, evalNoMod.getCount()); // add modifier range.addModifier(modifier); boolean found = false; for (final EstimationModifier<Range> existing : range.getModifiers()) { found = found || existing == modifier; } Assert.assertTrue(found); // EstimatedMeasurement<Range> eval = range.estimate(0, 0, refstate); final double w = evalNoMod.getCurrentWeight()[0]; Assert.assertEquals(w, eval.getCurrentWeight()[0], 1.0e-10); eval.setCurrentWeight(new double[] { w + 2 }); Assert.assertEquals(w + 2, eval.getCurrentWeight()[0], 1.0e-10); try { eval.getParameterDerivatives(new ParameterDriver("extra", 0, 1, -1, +1)); Assert.fail("an exception should have been thrown"); } catch (OrekitIllegalArgumentException oiae) { Assert.assertEquals(OrekitMessages.UNSUPPORTED_PARAMETER_NAME, oiae.getSpecifier()); } final double diffMeters = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0]; // TODO: check threshold Assert.assertEquals(0.0, diffMeters, 30.0); } } @Test public void testTurnAroundRangeIonoModifier() throws OrekitException { Context context = EstimationTestUtils.eccentricContext(); final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 0.001); // create perfect turn-around 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 TurnAroundRangeMeasurementCreator(context), 1.0, 3.0, 300.0); propagator.setSlaveMode(); final TurnAroundRangeIonosphericDelayModifier modifier = new TurnAroundRangeIonosphericDelayModifier(model); for (final ObservedMeasurement<?> measurement : measurements) { final AbsoluteDate date = measurement.getDate(); final SpacecraftState refstate = propagator.propagate(date); TurnAroundRange turnAroundRange = (TurnAroundRange) measurement; EstimatedMeasurement<TurnAroundRange> evalNoMod = turnAroundRange.estimate(12, 17, refstate); Assert.assertEquals(12, evalNoMod.getIteration()); Assert.assertEquals(17, evalNoMod.getCount()); // Add modifier turnAroundRange.addModifier(modifier); boolean found = false; for (final EstimationModifier<TurnAroundRange> existing : turnAroundRange.getModifiers()) { found = found || existing == modifier; } Assert.assertTrue(found); // EstimatedMeasurement<TurnAroundRange> eval = turnAroundRange.estimate(0, 0, refstate); final double w = evalNoMod.getCurrentWeight()[0]; Assert.assertEquals(w, eval.getCurrentWeight()[0], 1.0e-10); eval.setCurrentWeight(new double[] { w + 2 }); Assert.assertEquals(w + 2, eval.getCurrentWeight()[0], 1.0e-10); try { eval.getParameterDerivatives(new ParameterDriver("extra", 0, 1, -1, +1)); Assert.fail("an exception should have been thrown"); } catch (OrekitIllegalArgumentException oiae) { Assert.assertEquals(OrekitMessages.UNSUPPORTED_PARAMETER_NAME, oiae.getSpecifier()); } final double diffMeters = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0]; // TODO: check threshold Assert.assertEquals(0.0, diffMeters, 30.0); } } @Test public void testRangeRateIonoModifier() throws OrekitException { Context context = EstimationTestUtils.eccentricContext(); 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 RangeRateMeasurementCreator(context, false), 1.0, 3.0, 300.0); propagator.setSlaveMode(); final RangeRateIonosphericDelayModifier modifier = new RangeRateIonosphericDelayModifier(model, true); for (final ObservedMeasurement<?> measurement : measurements) { final AbsoluteDate date = measurement.getDate(); final SpacecraftState refstate = propagator.propagate(date); RangeRate rangeRate = (RangeRate) measurement; EstimatedMeasurement<RangeRate> evalNoMod = rangeRate.estimate(0, 0, refstate); // add modifier rangeRate.addModifier(modifier); // EstimatedMeasurement<RangeRate> eval = rangeRate.estimate(0, 0, refstate); final double diffMetersSec = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0]; // TODO: check threshold Assert.assertEquals(0.0, diffMetersSec, 0.016); } } @Test public void testAngularIonoModifier() throws OrekitException { Context context = EstimationTestUtils.eccentricContext(); 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 AngularMeasurementCreator(context), 1.0, 3.0, 300.0); propagator.setSlaveMode(); final AngularIonosphericDelayModifier modifier = new AngularIonosphericDelayModifier(model); for (final ObservedMeasurement<?> measurement : measurements) { final AbsoluteDate date = measurement.getDate(); final SpacecraftState refstate = propagator.propagate(date); Angular angular = (Angular) measurement; EstimatedMeasurement<Angular> evalNoMod = angular.estimate(0, 0, refstate); // add modifier angular.addModifier(modifier); // EstimatedMeasurement<Angular> eval = angular.estimate(0, 0, refstate); final double diffAz = MathUtils.normalizeAngle(eval.getEstimatedValue()[0], evalNoMod.getEstimatedValue()[0]) - evalNoMod.getEstimatedValue()[0]; final double diffEl = MathUtils.normalizeAngle(eval.getEstimatedValue()[1], evalNoMod.getEstimatedValue()[1]) - evalNoMod.getEstimatedValue()[1]; // TODO: check threshold Assert.assertEquals(0.0, diffAz, 5.0e-5); Assert.assertEquals(0.0, diffEl, 5.0e-6); } } @Test public void testKlobucharIonoModel() throws OrekitException { Context context = EstimationTestUtils.eccentricContext(); 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); propagator.setSlaveMode(); for (final ObservedMeasurement<?> measurement : measurements) { // parameter corresponding to station position offset final GroundStation station = ((Range) measurement).getStation(); final AbsoluteDate date = ((Range) measurement).getDate(); final SpacecraftState state = propagator.propagate(date); final Vector3D position = state.getPVCoordinates().getPosition(); // final GeodeticPoint geo = station.getBaseFrame().getPoint(); // elevation final double elevation = station.getBaseFrame().getElevation(position, state.getFrame(), state.getDate()); // elevation final double azimuth = station.getBaseFrame().getAzimuth(position, state.getFrame(), state.getDate()); double delayMeters = model.pathDelay(date, geo, elevation, azimuth); final double epsilon = 1e-6; Assert.assertTrue(Precision.compareTo(delayMeters, 15., epsilon) < 0); Assert.assertTrue(Precision.compareTo(delayMeters, 0., epsilon) > 0); } } }