1   /* Copyright 2002-2021 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  
19  import org.hipparchus.analysis.differentiation.UnivariateDerivative2;
20  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
21  import org.hipparchus.geometry.euclidean.threed.Vector3D;
22  import org.orekit.attitudes.AttitudeProvider;
23  import org.orekit.errors.OrekitException;
24  import org.orekit.errors.OrekitMessages;
25  import org.orekit.frames.Frame;
26  import org.orekit.orbits.CartesianOrbit;
27  import org.orekit.orbits.Orbit;
28  import org.orekit.propagation.SpacecraftState;
29  import org.orekit.propagation.analytical.AbstractAnalyticalPropagator;
30  import org.orekit.propagation.analytical.gnss.data.SBASOrbitalElements;
31  import org.orekit.time.AbsoluteDate;
32  import org.orekit.utils.PVCoordinates;
33  
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  
46      /** The SBAS orbital elements used. */
47      private final SBASOrbitalElements sbasOrbit;
48  
49      /** The spacecraft mass (kg). */
50      private final double mass;
51  
52      /** The Earth gravity coefficient used for SBAS propagation. */
53      private final double mu;
54  
55      /** The ECI frame used for SBAS propagation. */
56      private final Frame eci;
57  
58      /** The ECEF frame used for SBAS propagation. */
59      private final Frame ecef;
60  
61      /**
62       * Private constructor.
63       * @param sbasOrbit Glonass orbital elements
64       * @param eci Earth Centered Inertial frame
65       * @param ecef Earth Centered Earth Fixed frame
66       * @param provider Attitude provider
67       * @param mass Satellite mass (kg)
68       * @param mu Earth's gravity coefficient used for SBAS propagation
69       */
70      SBASPropagator(final SBASOrbitalElements sbasOrbit, final Frame eci,
71                     final Frame ecef, final AttitudeProvider provider,
72                     final double mass, final double mu) {
73          super(provider);
74          // Stores the SBAS orbital elements
75          this.sbasOrbit = sbasOrbit;
76          // Sets the start date as the date of the orbital elements
77          setStartDate(sbasOrbit.getDate());
78          // Sets the mu
79          this.mu = mu;
80          // Sets the mass
81          this.mass = mass;
82          // Sets the Earth Centered Inertial frame
83          this.eci  = eci;
84          // Sets the Earth Centered Earth Fixed frame
85          this.ecef = ecef;
86      }
87  
88      /**
89       * Gets the PVCoordinates of the GNSS SV in {@link #getECEF() ECEF frame}.
90       *
91       * <p>The algorithm uses automatic differentiation to compute velocity and
92       * acceleration.</p>
93       *
94       * @param date the computation date
95       * @return the GNSS SV PVCoordinates in {@link #getECEF() ECEF frame}
96       */
97      public PVCoordinates propagateInEcef(final AbsoluteDate date) {
98          // Duration from SBAS ephemeris Reference date
99          final UnivariateDerivative2 dt = new UnivariateDerivative2(getDT(date), 1.0, 0.0);
100         // Satellite coordinates
101         final UnivariateDerivative2 x = dt.multiply(dt.multiply(0.5 * sbasOrbit.getXDotDot()).add(sbasOrbit.getXDot())).add(sbasOrbit.getX());
102         final UnivariateDerivative2 y = dt.multiply(dt.multiply(0.5 * sbasOrbit.getYDotDot()).add(sbasOrbit.getYDot())).add(sbasOrbit.getY());
103         final UnivariateDerivative2 z = dt.multiply(dt.multiply(0.5 * sbasOrbit.getZDotDot()).add(sbasOrbit.getZDot())).add(sbasOrbit.getZ());
104         // Returns the Earth-fixed coordinates
105         final FieldVector3D<UnivariateDerivative2> positionwithDerivatives =
106                         new FieldVector3D<>(x, y, z);
107         return new PVCoordinates(new Vector3D(positionwithDerivatives.getX().getValue(),
108                                               positionwithDerivatives.getY().getValue(),
109                                               positionwithDerivatives.getZ().getValue()),
110                                  new Vector3D(positionwithDerivatives.getX().getFirstDerivative(),
111                                               positionwithDerivatives.getY().getFirstDerivative(),
112                                               positionwithDerivatives.getZ().getFirstDerivative()),
113                                  new Vector3D(positionwithDerivatives.getX().getSecondDerivative(),
114                                               positionwithDerivatives.getY().getSecondDerivative(),
115                                               positionwithDerivatives.getZ().getSecondDerivative()));
116     }
117 
118     /** {@inheritDoc} */
119     protected Orbit propagateOrbit(final AbsoluteDate date) {
120         // Gets the PVCoordinates in ECEF frame
121         final PVCoordinates pvaInECEF = propagateInEcef(date);
122         // Transforms the PVCoordinates to ECI frame
123         final PVCoordinates pvaInECI = ecef.getTransformTo(eci, date).transformPVCoordinates(pvaInECEF);
124         // Returns the Cartesian orbit
125         return new CartesianOrbit(pvaInECI, eci, date, mu);
126     }
127 
128     /**
129      * Get the Earth gravity coefficient used for SBAS propagation.
130      * @return the Earth gravity coefficient.
131      */
132     public double getMU() {
133         return mu;
134     }
135 
136     /**
137      * Gets the Earth Centered Inertial frame used to propagate the orbit.
138      *
139      * @return the ECI frame
140      */
141     public Frame getECI() {
142         return eci;
143     }
144 
145     /**
146      * Gets the Earth Centered Earth Fixed frame used to propagate GNSS orbits.
147      *
148      * @return the ECEF frame
149      */
150     public Frame getECEF() {
151         return ecef;
152     }
153 
154     /**
155      * Get the underlying SBAS orbital elements.
156      *
157      * @return the underlying SBAS orbital elements
158      */
159     public SBASOrbitalElements getSBASOrbitalElements() {
160         return sbasOrbit;
161     }
162 
163     /** {@inheritDoc} */
164     public Frame getFrame() {
165         return eci;
166     }
167 
168     /** {@inheritDoc} */
169     public void resetInitialState(final SpacecraftState state) {
170         throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
171     }
172 
173     /** {@inheritDoc} */
174     protected double getMass(final AbsoluteDate date) {
175         return mass;
176     }
177 
178     /** {@inheritDoc} */
179     protected void resetIntermediateState(final SpacecraftState state, final boolean forward) {
180         throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
181     }
182 
183     /** Get the duration from SBAS Reference epoch.
184      * @param date the considered date
185      * @return the duration from SBAS orbit Reference epoch (s)
186      */
187     private double getDT(final AbsoluteDate date) {
188         // Time from ephemeris reference epoch
189         return date.durationFrom(sbasOrbit.getDate());
190     }
191 
192 }