1   /* Copyright 2022-2026 Luc Maisonobe
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 java.util.function.Function;
20  
21  import org.hipparchus.CalculusFieldElement;
22  import org.hipparchus.util.MathArrays;
23  import org.orekit.orbits.FieldKeplerianOrbit;
24  import org.orekit.orbits.FieldOrbitalState;
25  import org.orekit.time.FieldAbsoluteDate;
26  import org.orekit.time.FieldGNSSDate;
27  import org.orekit.time.TimeScales;
28  
29  /** This class provides the minimal set of orbital elements needed by the {@link
30   * org.orekit.propagation.analytical.gnss.FieldGnssPropagator}.
31   * @param <T> type of the field elements
32   * @param <O> type of the orbital elements (non-field version)
33   * @since 13.0
34   * @author Luc Maisonobe
35  */
36  public abstract class FieldGnssOrbitalElements<T extends CalculusFieldElement<T>,
37                                                 O extends GNSSOrbitalElements<O>>
38      implements FieldOrbitalState<T>, FieldGNSSClockElements<T> {
39  
40      /** Mean angular velocity of the Earth for the GNSS model. */
41      private final double angularVelocity;
42  
43      /** Duration of the GNSS cycle in weeks. */
44      private final int weeksInCycle;
45  
46      /** Duration of the GNSS cycle in seconds. */
47      private final double cycleDuration;
48  
49      /** Known time scales. */
50      private final TimeScales timeScales;
51  
52      /** Message type (null if not a navigation message). */
53      private final String type;
54  
55      /** PRN number of the satellite. */
56      private final int prn;
57  
58      /** Time of ephemeris.
59       * @since 14.0
60       */
61      private final FieldGNSSDate<T> toe;
62  
63      /** Orbit. */
64      private final FieldKeplerianOrbit<T> orbit;
65  
66      /** Change rate in semi-major axis (m/s).
67       * @since 14.0
68       */
69      private final T aDot;
70  
71      /** Delta of satellite mean motion.
72       * @since 14.0
73       */
74      private final T deltaN0;
75  
76      /** Change rate in Δn₀.
77       * @since 14.0
78       */
79      private final T deltaN0Dot;
80  
81      /** Inclination rate (rad/s). */
82      private final T iDot;
83  
84      /** Rate of right ascension (rad/s). */
85      private final T omegaDot;
86  
87      /** Amplitude of the cosine harmonic correction term to the argument of latitude. */
88      private final T cuc;
89  
90      /** Amplitude of the sine harmonic correction term to the argument of latitude. */
91      private final T cus;
92  
93      /** Amplitude of the cosine harmonic correction term to the orbit radius. */
94      private final T crc;
95  
96      /** Amplitude of the sine harmonic correction term to the orbit radius. */
97      private final T crs;
98  
99      /** Amplitude of the cosine harmonic correction term to the inclination. */
100     private final T cic;
101 
102     /** Amplitude of the sine harmonic correction term to the inclination. */
103     private final T cis;
104 
105     /** SV zero-th order clock correction (s). */
106     private final T af0;
107 
108     /** SV first order clock correction (s/s). */
109     private final T af1;
110 
111     /** SV second order clock correction (s/s²). */
112     private final T af2;
113 
114     /** Time of clock.
115      * @since 14.0
116      */
117     private final FieldGNSSDate<T> toc;
118 
119     /** Group delay differential TGD for L1-L2 correction. */
120     private final T tgd;
121 
122     /** Creates a new instance.
123      * @param angularVelocity mean angular velocity of the Earth for the GNSS model
124      * @param weeksInCycle    number of weeks in the GNSS cycle
125      * @param timeScales      known time scales
126      * @param type            type (null if not a navigation message)
127      * @param prn             PRN number of the satellite
128      * @param toe             time of ephemeris (<em>must</em> be consistent with {@code orbit})
129      * @param orbit           Keplerian orbit in Earth-frozen frame
130      * @param aDot            change rate in semi-major axis (m/s)
131      * @param deltaN0         delta of satellite mean motion
132      * @param deltaN0Dot      change rate in Δn₀
133      * @param iDot            inclination rate (rad/s)
134      * @param omegaDot        rate of right ascension (rad/s)
135      * @param cuc             amplitude of the cosine harmonic correction term to the argument of latitude
136      * @param cus             amplitude of the sine harmonic correction term to the argument of latitude
137      * @param crc             amplitude of the cosine harmonic correction term to the orbit radius
138      * @param crs             amplitude of the sine harmonic correction term to the orbit radius
139      * @param cic             amplitude of the cosine harmonic correction term to the inclination
140      * @param cis             amplitude of the sine harmonic correction term to the inclination
141      * @param af0             zero-th order clock correction (s)
142      * @param af1             first order clock correction (s/s)
143      * @param af2             second order clock correction (s/s²)
144      * @param tgd             group delay differential TGD for L1-L2 correction
145      * @param toc             time of clock
146      * @since 14.0
147      */
148     protected FieldGnssOrbitalElements(final double angularVelocity, final int weeksInCycle,
149                                        final TimeScales timeScales, final String type, final int prn,
150                                        final FieldGNSSDate<T> toe, final FieldKeplerianOrbit<T> orbit,
151                                        final T aDot,
152                                        final T deltaN0, final T deltaN0Dot,
153                                        final T iDot, final T omegaDot,
154                                        final T cuc, final T cus,
155                                        final T crc, final T crs,
156                                        final T cic, final T cis,
157                                        final T af0, final T af1, final T af2,
158                                        final T tgd, final FieldGNSSDate<T> toc) {
159 
160         // system parameters
161         this.angularVelocity = angularVelocity;
162         this.weeksInCycle    = weeksInCycle;
163         this.cycleDuration   = GNSSConstants.GNSS_WEEK_IN_SECONDS * weeksInCycle;
164         this.timeScales      = timeScales;
165         this.type            = type;
166 
167         // satellite identifier
168         this.prn             = prn;
169 
170         // time of ephemeris
171         this.toe             = toe;
172 
173         // Keplerian orbit
174         this.orbit           = orbit;
175 
176         // non-Keplerian elements
177         this.aDot            = aDot;
178         this.deltaN0         = deltaN0;
179         this.deltaN0Dot      = deltaN0Dot;
180         this.iDot            = iDot;
181         this.omegaDot        = omegaDot;
182         this.cuc             = cuc;
183         this.cus             = cus;
184         this.crc             = crc;
185         this.crs             = crs;
186         this.cic             = cic;
187         this.cis             = cis;
188 
189         // clock elements
190         this.af0             = af0;
191         this.af1             = af1;
192         this.af2             = af2;
193         this.toc             = toc;
194         this.tgd             = tgd;
195 
196     }
197 
198     /** Creates a new instance.
199      * @param angularVelocity mean angular velocity of the Earth for the GNSS model
200      * @param weeksInCycle    number of weeks in the GNSS cycle
201      * @param timeScales      known time scales
202      * @param type            type (null if not a navigation message)
203      * @param prn             PRN number of the satellite
204      * @param toe             time of ephemeris (<em>must</em> be consistent with {@code orbit})
205      * @param orbit           Keplerian orbit in Earth-frozen frame
206      * @param nonKeplerian    15 non-Keplerian parameters (in the order given by {@link NonKeplerianDriversFactory}
207      * @param tgd             group delay differential TGD for L1-L2 correction
208      * @param toc             time of clock
209      * @since 14.0
210      */
211     protected FieldGnssOrbitalElements(final double angularVelocity, final int weeksInCycle,
212                                        final TimeScales timeScales, final String type, final int prn,
213                                        final FieldGNSSDate<T> toe, final FieldKeplerianOrbit<T> orbit,
214                                        final T[] nonKeplerian, final T tgd, final FieldGNSSDate<T> toc) {
215         this(angularVelocity, weeksInCycle, timeScales, type, prn,
216              toe, orbit,
217              nonKeplerian[NonKeplerianDriversFactory.A_DOT_INDEX],
218              nonKeplerian[NonKeplerianDriversFactory.DELTA_N0_INDEX],
219              nonKeplerian[NonKeplerianDriversFactory.DELTA_N0_DOT_INDEX],
220              nonKeplerian[NonKeplerianDriversFactory.I_DOT_INDEX],
221              nonKeplerian[NonKeplerianDriversFactory.OMEGA_DOT_INDEX],
222              nonKeplerian[NonKeplerianDriversFactory.CUC_INDEX],
223              nonKeplerian[NonKeplerianDriversFactory.CUS_INDEX],
224              nonKeplerian[NonKeplerianDriversFactory.CRC_INDEX],
225              nonKeplerian[NonKeplerianDriversFactory.CRS_INDEX],
226              nonKeplerian[NonKeplerianDriversFactory.CIC_INDEX],
227              nonKeplerian[NonKeplerianDriversFactory.CIS_INDEX],
228              nonKeplerian[NonKeplerianDriversFactory.AF0_INDEX],
229              nonKeplerian[NonKeplerianDriversFactory.AF1_INDEX],
230              nonKeplerian[NonKeplerianDriversFactory.AF2_INDEX],
231              tgd, toc);
232     }
233 
234     /** {@inheritDoc} */
235     @Override
236     public FieldAbsoluteDate<T> getDate() {
237         return toe.getDate();
238     }
239 
240     /** Get the time of ephemeris.
241      * @return time of ephemeris
242      * @since 14.0
243      */
244     public FieldGNSSDate<T> getTimeOfEphemeris() {
245         return toe;
246     }
247 
248     /** {@inheritDoc} */
249     @Override
250     public FieldGNSSDate<T> getTimeOfClock() {
251         return toc;
252     }
253 
254     /** Create a non-field version of the instance.
255      * @return non-field version of the instance
256      */
257     public abstract O toNonField();
258 
259     /** Create an array with the 15 non-Keplerian parameters.
260      * <p>
261      *  The array is ordered according to {@link NonKeplerianDriversFactory} order.
262      *  </p>
263      * @return array with the 15 non-Keplerian parameters
264      */
265     public T[] toArray() {
266         final T[] array = MathArrays.buildArray(orbit.getDate().getField(), NonKeplerianDriversFactory.SIZE);
267         array[NonKeplerianDriversFactory.A_DOT_INDEX]        = aDot;
268         array[NonKeplerianDriversFactory.DELTA_N0_INDEX]     = deltaN0;
269         array[NonKeplerianDriversFactory.DELTA_N0_DOT_INDEX] = deltaN0Dot;
270         array[NonKeplerianDriversFactory.I_DOT_INDEX]        = iDot;
271         array[NonKeplerianDriversFactory.OMEGA_DOT_INDEX]    = omegaDot;
272         array[NonKeplerianDriversFactory.CUC_INDEX]          = cuc;
273         array[NonKeplerianDriversFactory.CUS_INDEX]          = cus;
274         array[NonKeplerianDriversFactory.CRC_INDEX]          = crc;
275         array[NonKeplerianDriversFactory.CRS_INDEX]          = crs;
276         array[NonKeplerianDriversFactory.CIC_INDEX]          = cic;
277         array[NonKeplerianDriversFactory.CIS_INDEX]          = cis;
278         array[NonKeplerianDriversFactory.AF0_INDEX]          = af0;
279         array[NonKeplerianDriversFactory.AF1_INDEX]          = af1;
280         array[NonKeplerianDriversFactory.AF2_INDEX]          = af2;
281         return array;
282     }
283 
284     /** Create another field version of the instance.
285      * @param <U>          type of the new field elements
286      * @param keplerian    orbit in the correct gradient field
287      * @param nonKeplerian non-Keplerian parameters
288      * @param converter    converter for remaining elements
289      * @return field version of the instance
290      */
291     public abstract <U extends CalculusFieldElement<U>>
292         FieldGnssOrbitalElements<U, O> toField(FieldKeplerianOrbit<U> keplerian,
293                                                U[] nonKeplerian,
294                                                Function<T, U> converter);
295 
296     /** Get known time scales.
297      * @return known time scales
298      */
299     public TimeScales getTimeScales() {
300         return timeScales;
301     }
302 
303     /** Get the message type.
304      * @return message type (null if not a navigation message)
305      */
306     public String getType() {
307         return type;
308     }
309 
310     /** Get the mean angular velocity of the Earth of the GNSS model.
311      * @return mean angular velocity of the Earth of the GNSS model
312      */
313     public double getAngularVelocity() {
314         return angularVelocity;
315     }
316 
317     /** Get for the duration of the GNSS cycle in weeks.
318      * @return the duration of the GNSS cycle in weeks
319      */
320     public int getWeeksInCycle() {
321         return weeksInCycle;
322     }
323 
324     /** Get for the duration of the GNSS cycle in seconds.
325      * @return the duration of the GNSS cycle in seconds
326      */
327     public double getCycleDuration() {
328         return cycleDuration;
329     }
330 
331     /** Get the PRN number of the satellite.
332      * @return PRN number of the satellite
333      */
334     public int getPrn() {
335         return prn;
336     }
337 
338     /** Get the underlying Keplerian orbit.
339      * @return underlying Keplerian orbit
340      * @since 14.0
341      */
342     public FieldKeplerianOrbit<T> getOrbit() {
343         return orbit;
344     }
345 
346     /** Get change rate in semi-major axis.
347      * @return the change rate in semi-major axis
348      * @since 14.0
349      */
350     public T getADot() {
351         return aDot;
352     }
353 
354     /** Get the delta of satellite mean motion.
355      * @return the delta of satellite mean motion
356      * @since 14.0
357      */
358     public T getDeltaN0() {
359         return deltaN0;
360     }
361 
362     /** Get the change rate in Δn₀.
363      * @return change rate in Δn₀
364      * @since 14.0
365      */
366     public T getDeltaN0Dot() {
367         return deltaN0Dot;
368     }
369 
370     /** Get rate of inclination angle.
371      * @return rate of inclination angle (rad/s)
372      */
373     public T getIDot() {
374         return iDot;
375     }
376 
377     /** Get rate of right ascension.
378      * @return rate of right ascension (rad/s)
379      */
380     public T getOmegaDot() {
381         return omegaDot;
382     }
383 
384     /** Get amplitude of the cosine harmonic correction term to the argument of latitude.
385      * @return amplitude of the cosine harmonic correction term to the argument of latitude (rad)
386      */
387     public T getCuc() {
388         return cuc;
389     }
390 
391     /** Get amplitude of the sine harmonic correction term to the argument of latitude.
392      * @return amplitude of the sine harmonic correction term to the argument of latitude (rad)
393      */
394     public T getCus() {
395         return cus;
396     }
397 
398     /** Get amplitude of the cosine harmonic correction term to the orbit radius.
399      * @return amplitude of the cosine harmonic correction term to the orbit radius (m)
400      */
401     public T getCrc() {
402         return crc;
403     }
404 
405     /** Get amplitude of the sine harmonic correction term to the orbit radius.
406      * @return amplitude of the sine harmonic correction term to the orbit radius (m)
407      */
408     public T getCrs() {
409         return crs;
410     }
411 
412     /** Get amplitude of the cosine harmonic correction term to the angle of inclination.
413      * @return amplitude of the cosine harmonic correction term to the angle of inclination (rad)
414      */
415     public T getCic() {
416         return cic;
417     }
418 
419     /** Get amplitude of the sine harmonic correction term to the angle of inclination.
420      * @return amplitude of the sine harmonic correction term to the angle of inclination (rad)
421      */
422     public T getCis() {
423         return cis;
424     }
425 
426     /** {@inheritDoc} */
427     @Override
428     public T getAf0() {
429         return af0;
430     }
431 
432     /** {@inheritDoc} */
433     @Override
434     public T getAf1() {
435         return af1;
436     }
437 
438     /** {@inheritDoc} */
439     @Override
440     public T getAf2() {
441         return af2;
442     }
443 
444     /** {@inheritDoc} */
445     @Override
446     public T getTgd() {
447         return tgd;
448     }
449 
450     /** Check if elements correspond to a civilian message.
451      * @return true if elements correspond to a civilian message
452      */
453     public boolean isCivilianMessage() {
454         return false;
455     }
456 
457 }