EarthITU453AtmosphereRefraction.java

  1. /* Copyright 2013 Applied Defense Solutions, Inc.
  2.  * Licensed to CS Communication & Systèmes (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;

  18. import org.hipparchus.analysis.UnivariateFunction;
  19. import org.hipparchus.optim.MaxEval;
  20. import org.hipparchus.optim.nonlinear.scalar.GoalType;
  21. import org.hipparchus.optim.univariate.BrentOptimizer;
  22. import org.hipparchus.optim.univariate.SearchInterval;
  23. import org.hipparchus.optim.univariate.UnivariateObjectiveFunction;
  24. import org.hipparchus.util.FastMath;
  25. import org.orekit.models.AtmosphericRefractionModel;

  26. /** Implementation of refraction model for Earth exponential atmosphere based on ITU-R P.834-7 recommendation.
  27.  * <p>Refraction angle is computed according to the International Telecommunication Union recommendation formula.
  28.  *  For reference, see <b>ITU-R P.834-7</b> (October 2015).</p>
  29.  *
  30.  * @author Thierry Ceolin
  31.  * @since 7.1
  32.  */

  33. public class EarthITU453AtmosphereRefraction implements AtmosphericRefractionModel {

  34.     /** Altitude conversion factor. */
  35.     private static final double KM_TO_M = 1000.0;

  36.     /** Coefficients conversion factor. */
  37.     private static final double INV_DEG_TO_INV_RAD = 180.0 / FastMath.PI;

  38.     /** Default a coefficients to compute refractive index for a typical atmosphere. */
  39.     private static final double DEFAULT_CORRECTION_ACOEF = 0.000315;

  40.     /** Default b coefficients to compute refractive index for a typical atmosphere. */
  41.     private static final double DEFAULT_CORRECTION_BCOEF = 0.1361 / KM_TO_M;

  42.     /** Earth ray as defined in ITU-R P.834-7 (m). */
  43.     private static final double EARTH_RAY = 6370.0 * KM_TO_M;

  44.     /** Default coefficients array for Tau function (formula number 9).
  45.      * The coefficients have been converted to SI units
  46.      */
  47.     private static final double[] CCOEF = {
  48.         INV_DEG_TO_INV_RAD * 1.314,  INV_DEG_TO_INV_RAD * 0.6437,  INV_DEG_TO_INV_RAD * 0.02869,
  49.         INV_DEG_TO_INV_RAD * 0.2305 / KM_TO_M, INV_DEG_TO_INV_RAD * 0.09428 / KM_TO_M, INV_DEG_TO_INV_RAD * 0.01096 / KM_TO_M,
  50.         INV_DEG_TO_INV_RAD * 0.008583 / (KM_TO_M * KM_TO_M)
  51.     };

  52.     /** Default coefficients array for TauZero function (formula number 14).
  53.      * The coefficients have been converted to SI units
  54.      */
  55.     private static final double[] CCOEF0 = {
  56.         INV_DEG_TO_INV_RAD * 1.728, INV_DEG_TO_INV_RAD * 0.5411, INV_DEG_TO_INV_RAD * 0.03723,
  57.         INV_DEG_TO_INV_RAD * 0.1815 / KM_TO_M, INV_DEG_TO_INV_RAD * 0.06272 / KM_TO_M, INV_DEG_TO_INV_RAD * 0.011380 / KM_TO_M,
  58.         INV_DEG_TO_INV_RAD * 0.01727 / (KM_TO_M * KM_TO_M), INV_DEG_TO_INV_RAD * 0.008288 / (KM_TO_M * KM_TO_M)
  59.     };

  60.     /** Serializable UID. */
  61.     private static final long serialVersionUID = 20160118L;

  62.     /** station altitude (m). */
  63.     private final double altitude;

  64.     /** minimal elevation angle for the station (rad). */
  65.     private final double thetamin;

  66.     /** minimal elevation angle under free-space propagation (rad). */
  67.     private final double theta0;

  68.     /** elevation where elevation+refraction correction is minimal (near inequality formula number 11 validity domain). */
  69.     private final double elev_star;

  70.     /** refraction correction value where elevation+refraction correction is minimal (near inequality 11 validity domain). */
  71.     private final double refrac_star;

  72.     /** Creates a new default instance.
  73.      * @param altitude altitude of the ground station from which measurement is performed (m)
  74.      */
  75.     public EarthITU453AtmosphereRefraction(final double altitude) {
  76.         this.altitude = altitude;
  77.         thetamin = getMinimalElevation(altitude);
  78.         theta0   = thetamin - getTau(thetamin);

  79.         final UnivariateFunction refrac = new UnivariateFunction() {
  80.             public double value (final double elev) {
  81.                 return elev + getBaseRefraction(elev);
  82.             }
  83.         };

  84.         final double rel = 1.e-5;
  85.         final double abs = 1.e-10;
  86.         final BrentOptimizer optimizer = new BrentOptimizer(rel, abs);

  87.         // Call optimizer
  88.         elev_star = optimizer.optimize(new MaxEval(200),
  89.                                        new UnivariateObjectiveFunction(refrac),
  90.                                        GoalType.MINIMIZE,
  91.                                        new SearchInterval(-FastMath.PI / 30., FastMath.PI / 4)).getPoint();
  92.         refrac_star = getBaseRefraction(elev_star);
  93.     }

  94.     /** Compute the refractive index correction in the case of a typical atmosphere.
  95.      * ITU-R P.834-7, formula number 8, page 3
  96.      * @param alt altitude of the station at the Earth surface (m)
  97.      * @return the refractive index
  98.      */
  99.     private double getRefractiveIndex(final double alt) {

  100.         return 1.0 + DEFAULT_CORRECTION_ACOEF * FastMath.exp(-DEFAULT_CORRECTION_BCOEF * alt);
  101.     }

  102.     /** Compute the minimal elevation angle for a station.
  103.      * ITU-R P.834-7, formula number 10, page 3
  104.      * @param alt altitude of the station at the Earth surface (m)
  105.      * @return the minimal elevation angle (rad)
  106.      */
  107.     private double getMinimalElevation(final double alt) {

  108.         return -FastMath.acos( EARTH_RAY / (EARTH_RAY + alt) * getRefractiveIndex(0.0) / getRefractiveIndex(alt));
  109.     }


  110.     /** Compute the refraction correction in the case of a reference atmosphere.
  111.      * ITU-R P.834-7, formula number 9, page 3
  112.      * @param elevation elevation angle (rad)
  113.      * @return the refraction correction angle (rad)
  114.      */
  115.     private double getTau(final double elevation) {

  116.         final double eld = FastMath.toDegrees(elevation);
  117.         final double tmp0 = CCOEF[0] + CCOEF[1] * eld + CCOEF[2] * eld * eld;
  118.         final double tmp1 = altitude * (CCOEF[3] + CCOEF[4] * eld + CCOEF[5] * eld * eld);
  119.         final double tmp2 = altitude * altitude * CCOEF[6];
  120.         return 1.0 / (tmp0 + tmp1 + tmp2);
  121.     }


  122.     /** Compute the refraction correction in the case of a reference atmosphere.
  123.      * ITU-R P.834-7, formula number 14, page 3
  124.      * @param elevationZero elevation angle (rad)
  125.      * @return the refraction correction angle (rad)
  126.      */

  127.     private double getTauZero(final double elevationZero) {

  128.         final double eld = FastMath.toDegrees(elevationZero);
  129.         final double tmp0 = CCOEF0[0] + CCOEF0[1] * eld + CCOEF0[2] * eld * eld;
  130.         final double tmp1 = altitude * (CCOEF0[3] + CCOEF0[4] * eld + CCOEF0[5] * eld * eld);
  131.         final double tmp2 = altitude * altitude * (CCOEF0[6] + CCOEF0[7] * eld);
  132.         return 1.0 / (tmp0 + tmp1 + tmp2);
  133.     }

  134.     /** Compute the refraction correction in the case of a reference atmosphere without validity domain.
  135.      * The computation is done even if the inequality (formula number 11) is not verified
  136.      * ITU-R P.834-7, formula number 14, page 3
  137.      * @param elevation elevation angle (rad)
  138.      * @return the refraction correction angle (rad)
  139.      */
  140.     private double getBaseRefraction(final double elevation) {
  141.         return getTauZero(elevation);
  142.     }

  143.     /** Get the station minimal elevation angle.
  144.      * @return the minimal elevation angle (rad)
  145.      */
  146.     public double getThetaMin() {
  147.         return thetamin;
  148.     }

  149.     /** Get the station elevation angle under free-space propagation .
  150.      * @return the elevation angle under free-space propagation (rad)
  151.      */
  152.     public double getTheta0() {
  153.         return theta0;
  154.     }

  155.     @Override
  156.     /** {@inheritDoc} */
  157.     // elevation (rad)
  158.     // return refraction correction (rad)
  159.     public double getRefraction(final double elevation) {
  160.         if (elevation < elev_star ) {
  161.             return refrac_star;
  162.         }
  163.         // The validity of the formula is extended for negative elevation,
  164.         // ensuring that the refraction correction angle doesn't make visible a satellite with a too negative elevation
  165.         // elev_star is used instead of thetam (minimal elevation angle).
  166.         return getTauZero(elevation);
  167.     }

  168. }