SBASPropagator.java

  1. /* Copyright 2002-2020 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.propagation.analytical.gnss;

  18. import org.hipparchus.analysis.differentiation.UnivariateDerivative2;
  19. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  20. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  21. import org.orekit.attitudes.AttitudeProvider;
  22. import org.orekit.attitudes.InertialProvider;
  23. import org.orekit.errors.OrekitException;
  24. import org.orekit.errors.OrekitMessages;
  25. import org.orekit.frames.Frame;
  26. import org.orekit.frames.Frames;
  27. import org.orekit.orbits.CartesianOrbit;
  28. import org.orekit.orbits.Orbit;
  29. import org.orekit.propagation.SpacecraftState;
  30. import org.orekit.propagation.analytical.AbstractAnalyticalPropagator;
  31. import org.orekit.time.AbsoluteDate;
  32. import org.orekit.utils.IERSConventions;
  33. import org.orekit.utils.PVCoordinates;

  34. /**
  35.  * This class aims at propagating a SBAS orbit from {@link SBASOrbitalElements}.
  36.  *
  37.  * @see "Tyler Reid, Todd Walker, Per Enge, L1/L5 SBAS MOPS Ephemeris Message to
  38.  *       Support Multiple Orbit Classes, ION ITM, 2013"
  39.  *
  40.  * @author Bryan Cazabonne
  41.  * @since 10.1
  42.  *
  43.  */
  44. public class SBASPropagator extends AbstractAnalyticalPropagator {

  45.     /** The SBAS orbital elements used. */
  46.     private final SBASOrbitalElements sbasOrbit;

  47.     /** The spacecraft mass (kg). */
  48.     private final double mass;

  49.     /** The Earth gravity coefficient used for SBAS propagation. */
  50.     private final double mu;

  51.     /** The ECI frame used for SBAS propagation. */
  52.     private final Frame eci;

  53.     /** The ECEF frame used for SBAS propagation. */
  54.     private final Frame ecef;

  55.     /**
  56.      * This nested class aims at building a SBASPropagator.
  57.      * <p>It implements the classical builder pattern.</p>
  58.      *
  59.      */
  60.     public static class Builder {

  61.         /** The SBAS orbital elements. */
  62.         private final SBASOrbitalElements orbit;

  63.         /** The Earth gravity coefficient used for SBAS propagation. */
  64.         private double mu;

  65.         /** The attitude provider. */
  66.         private AttitudeProvider attitudeProvider;

  67.         /** The mass. */
  68.         private double mass = DEFAULT_MASS;

  69.         /** The ECI frame. */
  70.         private Frame eci  = null;

  71.         /** The ECEF frame. */
  72.         private Frame ecef = null;

  73.         /** Initializes the builder.
  74.          * <p>The SBAS orbital elements is the only requested parameter to build a SBASPropagator.</p>
  75.          * <p>The attitude provider is set by default to the
  76.          *  {@link org.orekit.propagation.Propagator#DEFAULT_LAW DEFAULT_LAW}.<br>
  77.          * The Earth gravity coefficient is set by default to the
  78.          *  {@link org.orekit.propagation.analytical.gnss.SBASOrbitalElements#SBAS_MU SBAS_MU}.<br>
  79.          * The mass is set by default to the
  80.          *  {@link org.orekit.propagation.Propagator#DEFAULT_MASS DEFAULT_MASS}.<br>
  81.          * The ECI frame is set by default to the
  82.          *  {@link org.orekit.frames.Predefined#EME2000 EME2000 frame}.<br>
  83.          * The ECEF frame is set by default to the
  84.          *  {@link org.orekit.frames.Predefined#ITRF_CIO_CONV_2010_SIMPLE_EOP CIO/2010-based ITRF simple EOP}.
  85.          * </p>
  86.          *
  87.          * @param sbasOrbElt the SBAS orbital elements to be used by the SBAS propagator.
  88.          * @param frames     set of reference frames to use to initialize {@link
  89.          *                   #ecef(Frame)}, {@link #eci(Frame)}, and {@link
  90.          *                   #attitudeProvider(AttitudeProvider)}.
  91.          * @see #attitudeProvider(AttitudeProvider provider)
  92.          * @see #mu(double coefficient)
  93.          * @see #mass(double mass)
  94.          * @see #eci(Frame inertial)
  95.          * @see #ecef(Frame bodyFixed)
  96.          */
  97.         public Builder(final SBASOrbitalElements sbasOrbElt, final Frames frames) {
  98.             this.orbit = sbasOrbElt;
  99.             this.eci   = frames.getEME2000();
  100.             this.ecef  = frames.getITRF(IERSConventions.IERS_2010, true);
  101.             this.mu    = SBASOrbitalElements.SBAS_MU;
  102.             this.attitudeProvider = new InertialProvider(eci);
  103.         }

  104.         /** Sets the attitude provider.
  105.          *
  106.          * @param userProvider the attitude provider
  107.          * @return the updated builder
  108.          */
  109.         public Builder attitudeProvider(final AttitudeProvider userProvider) {
  110.             this.attitudeProvider = userProvider;
  111.             return this;
  112.         }

  113.         /** Sets the Earth gravity coefficient.
  114.         *
  115.         * @param coefficient the Earth gravity coefficient
  116.         * @return the updated builder
  117.         */
  118.         public Builder mu(final double coefficient) {
  119.             this.mu = coefficient;
  120.             return this;
  121.         }

  122.         /** Sets the mass.
  123.          *
  124.          * @param userMass the mass (in kg)
  125.          * @return the updated builder
  126.          */
  127.         public Builder mass(final double userMass) {
  128.             this.mass = userMass;
  129.             return this;
  130.         }

  131.         /** Sets the Earth Centered Inertial frame used for propagation.
  132.          *
  133.          * @param inertial the ECI frame
  134.          * @return the updated builder
  135.          */
  136.         public Builder eci(final Frame inertial) {
  137.             this.eci = inertial;
  138.             return this;
  139.         }

  140.         /** Sets the Earth Centered Earth Fixed frame assimilated to the WGS84 ECEF.
  141.          *
  142.          * @param bodyFixed the ECEF frame
  143.          * @return the updated builder
  144.          */
  145.         public Builder ecef(final Frame bodyFixed) {
  146.             this.ecef = bodyFixed;
  147.             return this;
  148.         }

  149.         /** Finalizes the build.
  150.          *
  151.          * @return the built SBASPropagator
  152.          */
  153.         public SBASPropagator build() {
  154.             return new SBASPropagator(this);
  155.         }

  156.     }

  157.     /**
  158.      * Private constructor.
  159.      * @param builder the builder
  160.      */
  161.     private SBASPropagator(final Builder builder) {
  162.         super(builder.attitudeProvider);
  163.         // Stores the SBAS orbital elements
  164.         this.sbasOrbit = builder.orbit;
  165.         // Sets the start date as the date of the orbital elements
  166.         setStartDate(sbasOrbit.getDate());
  167.         // Sets the mu
  168.         this.mu = builder.mu;
  169.         // Sets the mass
  170.         this.mass = builder.mass;
  171.         // Sets the Earth Centered Inertial frame
  172.         this.eci  = builder.eci;
  173.         // Sets the Earth Centered Earth Fixed frame
  174.         this.ecef = builder.ecef;
  175.     }

  176.     /**
  177.      * Gets the PVCoordinates of the GNSS SV in {@link #getECEF() ECEF frame}.
  178.      *
  179.      * <p>The algorithm uses automatic differentiation to compute velocity and
  180.      * acceleration.</p>
  181.      *
  182.      * @param date the computation date
  183.      * @return the GNSS SV PVCoordinates in {@link #getECEF() ECEF frame}
  184.      */
  185.     public PVCoordinates propagateInEcef(final AbsoluteDate date) {
  186.         // Duration from SBAS ephemeris Reference date
  187.         final UnivariateDerivative2 dt = new UnivariateDerivative2( getDT(date), 1.0, 0.0);
  188.         // Satellite coordinates
  189.         final UnivariateDerivative2 x = dt.multiply(dt.multiply(0.5 * sbasOrbit.getXDotDot()).add(sbasOrbit.getXDot())).add(sbasOrbit.getX());
  190.         final UnivariateDerivative2 y = dt.multiply(dt.multiply(0.5 * sbasOrbit.getYDotDot()).add(sbasOrbit.getYDot())).add(sbasOrbit.getY());
  191.         final UnivariateDerivative2 z = dt.multiply(dt.multiply(0.5 * sbasOrbit.getZDotDot()).add(sbasOrbit.getZDot())).add(sbasOrbit.getZ());
  192.         // Returns the Earth-fixed coordinates
  193.         final FieldVector3D<UnivariateDerivative2> positionwithDerivatives =
  194.                         new FieldVector3D<>(x, y, z);
  195.         return new PVCoordinates(new Vector3D(positionwithDerivatives.getX().getValue(),
  196.                                               positionwithDerivatives.getY().getValue(),
  197.                                               positionwithDerivatives.getZ().getValue()),
  198.                                  new Vector3D(positionwithDerivatives.getX().getFirstDerivative(),
  199.                                               positionwithDerivatives.getY().getFirstDerivative(),
  200.                                               positionwithDerivatives.getZ().getFirstDerivative()),
  201.                                  new Vector3D(positionwithDerivatives.getX().getSecondDerivative(),
  202.                                               positionwithDerivatives.getY().getSecondDerivative(),
  203.                                               positionwithDerivatives.getZ().getSecondDerivative()));
  204.     }

  205.     /** {@inheritDoc} */
  206.     protected Orbit propagateOrbit(final AbsoluteDate date) {
  207.         // Gets the PVCoordinates in ECEF frame
  208.         final PVCoordinates pvaInECEF = propagateInEcef(date);
  209.         // Transforms the PVCoordinates to ECI frame
  210.         final PVCoordinates pvaInECI = ecef.getTransformTo(eci, date).transformPVCoordinates(pvaInECEF);
  211.         // Returns the Cartesian orbit
  212.         return new CartesianOrbit(pvaInECI, eci, date, mu);
  213.     }

  214.     /**
  215.      * Get the Earth gravity coefficient used for SBAS propagation.
  216.      * @return the Earth gravity coefficient.
  217.      */
  218.     public double getMU() {
  219.         return mu;
  220.     }

  221.     /**
  222.      * Gets the Earth Centered Inertial frame used to propagate the orbit.
  223.      *
  224.      * @return the ECI frame
  225.      */
  226.     public Frame getECI() {
  227.         return eci;
  228.     }

  229.     /**
  230.      * Gets the Earth Centered Earth Fixed frame used to propagate GNSS orbits.
  231.      *
  232.      * @return the ECEF frame
  233.      */
  234.     public Frame getECEF() {
  235.         return ecef;
  236.     }

  237.     /**
  238.      * Get the underlying SBAS orbital elements.
  239.      *
  240.      * @return the underlying SBAS orbital elements
  241.      */
  242.     public SBASOrbitalElements getSBASOrbitalElements() {
  243.         return sbasOrbit;
  244.     }

  245.     /** {@inheritDoc} */
  246.     public Frame getFrame() {
  247.         return eci;
  248.     }

  249.     /** {@inheritDoc} */
  250.     public void resetInitialState(final SpacecraftState state) {
  251.         throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
  252.     }

  253.     /** {@inheritDoc} */
  254.     protected double getMass(final AbsoluteDate date) {
  255.         return mass;
  256.     }

  257.     /** {@inheritDoc} */
  258.     protected void resetIntermediateState(final SpacecraftState state, final boolean forward) {
  259.         throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
  260.     }

  261.     /** Get the duration from SBAS Reference epoch.
  262.      * @param date the considered date
  263.      * @return the duration from SBAS orbit Reference epoch (s)
  264.      */
  265.     private double getDT(final AbsoluteDate date) {
  266.         // Time from ephemeris reference epoch
  267.         return date.durationFrom(sbasOrbit.getDate());
  268.     }

  269. }