EstimatedIonosphericModel.java

  1. /* Copyright 2002-2025 CS GROUP
  2.  * Licensed to CS GROUP (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.models.earth.ionosphere;

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

  20. import org.hipparchus.CalculusFieldElement;
  21. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  22. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  23. import org.hipparchus.util.FastMath;
  24. import org.orekit.frames.FieldStaticTransform;
  25. import org.orekit.frames.StaticTransform;
  26. import org.orekit.frames.TopocentricFrame;
  27. import org.orekit.propagation.FieldSpacecraftState;
  28. import org.orekit.propagation.SpacecraftState;
  29. import org.orekit.time.AbsoluteDate;
  30. import org.orekit.time.FieldAbsoluteDate;
  31. import org.orekit.utils.ParameterDriver;

  32. /**
  33.  * An estimated ionospheric model. The ionospheric delay is computed according to the formula:
  34.  * <p>
  35.  *           40.3
  36.  *    δ =  --------  *  STEC      with, STEC = VTEC * F(elevation)
  37.  *            f²
  38.  * </p>
  39.  * With:
  40.  * <ul>
  41.  * <li>f: The frequency of the signal in Hz.</li>
  42.  * <li>STEC: The Slant Total Electron Content in TECUnits.</li>
  43.  * <li>VTEC: The Vertical Total Electron Content in TECUnits.</li>
  44.  * <li>F(elevation): A mapping function which depends on satellite elevation.</li>
  45.  * </ul>
  46.  * The VTEC is estimated as a {@link ParameterDriver}
  47.  *
  48.  * @author Bryan Cazabonne
  49.  * @since 10.2
  50.  */
  51. public class EstimatedIonosphericModel implements IonosphericModel, IonosphericDelayModel {

  52.     /** Name of the parameter of this model: the Vertical Total Electron Content. */
  53.     public static final String VERTICAL_TOTAL_ELECTRON_CONTENT = "vertical total electron content";

  54.     /** Ionospheric delay factor. */
  55.     private static final double FACTOR = 40.3e16;

  56.     /** Ionospheric mapping Function model. */
  57.     private final transient IonosphericMappingFunction model;

  58.     /** Driver for the Vertical Total Electron Content.*/
  59.     private final transient ParameterDriver vtec;


  60.     /**
  61.      * Build a new instance.
  62.      * @param model ionospheric mapping function
  63.      * @param vtecValue value of the Vertical Total Electron Content in TECUnits
  64.      */
  65.     public EstimatedIonosphericModel(final IonosphericMappingFunction model, final double vtecValue) {
  66.         this.model = model;
  67.         this.vtec  = new ParameterDriver(EstimatedIonosphericModel.VERTICAL_TOTAL_ELECTRON_CONTENT,
  68.                                          vtecValue, FastMath.scalb(1.0, 3), 0.0, 1000.0);
  69.     }

  70.     /** {@inheritDoc} */
  71.     @Override
  72.     public double pathDelay(final SpacecraftState state, final TopocentricFrame baseFrame,
  73.                             final double frequency, final double[] parameters) {
  74.         return pathDelay(state, baseFrame, state.getDate(), frequency, parameters);
  75.     }

  76.     /** {@inheritDoc} */
  77.     @Override
  78.     public double pathDelay(final SpacecraftState state,
  79.                             final TopocentricFrame baseFrame, final AbsoluteDate receptionDate,
  80.                             final double frequency, final double[] parameters) {

  81.         // we use transform from base frame to inert frame and invert it
  82.         // because base frame could be peered with inertial frame (hence improving performances with caching)
  83.         // but the reverse is almost never used
  84.         final StaticTransform base2Inert = baseFrame.getStaticTransformTo(state.getFrame(), receptionDate);
  85.         final Vector3D        position   = base2Inert.getInverse().transformPosition(state.getPosition());

  86.         // Elevation in radians
  87.         final double          elevation  = position.getDelta();

  88.         // Only consider measures above the horizon
  89.         if (elevation > 0.0) {
  90.             // Delay
  91.             return pathDelay(elevation, frequency, parameters);
  92.         }

  93.         return 0.0;
  94.     }

  95.     /**
  96.      * Calculates the ionospheric path delay for the signal path from a ground
  97.      * station to a satellite.
  98.      * <p>
  99.      * The path delay is computed for any elevation angle.
  100.      * </p>
  101.      * @param elevation elevation of the satellite in radians
  102.      * @param frequency frequency of the signal in Hz
  103.      * @param parameters ionospheric model parameters
  104.      * @return the path delay due to the ionosphere in m
  105.      */
  106.     public double pathDelay(final double elevation, final double frequency, final double[] parameters) {
  107.         // Square of the frequency
  108.         final double freq2 = frequency * frequency;
  109.         // Mapping factor
  110.         final double fz = model.mappingFactor(elevation);
  111.         // "Slant" Total Electron Content
  112.         final double stec = parameters[0] * fz;
  113.         // Delay computation
  114.         final double alpha  = FACTOR / freq2;
  115.         return alpha * stec;
  116.     }

  117.     /** {@inheritDoc} */
  118.     @Override
  119.     public <T extends CalculusFieldElement<T>> T pathDelay(final FieldSpacecraftState<T> state, final TopocentricFrame baseFrame,
  120.                                                        final double frequency, final T[] parameters) {
  121.         return pathDelay(state, baseFrame, state.getDate(), frequency, parameters);
  122.     }

  123.     /** {@inheritDoc} */
  124.     @Override
  125.     public <T extends CalculusFieldElement<T>> T pathDelay(final FieldSpacecraftState<T> state,
  126.                                                            final TopocentricFrame baseFrame, final FieldAbsoluteDate<T> receptionDate,
  127.                                                            final double frequency, final T[] parameters) {

  128.         // we use transform from base frame to inert frame and invert it
  129.         // because base frame could be peered with inertial frame (hence improving performances with caching)
  130.         // but the reverse is almost never used
  131.         final FieldStaticTransform<T> base2Inert = baseFrame.getStaticTransformTo(state.getFrame(), receptionDate);
  132.         final FieldVector3D<T>        position   = base2Inert.getInverse().transformPosition(state.getPosition());

  133.         // Elevation in radians
  134.         final T elevation = position.getDelta();

  135.         if (elevation.getReal() > 0.0) {
  136.             // Delay
  137.             return pathDelay(elevation, frequency, parameters);
  138.         }

  139.         return elevation.getField().getZero();
  140.     }

  141.     /**
  142.      * Calculates the ionospheric path delay for the signal path from a ground
  143.      * station to a satellite.
  144.      * <p>
  145.      * The path delay is computed for any elevation angle.
  146.      * </p>
  147.      * @param <T> type of the elements
  148.      * @param elevation elevation of the satellite in radians
  149.      * @param frequency frequency of the signal in Hz
  150.      * @param parameters ionospheric model parameters at state date
  151.      * @return the path delay due to the ionosphere in m
  152.      */
  153.     public <T extends CalculusFieldElement<T>> T pathDelay(final T elevation, final double frequency, final T[] parameters) {
  154.         // Square of the frequency
  155.         final double freq2 = frequency * frequency;
  156.         // Mapping factor
  157.         final T fz = model.mappingFactor(elevation);
  158.         // "Slant" Total Electron Content
  159.         final T stec = parameters[0].multiply(fz);
  160.         // Delay computation
  161.         final double alpha  = FACTOR / freq2;
  162.         return stec.multiply(alpha);
  163.     }

  164.     @Override
  165.     public List<ParameterDriver> getParametersDrivers() {
  166.         return Collections.singletonList(vtec);
  167.     }

  168. }