ReferenceEllipsoid.java

  1. /* Contributed in the public domain.
  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;

  18. import org.hipparchus.util.FastMath;
  19. import org.orekit.bodies.OneAxisEllipsoid;
  20. import org.orekit.frames.Frame;
  21. import org.orekit.utils.Constants;

  22. /**
  23.  * A Reference Ellipsoid for use in geodesy. The ellipsoid defines an
  24.  * ellipsoidal potential called the normal potential, and its gradient, normal
  25.  * gravity.
  26.  *
  27.  * <p> These parameters are needed to define the normal potential:
  28.  *
  29.  *
  30.  * <ul> <li>a, semi-major axis</li>
  31.  *
  32.  * <li>f, flattening</li>
  33.  *
  34.  * <li>GM, the gravitational parameter</li>
  35.  *
  36.  * <li>&omega;, the spin rate</li> </ul>
  37.  *
  38.  * <p> References:
  39.  *
  40.  * <ol> <li>Martin Losch, Verena Seufer. How to Compute Geoid Undulations (Geoid
  41.  * Height Relative to a Given Reference Ellipsoid) from Spherical Harmonic
  42.  * Coefficients for Satellite Altimetry Applications. , 2003. <a
  43.  * href="http://mitgcm.org/~mlosch/geoidcookbook.pdf" >mitgcm.org/~mlosch/geoidcookbook.pdf</a></li>
  44.  *
  45.  * <li>Weikko A. Heiskanen, Helmut Moritz. Physical Geodesy. W. H. Freeman and
  46.  * Company, 1967. (especially sections 2.13 and equation 2-144)</li>
  47.  *
  48.  * <li>Department of Defense World Geodetic System 1984. 2000. NIMA TR 8350.2
  49.  * Third Edition, Amendment 1.</li> </ol>
  50.  *
  51.  * @author Evan Ward
  52.  * @author Guylaine Prat
  53.  */
  54. public class ReferenceEllipsoid extends OneAxisEllipsoid implements EarthShape {

  55.     /** uid is date of last modification. */
  56.     private static final long serialVersionUID = 20150311L;

  57.     /** the gravitational parameter of the ellipsoid, in m<sup>3</sup>/s<sup>2</sup>. */
  58.     private final double GM;
  59.     /** the rotation rate of the ellipsoid, in rad/s. */
  60.     private final double spin;

  61.     /**
  62.      * Creates a new geodetic Reference Ellipsoid from four defining
  63.      * parameters.
  64.      *
  65.      * @param ae        Equatorial radius, in m
  66.      * @param f         flattening of the ellipsoid.
  67.      * @param bodyFrame the frame to attach to the ellipsoid. The origin is at
  68.      *                  the center of mass, the z axis is the minor axis.
  69.      * @param GM        gravitational parameter, in m<sup>3</sup>/s<sup>2</sup>
  70.      * @param spin      &omega; in rad/s
  71.      */
  72.     public ReferenceEllipsoid(final double ae,
  73.                               final double f,
  74.                               final Frame bodyFrame,
  75.                               final double GM,
  76.                               final double spin) {
  77.         super(ae, f, bodyFrame);
  78.         this.GM = GM;
  79.         this.spin = spin;
  80.     }

  81.     /**
  82.      * Gets the gravitational parameter that is part of the definition of the
  83.      * reference ellipsoid.
  84.      *
  85.      * @return GM in m<sup>3</sup>/s<sup>2</sup>
  86.      */
  87.     public double getGM() {
  88.         return this.GM;
  89.     }

  90.     /**
  91.      * Gets the rotation of the ellipsoid about its axis.
  92.      *
  93.      * @return &omega; in rad/s
  94.      */
  95.     public double getSpin() {
  96.         return this.spin;
  97.     }

  98.     /**
  99.      * Get the radius of this ellipsoid at the poles.
  100.      *
  101.      * @return the polar radius, in meters
  102.      * @see #getEquatorialRadius()
  103.      */
  104.     public double getPolarRadius() {
  105.         // use the definition of flattening: f = (a-b)/a
  106.         final double a = this.getEquatorialRadius();
  107.         final double f = this.getFlattening();
  108.         return a - f * a;
  109.     }

  110.     /**
  111.      * Gets the normal gravity, that is gravity just due to the reference
  112.      * ellipsoid's potential. The normal gravity only depends on latitude
  113.      * because the ellipsoid is axis symmetric.
  114.      *
  115.      * <p> The normal gravity is a vector, having both magnitude and direction.
  116.      * This method only give the magnitude.
  117.      *
  118.      * @param latitude geodetic latitude, in radians. That is the angle between
  119.      *                 the local normal on the ellipsoid and the equatorial
  120.      *                 plane.
  121.      * @return the normal gravity, &gamma;, at the given latitude in
  122.      * m/s<sup>2</sup>. This is the acceleration felt by a mass at rest on the
  123.      * surface of the reference ellipsoid.
  124.      */
  125.     public double getNormalGravity(final double latitude) {
  126.         /*
  127.          * Uses the equations from [2] as compiled in [1]. See Class comment.
  128.          */

  129.         final double a  = this.getEquatorialRadius();
  130.         final double f  = this.getFlattening();

  131.         // define derived constants, move to constructor for more speed
  132.         // semi-minor axis
  133.         final double b = a * (1 - f);
  134.         final double a2 = a * a;
  135.         final double b2 = b * b;
  136.         // linear eccentricity
  137.         final double E = FastMath.sqrt(a2 - b2);
  138.         // first numerical eccentricity
  139.         final double e = E / a;
  140.         // second numerical eccentricity
  141.         final double eprime = E / b;
  142.         // an abbreviation for a common term
  143.         final double m = this.spin * this.spin * a2 * b / this.GM;
  144.         // gravity at equator
  145.         final double ya = this.GM / (a * b) *
  146.                 (1 - 3. / 2. * m - 3. / 14. * eprime * m);
  147.         // gravity at the poles
  148.         final double yb = this.GM / a2 * (1 + m + 3. / 7. * eprime * m);
  149.         // another abbreviation for a common term
  150.         final double kappa = (b * yb - a * ya) / (a * ya);

  151.         // calculate normal gravity at the given latitude.
  152.         final double sin  = FastMath.sin(latitude);
  153.         final double sin2 = sin * sin;
  154.         return ya * (1 + kappa * sin2) / FastMath.sqrt(1 - e * e * sin2);
  155.     }

  156.     /**
  157.      * Get the fully normalized coefficient C<sub>2n,0</sub> for the normal
  158.      * gravity potential.
  159.      *
  160.      * @param n index in C<sub>2n,0</sub>, n &gt;= 1.
  161.      * @return normalized C<sub>2n,0</sub> of the ellipsoid
  162.      * @see "Department of Defense World Geodetic System 1984. 2000. NIMA TR
  163.      * 8350.2 Third Edition, Amendment 1."
  164.      * @see "DMA TR 8350.2. 1984."
  165.      */
  166.     public double getC2n0(final int n) {
  167.         // parameter check
  168.         if (n < 1) {
  169.             throw new IllegalArgumentException("Expected n < 1, got n=" + n);
  170.         }

  171.         final double a = this.getEquatorialRadius();
  172.         final double f = this.getFlattening();
  173.         // define derived constants, move to constructor for more speed
  174.         // semi-minor axis
  175.         final double b = a * (1 - f);
  176.         final double a2 = a * a;
  177.         final double b2 = b * b;
  178.         // linear eccentricity
  179.         final double E = FastMath.sqrt(a2 - b2);
  180.         // first numerical eccentricity
  181.         final double e = E / a;
  182.         // an abbreviation for a common term
  183.         final double m = this.spin * this.spin * a2 * b / this.GM;

  184.         /*
  185.          * derive C2 using a linear approximation, good to ~1e-9, eq 2.118 in
  186.          * Heiskanen & Moritz[2]. See comment for ReferenceEllipsoid
  187.          */
  188.         final double J2 = 2. / 3. * f - 1. / 3. * m - 1. / 3. * f * f + 2. / 21. * f * m;
  189.         final double C2 = -J2 / FastMath.sqrt(5);

  190.         // eq 3-62 in chapter 3 of DMA TR 8350.2, calculated by scaling C2,0
  191.         return (((n & 0x1) == 0) ? 3 : -3) * FastMath.pow(e, 2 * n) *
  192.                 (1 - n - FastMath.pow(5, 3. / 2.) * n * C2 / (e * e)) /
  193.                 ((2 * n + 1) * (2 * n + 3) * FastMath.sqrt(4 * n + 1));
  194.     }

  195.     @Override
  196.     public ReferenceEllipsoid getEllipsoid() {
  197.         return this;
  198.     }

  199.     /**
  200.      * Get the WGS84 ellipsoid, attached to the given body frame.
  201.      *
  202.      * @param bodyFrame the earth centered fixed frame
  203.      * @return a WGS84 reference ellipsoid
  204.      */
  205.     public static ReferenceEllipsoid getWgs84(final Frame bodyFrame) {
  206.         return new ReferenceEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
  207.                 Constants.WGS84_EARTH_FLATTENING, bodyFrame,
  208.                 Constants.WGS84_EARTH_MU,
  209.                 Constants.WGS84_EARTH_ANGULAR_VELOCITY);
  210.     }

  211.     /**
  212.      * Get the GRS80 ellipsoid, attached to the given body frame.
  213.      *
  214.      * @param bodyFrame the earth centered fixed frame
  215.      * @return a GRS80 reference ellipsoid
  216.      */
  217.     public static ReferenceEllipsoid getGrs80(final Frame bodyFrame) {
  218.         return new ReferenceEllipsoid(
  219.                 Constants.GRS80_EARTH_EQUATORIAL_RADIUS,
  220.                 Constants.GRS80_EARTH_FLATTENING,
  221.                 bodyFrame,
  222.                 Constants.GRS80_EARTH_MU,
  223.                 Constants.GRS80_EARTH_ANGULAR_VELOCITY
  224.         );
  225.     }

  226.     /**
  227.      * Get the IERS96 ellipsoid, attached to the given body frame.
  228.      *
  229.      * @param bodyFrame the earth centered fixed frame
  230.      * @return an IERS96 reference ellipsoid
  231.      */
  232.     public static ReferenceEllipsoid getIers96(final Frame bodyFrame) {
  233.         return new ReferenceEllipsoid(Constants.IERS96_EARTH_EQUATORIAL_RADIUS,
  234.                 Constants.IERS96_EARTH_FLATTENING, bodyFrame,
  235.                 Constants.IERS96_EARTH_MU,
  236.                 Constants.IERS96_EARTH_ANGULAR_VELOCITY);
  237.     }

  238.     /**
  239.      * Get the IERS2003 ellipsoid, attached to the given body frame.
  240.      *
  241.      * @param bodyFrame the earth centered fixed frame
  242.      * @return an IERS2003 reference ellipsoid
  243.      */
  244.     public static ReferenceEllipsoid getIers2003(final Frame bodyFrame) {
  245.         return new ReferenceEllipsoid(Constants.IERS2003_EARTH_EQUATORIAL_RADIUS,
  246.                 Constants.IERS2003_EARTH_FLATTENING, bodyFrame,
  247.                 Constants.IERS2003_EARTH_MU,
  248.                 Constants.IERS2003_EARTH_ANGULAR_VELOCITY);
  249.     }

  250.     /**
  251.      * Get the IERS2010 ellipsoid, attached to the given body frame.
  252.      *
  253.      * @param bodyFrame the earth centered fixed frame
  254.      * @return an IERS2010 reference ellipsoid
  255.      */
  256.     public static ReferenceEllipsoid getIers2010(final Frame bodyFrame) {
  257.         return new ReferenceEllipsoid(Constants.IERS2010_EARTH_EQUATORIAL_RADIUS,
  258.                 Constants.IERS2010_EARTH_FLATTENING, bodyFrame,
  259.                 Constants.IERS2010_EARTH_MU,
  260.                 Constants.IERS2010_EARTH_ANGULAR_VELOCITY);
  261.     }
  262. }