1   /* Copyright 2002-2026 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,       0);
110         this.eccDriver  = createDriver(ECCENTRICITY,        -24);
111         this.i0Driver   = createDriver(INCLINATION,         -24);
112         this.aopDriver  = createDriver(ARGUMENT_OF_PERIGEE, -24);
113         this.om0Driver  = createDriver(NODE_LONGITUDE,      -24);
114         this.anomDriver = createDriver(MEAN_ANOMALY,        -24);
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-Keplerian parameters
129         copyNonKeplerian(original);
130 
131         // Keplerian orbital elements
132         setSma(original.getSma().getReal());
133         setE(original.getE().getReal());
134         setI0(original.getI0().getReal());
135         setPa(original.getPa().getReal());
136         setOmega0(original.getOmega0().getReal());
137         setM0(original.getM0().getReal());
138 
139         // copy selection settings
140         copySelectionSettings(original);
141 
142     }
143 
144     /** Create a field version of the instance.
145      * @param <T> type of the field elements
146      * @param <F> type of the orbital elements (field version)
147      * @param field field to which elements belong
148      * @return field version of the instance
149      */
150     public abstract <T extends CalculusFieldElement<T>, F extends FieldGnssOrbitalElements<T, O>>
151         F toField(Field<T> field);
152 
153     /** {@inheritDoc} */
154     protected void setGnssDate(final GNSSDate gnssDate) {
155         this.date = gnssDate.getDate();
156     }
157 
158     /** {@inheritDoc} */
159     @Override
160     public AbsoluteDate getDate() {
161         return date;
162     }
163 
164     /** Get the Earth's universal gravitational parameter.
165      * @return the Earth's universal gravitational parameter
166      */
167     public double getMu() {
168         return mu;
169     }
170 
171     /** Get semi-major axis.
172      * @return driver for the semi-major axis (m)
173      */
174     public ParameterDriver getSmaDriver() {
175         return smaDriver;
176     }
177 
178     /** Get semi-major axis.
179      * @return semi-major axis (m)
180      */
181     public double getSma() {
182         return getSmaDriver().getValue();
183     }
184 
185     /** Set semi-major axis.
186      * @param sma demi-major axis (m)
187      */
188     public void setSma(final double sma) {
189         getSmaDriver().setValue(sma);
190     }
191 
192     /** Get the computed mean motion n₀.
193      * @return the computed mean motion n₀ (rad/s)
194      * @since 13.0
195      */
196     public double getMeanMotion0() {
197         final double absA = FastMath.abs(getSma());
198         return FastMath.sqrt(getMu() / absA) / absA;
199     }
200 
201     /** Get the driver for the eccentricity.
202      * @return driver for the eccentricity
203      */
204     public ParameterDriver getEDriver() {
205         return eccDriver;
206     }
207 
208     /** Get eccentricity.
209      * @return eccentricity
210      */
211     public double getE() {
212         return getEDriver().getValue();
213     }
214 
215     /** Set eccentricity.
216      * @param e eccentricity
217      */
218     public void setE(final double e) {
219         getEDriver().setValue(e);
220     }
221 
222     /** Get the driver for the inclination angle at reference time.
223      * @return driver for the inclination angle at reference time (rad)
224      */
225     public ParameterDriver getI0Driver() {
226         return i0Driver;
227     }
228 
229     /** Get the inclination angle at reference time.
230      * @return inclination angle at reference time (rad)
231      */
232     public double getI0() {
233         return getI0Driver().getValue();
234     }
235 
236     /** Set inclination angle at reference time.
237      * @param i0 inclination angle at reference time (rad)
238      */
239     public void setI0(final double i0) {
240         getI0Driver().setValue(i0);
241     }
242 
243     /** Get the driver for the longitude of ascending node of orbit plane at weekly epoch.
244      * @return driver for the longitude of ascending node of orbit plane at weekly epoch (rad)
245      */
246     public ParameterDriver getOmega0Driver() {
247         return om0Driver;
248     }
249 
250     /** Get longitude of ascending node of orbit plane at weekly epoch.
251      * @return longitude of ascending node of orbit plane at weekly epoch (rad)
252      */
253     public double getOmega0() {
254         return getOmega0Driver().getValue();
255     }
256 
257     /** Set longitude of ascending node of orbit plane at weekly epoch.
258      * @param om0 longitude of ascending node of orbit plane at weekly epoch (rad)
259      */
260     public void setOmega0(final double om0) {
261         getOmega0Driver().setValue(om0);
262     }
263 
264     /** Get the driver for the argument of perigee.
265      * @return driver for the argument of perigee (rad)
266      */
267     public ParameterDriver getPaDriver() {
268         return aopDriver;
269     }
270 
271     /** Get argument of perigee.
272      * @return argument of perigee (rad)
273      */
274     public double getPa() {
275         return getPaDriver().getValue();
276     }
277 
278     /** Set argument of perigee.
279      * @param aop argument of perigee (rad)
280      */
281     public void setPa(final double aop) {
282         getPaDriver().setValue(aop);
283     }
284 
285     /** Get the driver for the mean anomaly at reference time.
286      * @return driver for the mean anomaly at reference time (rad)
287      */
288     public ParameterDriver getM0Driver() {
289         return anomDriver;
290     }
291 
292     /** Get mean anomaly at reference time.
293      * @return mean anomaly at reference time (rad)
294      */
295     public double getM0() {
296         return getM0Driver().getValue();
297     }
298 
299     /** Set mean anomaly at reference time.
300      * @param anom mean anomaly at reference time (rad)
301      */
302     public void setM0(final double anom) {
303         getM0Driver().setValue(anom);
304     }
305 
306 }