1 /* Copyright 2022-2025 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 org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.util.FastMath;
22 import org.orekit.gnss.SatelliteSystem;
23 import org.orekit.time.FieldAbsoluteDate;
24 import org.orekit.time.FieldTimeStamped;
25 import org.orekit.time.GNSSDate;
26 import org.orekit.time.TimeScales;
27
28 import java.util.function.Function;
29
30 /** This class provides the minimal set of orbital elements needed by the {@link
31 * org.orekit.propagation.analytical.gnss.FieldGnssPropagator}.
32 * @param <T> type of the field elements
33 * @param <O> type of the orbital elements (non-field version)
34 * @since 13.0
35 * @author Luc Maisonobe
36 */
37 public abstract class FieldGnssOrbitalElements<T extends CalculusFieldElement<T>, O extends GNSSOrbitalElements<O>>
38 extends GNSSOrbitalElementsDriversProvider
39 implements FieldTimeStamped<T> {
40
41 /** Earth's universal gravitational parameter. */
42 private final T mu;
43
44 /** Reference epoch. */
45 private FieldAbsoluteDate<T> date;
46
47 /** Semi-Major Axis (m). */
48 private T sma;
49
50 /** Eccentricity. */
51 private T ecc;
52
53 /** Inclination angle at reference time (rad). */
54 private T i0;
55
56 /** Argument of perigee (rad). */
57 private T aop;
58
59 /** Longitude of ascending node of orbit plane at weekly epoch (rad). */
60 private T om0;
61
62 /** Mean anomaly at reference time (rad). */
63 private T anom;
64
65 /** Simple constructor.
66 * @param mu Earth's universal gravitational parameter
67 * @param angularVelocity mean angular velocity of the Earth for the GNSS model
68 * @param weeksInCycle number of weeks in the GNSS cycle
69 * @param timeScales known time scales
70 * @param system satellite system to consider for interpreting week number
71 * (may be different from real system, for example in Rinex nav, weeks
72 * are always according to GPS)
73 */
74 protected FieldGnssOrbitalElements(final T mu, final double angularVelocity, final int weeksInCycle,
75 final TimeScales timeScales, final SatelliteSystem system) {
76
77 super(angularVelocity, weeksInCycle, timeScales, system);
78
79 // immutable field
80 this.mu = mu;
81
82 // Keplerian orbital elements
83 this.sma = mu.newInstance(Double.NaN);
84 this.ecc = mu.newInstance(Double.NaN);
85 this.i0 = mu.newInstance(Double.NaN);
86 this.aop = mu.newInstance(Double.NaN);
87 this.om0 = mu.newInstance(Double.NaN);
88 this.anom = mu.newInstance(Double.NaN);
89
90 }
91
92 /** Constructor from non-field instance.
93 * @param field field to which elements belong
94 * @param original regular non-field instance
95 */
96 protected FieldGnssOrbitalElements(final Field<T> field, final O original) {
97
98 super(original.getAngularVelocity(), original.getWeeksInCycle(),
99 original.getTimeScales(), original.getSystem());
100 mu = field.getZero().newInstance(original.getMu());
101
102 // non-Keplerian parameters
103 setPRN(original.getPRN());
104 setWeek(original.getWeek());
105 setTime(original.getTime());
106 setIDot(original.getIDot());
107 setOmegaDot(original.getOmegaDot());
108 setCuc(original.getCuc());
109 setCus(original.getCus());
110 setCrc(original.getCrc());
111 setCrs(original.getCrs());
112 setCic(original.getCic());
113 setCis(original.getCis());
114
115 // Keplerian orbital elements
116 setGnssDate(new GNSSDate(original.getWeek(), original.getTime(), original.getSystem(), original.getTimeScales()));
117 setSma(field.getZero().newInstance(original.getSma()));
118 setE(field.getZero().newInstance(original.getE()));
119 setI0(field.getZero().newInstance(original.getI0()));
120 setPa(field.getZero().newInstance(original.getPa()));
121 setOmega0(field.getZero().newInstance(original.getOmega0()));
122 setM0(field.getZero().newInstance(original.getM0()));
123
124 // copy selection settings
125 copySelectionSettings(original);
126
127 }
128
129 /** Constructor from different field instance.
130 * @param <V> type of the old field elements
131 * @param original regular non-field instance
132 * @param converter for field elements
133 */
134 protected <V extends CalculusFieldElement<V>> FieldGnssOrbitalElements(final Function<V, T> converter,
135 final FieldGnssOrbitalElements<V, O> original) {
136 super(original.getAngularVelocity(), original.getWeeksInCycle(),
137 original.getTimeScales(), original.getSystem());
138 mu = converter.apply(original.getMu());
139
140 // non-Keplerian parameters
141 setPRN(original.getPRN());
142 setWeek(original.getWeek());
143 setTime(original.getTime());
144 setIDot(original.getIDot());
145 setOmegaDot(original.getOmegaDot());
146 setCuc(original.getCuc());
147 setCus(original.getCus());
148 setCrc(original.getCrc());
149 setCrs(original.getCrs());
150 setCic(original.getCic());
151 setCis(original.getCis());
152
153 // Keplerian orbital elements
154 setGnssDate(new GNSSDate(original.getWeek(), original.getTime(), original.getSystem(), original.getTimeScales()));
155 setSma(converter.apply(original.getSma()));
156 setE(converter.apply(original.getE()));
157 setI0(converter.apply(original.getI0()));
158 setPa(converter.apply(original.getPa()));
159 setOmega0(converter.apply(original.getOmega0()));
160 setM0(converter.apply(original.getM0()));
161
162 // copy selection settings
163 copySelectionSettings(original);
164
165 }
166
167 /** Create a non-field version of the instance.
168 * @return non-field version of the instance
169 */
170 public abstract O toNonField();
171
172 /**
173 * Create another field version of the instance.
174 *
175 * @param <U> type of the new field elements
176 * @param <G> type of the orbital elements (field version)
177 * @param converter for field elements
178 * @return field version of the instance
179 */
180 public abstract <U extends CalculusFieldElement<U>, G extends FieldGnssOrbitalElements<U, O>>
181 G changeField(Function<T, U> converter);
182
183 /** {@inheritDoc} */
184 protected void setGnssDate(final GNSSDate gnssDate) {
185 this.date = new FieldAbsoluteDate<>(mu.getField(), gnssDate.getDate());
186 }
187
188 /** Get date.
189 * @return date
190 */
191 public FieldAbsoluteDate<T> getDate() {
192 return date;
193 }
194
195 /** Get the Earth's universal gravitational parameter.
196 * @return the Earth's universal gravitational parameter
197 */
198 public T getMu() {
199 return mu;
200 }
201
202 /** Get semi-major axis.
203 * @return semi-major axis (m)
204 */
205 public T getSma() {
206 return sma;
207 }
208
209 /** Set semi-major axis.
210 * @param sma demi-major axis (m)
211 */
212 public void setSma(final T sma) {
213 this.sma = sma;
214 }
215
216 /** Getter for the change rate in semi-major axis.
217 * <p>
218 * This value is non-zero only in civilian navigation messages
219 * </p>
220 * @return the change rate in semi-major axis
221 * @since 13.0
222 */
223 public T getADot() {
224 return mu.getField().getZero();
225 }
226
227 /** Get the computed mean motion n₀.
228 * @return the computed mean motion n₀ (rad/s)
229 * @since 13.0
230 */
231 public T getMeanMotion0() {
232 final T invA = FastMath.abs(getSma()).reciprocal();
233 return FastMath.sqrt(getMu().multiply(invA)).multiply(invA);
234 }
235
236 /** Getter for the delta of satellite mean motion.
237 * <p>
238 * This value is non-zero only in navigation messages
239 * </p>
240 * @return delta of satellite mean motion
241 * @since 13.0
242 */
243 public T getDeltaN0() {
244 return mu.getField().getZero();
245 }
246
247 /** Getter for change rate in Δn₀.
248 * <p>
249 * This value is non-zero only in civilian navigation messages
250 * </p>
251 * @return change rate in Δn₀
252 * @since 13.0
253 */
254 public T getDeltaN0Dot() {
255 return mu.getField().getZero();
256 }
257
258 /** Get eccentricity.
259 * @return eccentricity
260 */
261 public T getE() {
262 return ecc;
263 }
264
265 /** Set eccentricity.
266 * @param e eccentricity
267 */
268 public void setE(final T e) {
269 this.ecc = e;
270 }
271
272 /** Get the inclination angle at reference time.
273 * @return inclination angle at reference time (rad)
274 */
275 public T getI0() {
276 return i0;
277 }
278
279 /** Set inclination angle at reference time.
280 * @param i0 inclination angle at reference time (rad)
281 */
282 public void setI0(final T i0) {
283 this.i0 = i0;
284 }
285
286 /** Get longitude of ascending node of orbit plane at weekly epoch.
287 * @return longitude of ascending node of orbit plane at weekly epoch (rad)
288 */
289 public T getOmega0() {
290 return om0;
291 }
292
293 /** Set longitude of ascending node of orbit plane at weekly epoch.
294 * @param omega0 longitude of ascending node of orbit plane at weekly epoch (rad)
295 */
296 public void setOmega0(final T omega0) {
297 this.om0 = omega0;
298 }
299
300 /** Get argument of perigee.
301 * @return argument of perigee (rad)
302 */
303 public T getPa() {
304 return aop;
305 }
306
307 /** Set argument of perigee.
308 * @param pa argument of perigee (rad)
309 */
310 public void setPa(final T pa) {
311 this.aop = pa;
312 }
313
314 /** Get mean anomaly at reference time.
315 * @return mean anomaly at reference time (rad)
316 */
317 public T getM0() {
318 return anom;
319 }
320
321 /** Set mean anomaly at reference time.
322 * @param m0 mean anomaly at reference time (rad)
323 */
324 public void setM0(final T m0) {
325 this.anom = m0;
326 }
327
328 }