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.propagation.analytical.gnss.data;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.hipparchus.util.FastMath;
22  import org.orekit.gnss.SatelliteSystem;
23  import org.orekit.propagation.analytical.gnss.GNSSPropagator;
24  import org.orekit.time.AbsoluteDate;
25  import org.orekit.time.GNSSDate;
26  import org.orekit.time.TimeScales;
27  import org.orekit.time.TimeStamped;
28  import org.orekit.utils.ParameterDriver;
29  
30  /** This class provides the minimal set of orbital elements needed by the {@link GNSSPropagator}.
31   * <p>
32   * The parameters are split in two groups: Keplerian orbital parameters and non-Keplerian
33   * evolution parameters. All parameters can be updated as they are all instances of
34   * {@link ParameterDriver}. Only the non-Keplerian parameters are returned in the
35   * {@link #getParametersDrivers()} method, the Keplerian orbital parameters must
36   * be accessed independently. These groups ensure proper separate computation of
37   * state transition matrix and Jacobian matrix by {@link GNSSPropagator}.
38   * </p>
39   * @param <O> type of the orbital elements
40   * @since 13.0
41   * @author Pascal Parraud
42   * @author Luc Maisonobe
43  */
44  public abstract class GNSSOrbitalElements<O extends GNSSOrbitalElements<O>>
45      extends GNSSOrbitalElementsDriversProvider
46      implements TimeStamped {
47  
48      /** Name for semi major axis parameter. */
49      public static final String SEMI_MAJOR_AXIS = "GnssSemiMajorAxis";
50  
51      /** Name for eccentricity parameter. */
52      public static final String ECCENTRICITY = "GnssEccentricity";
53  
54      /** Name for inclination at reference time parameter. */
55      public static final String INCLINATION = "GnssInclination";
56  
57      /** Name for argument of perigee parameter. */
58      public static final String ARGUMENT_OF_PERIGEE = "GnssPerigeeArgument";
59  
60      /** Name for longitude of ascending node at weekly epoch parameter. */
61      public static final String NODE_LONGITUDE = "GnssNodeLongitude";
62  
63      /** Name for mean anomaly at reference time parameter. */
64      public static final String MEAN_ANOMALY = "GnssMeanAnomaly";
65  
66      /** Earth's universal gravitational parameter. */
67      private final double mu;
68  
69      /** Reference epoch. */
70      private AbsoluteDate date;
71  
72      /** Semi-Major Axis (m). */
73      private final ParameterDriver smaDriver;
74  
75      /** Eccentricity. */
76      private final ParameterDriver eccDriver;
77  
78      /** Inclination angle at reference time (rad). */
79      private final ParameterDriver i0Driver;
80  
81      /** Argument of perigee (rad). */
82      private final ParameterDriver aopDriver;
83  
84      /** Longitude of ascending node of orbit plane at weekly epoch (rad). */
85      private final ParameterDriver om0Driver;
86  
87      /** Mean anomaly at reference time (rad). */
88      private final ParameterDriver anomDriver;
89  
90      /**
91       * Constructor.
92       * @param mu              Earth's universal gravitational parameter
93       * @param angularVelocity mean angular velocity of the Earth for the GNSS model
94       * @param weeksInCycle    number of weeks in the GNSS cycle
95       * @param timeScales      known time scales
96       * @param system          satellite system to consider for interpreting week number
97       *                        (may be different from real system, for example in Rinex nav, weeks
98       *                        are always according to GPS)
99       */
100     protected GNSSOrbitalElements(final double mu, final double angularVelocity, final int weeksInCycle,
101                                   final TimeScales timeScales, final SatelliteSystem system) {
102 
103         super(angularVelocity, weeksInCycle, timeScales, system);
104 
105         // immutable field
106         this.mu         = mu;
107 
108         // fields controlled by parameter drivers for Keplerian orbital elements
109         this.smaDriver  = createDriver(SEMI_MAJOR_AXIS);
110         this.eccDriver  = createDriver(ECCENTRICITY);
111         this.i0Driver   = createDriver(INCLINATION);
112         this.aopDriver  = createDriver(ARGUMENT_OF_PERIGEE);
113         this.om0Driver  = createDriver(NODE_LONGITUDE);
114         this.anomDriver = createDriver(MEAN_ANOMALY);
115 
116     }
117 
118     /** Constructor from field instance.
119      * @param <T> type of the field elements
120      * @param <A> type of the orbital elements (non-field version)
121      * @param original regular field instance
122      */
123     protected <T extends CalculusFieldElement<T>,
124                A extends GNSSOrbitalElements<A>> GNSSOrbitalElements(final FieldGnssOrbitalElements<T, A> original) {
125         this(original.getMu().getReal(), original.getAngularVelocity(), original.getWeeksInCycle(),
126              original.getTimeScales(), original.getSystem());
127 
128         // non-Keperian parameters
129         setPRN(original.getPRN());
130         setWeek(original.getWeek());
131         setTime(original.getTime());
132         setIDot(original.getIDot());
133         setOmegaDot(original.getOmegaDot());
134         setCuc(original.getCuc());
135         setCus(original.getCus());
136         setCrc(original.getCrc());
137         setCrs(original.getCrs());
138         setCic(original.getCic());
139         setCis(original.getCis());
140 
141         // Keplerian orbital elements
142         setSma(original.getSma().getReal());
143         setE(original.getE().getReal());
144         setI0(original.getI0().getReal());
145         setPa(original.getPa().getReal());
146         setOmega0(original.getOmega0().getReal());
147         setM0(original.getM0().getReal());
148 
149         // copy selection settings
150         copySelectionSettings(original);
151 
152     }
153 
154     /** Create a field version of the instance.
155      * @param <T> type of the field elements
156      * @param <F> type of the orbital elements (field version)
157      * @param field field to which elements belong
158      * @return field version of the instance
159      */
160     public abstract <T extends CalculusFieldElement<T>, F extends FieldGnssOrbitalElements<T, O>>
161         F toField(Field<T> field);
162 
163     /** {@inheritDoc} */
164     protected void setGnssDate(final GNSSDate gnssDate) {
165         this.date = gnssDate.getDate();
166     }
167 
168     /** {@inheritDoc} */
169     @Override
170     public AbsoluteDate getDate() {
171         return date;
172     }
173 
174     /** Get the Earth's universal gravitational parameter.
175      * @return the Earth's universal gravitational parameter
176      */
177     public double getMu() {
178         return mu;
179     }
180 
181     /** Get semi-major axis.
182      * @return driver for the semi-major axis (m)
183      */
184     public ParameterDriver getSmaDriver() {
185         return smaDriver;
186     }
187 
188     /** Get semi-major axis.
189      * @return semi-major axis (m)
190      */
191     public double getSma() {
192         return getSmaDriver().getValue();
193     }
194 
195     /** Set semi-major axis.
196      * @param sma demi-major axis (m)
197      */
198     public void setSma(final double sma) {
199         getSmaDriver().setValue(sma);
200     }
201 
202     /** Getter for the change rate in semi-major axis.
203      * <p>
204      * This value is non-zero only in civilian navigation messages
205      * </p>
206      * @return the change rate in semi-major axis
207      * @since 13.0
208      */
209     public double getADot() {
210         return 0;
211     }
212 
213     /** Get the computed mean motion n₀.
214      * @return the computed mean motion n₀ (rad/s)
215      * @since 13.0
216      */
217     public double getMeanMotion0() {
218         final double absA = FastMath.abs(getSma());
219         return FastMath.sqrt(getMu() / absA) / absA;
220     }
221 
222     /** Getter for the delta of satellite mean motion.
223      * <p>
224      * This value is non-zero only in navigation messages
225      * </p>
226      * @return delta of satellite mean motion
227      * @since 13.0
228      */
229     public double getDeltaN0() {
230         return 0;
231     }
232 
233     /** Getter for change rate in Δn₀.
234      * <p>
235      * This value is non-zero only in civilian navigation messages
236      * </p>
237      * @return change rate in Δn₀
238      * @since 13.0
239      */
240     public double getDeltaN0Dot() {
241         return 0;
242     }
243 
244     /** Get the driver for the eccentricity.
245      * @return driver for the eccentricity
246      */
247     public ParameterDriver getEDriver() {
248         return eccDriver;
249     }
250 
251     /** Get eccentricity.
252      * @return eccentricity
253      */
254     public double getE() {
255         return getEDriver().getValue();
256     }
257 
258     /** Set eccentricity.
259      * @param e eccentricity
260      */
261     public void setE(final double e) {
262         getEDriver().setValue(e);
263     }
264 
265     /** Get the driver for the inclination angle at reference time.
266      * @return driver for the inclination angle at reference time (rad)
267      */
268     public ParameterDriver getI0Driver() {
269         return i0Driver;
270     }
271 
272     /** Get the inclination angle at reference time.
273      * @return inclination angle at reference time (rad)
274      */
275     public double getI0() {
276         return getI0Driver().getValue();
277     }
278 
279     /** Set inclination angle at reference time.
280      * @param i0 inclination angle at reference time (rad)
281      */
282     public void setI0(final double i0) {
283         getI0Driver().setValue(i0);
284     }
285 
286     /** Get the driver for the longitude of ascending node of orbit plane at weekly epoch.
287      * @return driver for the longitude of ascending node of orbit plane at weekly epoch (rad)
288      */
289     public ParameterDriver getOmega0Driver() {
290         return om0Driver;
291     }
292 
293     /** Get longitude of ascending node of orbit plane at weekly epoch.
294      * @return longitude of ascending node of orbit plane at weekly epoch (rad)
295      */
296     public double getOmega0() {
297         return getOmega0Driver().getValue();
298     }
299 
300     /** Set longitude of ascending node of orbit plane at weekly epoch.
301      * @param om0 longitude of ascending node of orbit plane at weekly epoch (rad)
302      */
303     public void setOmega0(final double om0) {
304         getOmega0Driver().setValue(om0);
305     }
306 
307     /** Get the driver for the argument of perigee.
308      * @return driver for the argument of perigee (rad)
309      */
310     public ParameterDriver getPaDriver() {
311         return aopDriver;
312     }
313 
314     /** Get argument of perigee.
315      * @return argument of perigee (rad)
316      */
317     public double getPa() {
318         return getPaDriver().getValue();
319     }
320 
321     /** Set argument of perigee.
322      * @param aop argument of perigee (rad)
323      */
324     public void setPa(final double aop) {
325         getPaDriver().setValue(aop);
326     }
327 
328     /** Get the driver for the mean anomaly at reference time.
329      * @return driver for the mean anomaly at reference time (rad)
330      */
331     public ParameterDriver getM0Driver() {
332         return anomDriver;
333     }
334 
335     /** Get mean anomaly at reference time.
336      * @return mean anomaly at reference time (rad)
337      */
338     public double getM0() {
339         return getM0Driver().getValue();
340     }
341 
342     /** Set mean anomaly at reference time.
343      * @param anom mean anomaly at reference time (rad)
344      */
345     public void setM0(final double anom) {
346         getM0Driver().setValue(anom);
347     }
348 
349 }