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 }