RangeIonosphericDelayModifier.java

  1. /* Copyright 2002-2018 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.estimation.measurements.modifiers;

  18. import java.util.Arrays;
  19. import java.util.Collections;
  20. import java.util.List;

  21. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  22. import org.orekit.errors.OrekitException;
  23. import org.orekit.errors.OrekitExceptionWrapper;
  24. import org.orekit.estimation.measurements.EstimatedMeasurement;
  25. import org.orekit.estimation.measurements.EstimationModifier;
  26. import org.orekit.estimation.measurements.GroundStation;
  27. import org.orekit.estimation.measurements.Range;
  28. import org.orekit.models.earth.IonosphericModel;
  29. import org.orekit.orbits.OrbitType;
  30. import org.orekit.orbits.PositionAngle;
  31. import org.orekit.propagation.Propagator;
  32. import org.orekit.propagation.SpacecraftState;
  33. import org.orekit.utils.Differentiation;
  34. import org.orekit.utils.ParameterDriver;
  35. import org.orekit.utils.ParameterFunction;
  36. import org.orekit.utils.StateFunction;

  37. /** Class modifying theoretical range measurement with ionospheric delay.
  38.  * The effect of ionospheric correction on the range is directly computed
  39.  * through the computation of the ionospheric delay.
  40.  *
  41.  * The ionospheric delay depends on the frequency of the signal (GNSS, VLBI, ...).
  42.  * For optical measurements (e.g. SLR), the ray is not affected by ionosphere charged particles.
  43.  *
  44.  * @author Maxime Journot
  45.  * @author Joris Olympio
  46.  * @since 8.0
  47.  */
  48. public class RangeIonosphericDelayModifier implements EstimationModifier<Range> {

  49.     /** Ionospheric delay model. */
  50.     private final IonosphericModel ionoModel;

  51.     /** Constructor.
  52.      *
  53.      * @param model  Ionospheric delay model appropriate for the current range measurement method.
  54.      */
  55.     public RangeIonosphericDelayModifier(final IonosphericModel model) {
  56.         ionoModel = model;
  57.     }

  58.     /** Compute the measurement error due to ionosphere.
  59.      * @param station station
  60.      * @param state spacecraft state
  61.      * @return the measurement error due to ionosphere
  62.      * @throws OrekitException  if frames transformations cannot be computed
  63.      */
  64.     private double rangeErrorIonosphericModel(final GroundStation station,
  65.                                               final SpacecraftState state)
  66.         throws OrekitException {
  67.         //
  68.         final Vector3D position = state.getPVCoordinates().getPosition();

  69.         // elevation
  70.         final double elevation = station.getBaseFrame().getElevation(position,
  71.                                                                      state.getFrame(),
  72.                                                                      state.getDate());

  73.         // only consider measures above the horizon
  74.         if (elevation > 0) {

  75.             // compute azimuth
  76.             final double azimuth = station.getBaseFrame().getAzimuth(position,
  77.                                                                      state.getFrame(),
  78.                                                                      state.getDate());

  79.             // delay in meters
  80.             final double delay = ionoModel.pathDelay(state.getDate(),
  81.                                                      station.getBaseFrame().getPoint(),
  82.                                                      elevation, azimuth);
  83.             return delay;
  84.         }

  85.         return 0;
  86.     }

  87.     /** Compute the Jacobian of the delay term wrt state.
  88.      *
  89.      * @param station station
  90.      * @param refstate reference spacecraft state
  91.      *
  92.      * @return Jacobian of the delay wrt state
  93.      * @throws OrekitException  if frames transformations cannot be computed
  94.      */
  95.     private double[][] rangeErrorJacobianState(final GroundStation station,
  96.                                                final SpacecraftState refstate)
  97.         throws OrekitException {
  98.         final double[][] finiteDifferencesJacobian =
  99.                         Differentiation.differentiate(new StateFunction() {
  100.                             public double[] value(final SpacecraftState state) throws OrekitException {
  101.                                 try {
  102.                                     // evaluate target's elevation with a changed target position
  103.                                     final double value = rangeErrorIonosphericModel(station, state);

  104.                                     return new double[] {
  105.                                         value
  106.                                     };

  107.                                 } catch (OrekitException oe) {
  108.                                     throw new OrekitExceptionWrapper(oe);
  109.                                 }
  110.                             }
  111.                         }, 1, Propagator.DEFAULT_LAW, OrbitType.CARTESIAN,
  112.                         PositionAngle.TRUE, 15.0, 3).value(refstate);

  113.         return finiteDifferencesJacobian;
  114.     }


  115.     /** Compute the derivative of the delay term wrt parameters.
  116.      *
  117.      * @param station ground station
  118.      * @param driver driver for the station offset parameter
  119.      * @param state spacecraft state
  120.      * @param delay current ionospheric delay
  121.      * @return derivative of the delay wrt station offset parameter
  122.      * @throws OrekitException  if frames transformations cannot be computed
  123.      */
  124.     private double rangeErrorParameterDerivative(final GroundStation station,
  125.                                                  final ParameterDriver driver,
  126.                                                  final SpacecraftState state,
  127.                                                  final double delay)
  128.         throws OrekitException {

  129.         final ParameterFunction rangeError = new ParameterFunction() {
  130.             /** {@inheritDoc} */
  131.             @Override
  132.             public double value(final ParameterDriver parameterDriver) throws OrekitException {
  133.                 return rangeErrorIonosphericModel(station, state);
  134.             }
  135.         };

  136.         final ParameterFunction rangeErrorDerivative =
  137.                         Differentiation.differentiate(rangeError, driver, 3, 10.0);

  138.         return rangeErrorDerivative.value(driver);

  139.     }

  140.     /** {@inheritDoc} */
  141.     @Override
  142.     public List<ParameterDriver> getParametersDrivers() {
  143.         return Collections.emptyList();
  144.     }

  145.     @Override
  146.     public void modify(final EstimatedMeasurement<Range> estimated)
  147.         throws OrekitException {
  148.         final Range           measurement = estimated.getObservedMeasurement();
  149.         final GroundStation   station     = measurement.getStation();
  150.         final SpacecraftState state       = estimated.getStates()[0];

  151.         final double[] oldValue = estimated.getEstimatedValue();

  152.         final double delay = rangeErrorIonosphericModel(station, state);

  153.         // update estimated value taking into account the ionospheric delay.
  154.         // The ionospheric delay is directly added to the range.
  155.         final double[] newValue = oldValue.clone();
  156.         newValue[0] = newValue[0] + delay;
  157.         estimated.setEstimatedValue(newValue);

  158.         // update estimated derivatives with Jacobian of the measure wrt state
  159.         final double[][] djac = rangeErrorJacobianState(station, state);
  160.         final double[][] stateDerivatives = estimated.getStateDerivatives(0);
  161.         for (int irow = 0; irow < stateDerivatives.length; ++irow) {
  162.             for (int jcol = 0; jcol < stateDerivatives[0].length; ++jcol) {
  163.                 stateDerivatives[irow][jcol] += djac[irow][jcol];
  164.             }
  165.         }
  166.         estimated.setStateDerivatives(0, stateDerivatives);

  167.         for (final ParameterDriver driver : Arrays.asList(station.getEastOffsetDriver(),
  168.                                                           station.getNorthOffsetDriver(),
  169.                                                           station.getZenithOffsetDriver())) {
  170.             if (driver.isSelected()) {
  171.                 // update estimated derivatives with derivative of the modification wrt station parameters
  172.                 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
  173.                 parameterDerivative += rangeErrorParameterDerivative(station, driver, state, delay);
  174.                 estimated.setParameterDerivatives(driver, parameterDerivative);
  175.             }
  176.         }

  177.     }

  178. }