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 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 copyNonKeplerian(original);
104
105 // Keplerian orbital elements
106 setGnssDate(new GNSSDate(original.getWeek(), original.getTime(), original.getSystem(), original.getTimeScales()));
107 setSma(field.getZero().newInstance(original.getSma()));
108 setE(field.getZero().newInstance(original.getE()));
109 setI0(field.getZero().newInstance(original.getI0()));
110 setPa(field.getZero().newInstance(original.getPa()));
111 setOmega0(field.getZero().newInstance(original.getOmega0()));
112 setM0(field.getZero().newInstance(original.getM0()));
113
114 // copy selection settings
115 copySelectionSettings(original);
116
117 }
118
119 /** Constructor from different field instance.
120 * @param <V> type of the old field elements
121 * @param original regular non-field instance
122 * @param converter for field elements
123 */
124 protected <V extends CalculusFieldElement<V>> FieldGnssOrbitalElements(final Function<V, T> converter,
125 final FieldGnssOrbitalElements<V, O> original) {
126 super(original.getAngularVelocity(), original.getWeeksInCycle(),
127 original.getTimeScales(), original.getSystem());
128 mu = converter.apply(original.getMu());
129
130 // non-Keplerian parameters
131 copyNonKeplerian(original);
132
133 // Keplerian orbital elements
134 setGnssDate(new GNSSDate(original.getWeek(), original.getTime(), original.getSystem(), original.getTimeScales()));
135 setSma(converter.apply(original.getSma()));
136 setE(converter.apply(original.getE()));
137 setI0(converter.apply(original.getI0()));
138 setPa(converter.apply(original.getPa()));
139 setOmega0(converter.apply(original.getOmega0()));
140 setM0(converter.apply(original.getM0()));
141
142 // copy selection settings
143 copySelectionSettings(original);
144
145 }
146
147 /** Create a non-field version of the instance.
148 * @return non-field version of the instance
149 */
150 public abstract O toNonField();
151
152 /**
153 * Create another field version of the instance.
154 *
155 * @param <U> type of the new field elements
156 * @param <G> type of the orbital elements (field version)
157 * @param converter for field elements
158 * @return field version of the instance
159 */
160 public abstract <U extends CalculusFieldElement<U>, G extends FieldGnssOrbitalElements<U, O>>
161 G changeField(Function<T, U> converter);
162
163 /** {@inheritDoc} */
164 protected void setGnssDate(final GNSSDate gnssDate) {
165 this.date = new FieldAbsoluteDate<>(mu.getField(), gnssDate.getDate());
166 }
167
168 /** Get date.
169 * @return date
170 */
171 public FieldAbsoluteDate<T> getDate() {
172 return date;
173 }
174
175 /** Get the Earth's universal gravitational parameter.
176 * @return the Earth's universal gravitational parameter
177 */
178 public T getMu() {
179 return mu;
180 }
181
182 /** Get semi-major axis.
183 * @return semi-major axis (m)
184 */
185 public T getSma() {
186 return sma;
187 }
188
189 /** Set semi-major axis.
190 * @param sma demi-major axis (m)
191 */
192 public void setSma(final T sma) {
193 this.sma = sma;
194 }
195
196 /** Get the computed mean motion n₀.
197 * @return the computed mean motion n₀ (rad/s)
198 * @since 13.0
199 */
200 public T getMeanMotion0() {
201 final T invA = FastMath.abs(getSma()).reciprocal();
202 return FastMath.sqrt(getMu().multiply(invA)).multiply(invA);
203 }
204
205 /** Get eccentricity.
206 * @return eccentricity
207 */
208 public T getE() {
209 return ecc;
210 }
211
212 /** Set eccentricity.
213 * @param e eccentricity
214 */
215 public void setE(final T e) {
216 this.ecc = e;
217 }
218
219 /** Get the inclination angle at reference time.
220 * @return inclination angle at reference time (rad)
221 */
222 public T getI0() {
223 return i0;
224 }
225
226 /** Set inclination angle at reference time.
227 * @param i0 inclination angle at reference time (rad)
228 */
229 public void setI0(final T i0) {
230 this.i0 = i0;
231 }
232
233 /** Get longitude of ascending node of orbit plane at weekly epoch.
234 * @return longitude of ascending node of orbit plane at weekly epoch (rad)
235 */
236 public T getOmega0() {
237 return om0;
238 }
239
240 /** Set longitude of ascending node of orbit plane at weekly epoch.
241 * @param omega0 longitude of ascending node of orbit plane at weekly epoch (rad)
242 */
243 public void setOmega0(final T omega0) {
244 this.om0 = omega0;
245 }
246
247 /** Get argument of perigee.
248 * @return argument of perigee (rad)
249 */
250 public T getPa() {
251 return aop;
252 }
253
254 /** Set argument of perigee.
255 * @param pa argument of perigee (rad)
256 */
257 public void setPa(final T pa) {
258 this.aop = pa;
259 }
260
261 /** Get mean anomaly at reference time.
262 * @return mean anomaly at reference time (rad)
263 */
264 public T getM0() {
265 return anom;
266 }
267
268 /** Set mean anomaly at reference time.
269 * @param m0 mean anomaly at reference time (rad)
270 */
271 public void setM0(final T m0) {
272 this.anom = m0;
273 }
274
275 }