1   /* Copyright 2002-2025 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.ode.nonstiff.ClassicalRungeKuttaIntegrator;
20  import org.hipparchus.util.FastMath;
21  import org.orekit.annotation.DefaultDataContext;
22  import org.orekit.attitudes.AttitudeProvider;
23  import org.orekit.data.DataContext;
24  import org.orekit.frames.Frame;
25  import org.orekit.propagation.numerical.GLONASSNumericalPropagator;
26  import org.orekit.propagation.numerical.GLONASSNumericalPropagatorBuilder;
27  
28  /**
29   * Container for data contained in a Glonass navigation message.
30   * @author Bryan Cazabonne
31   * @since 11.0
32   */
33  public class GLONASSNavigationMessage extends AbstractEphemerisMessage implements GLONASSOrbitalElements {
34  
35      /** Message frame time. */
36      private double time;
37  
38      /** SV clock bias. */
39      private double tauN;
40  
41      /** SV relative frequency bias. */
42      private double gammaN;
43  
44      /** Frequency number. */
45      private int frequencyNumber;
46  
47      /** Status flags.
48       * @since 12.0
49       */
50      private int statusFlags;
51  
52      /** Health flags.
53       * @since 12.0
54       */
55      private int healthFlags;
56  
57      /** Group Delay Difference (s).
58       * @since 12.0
59       */
60      private double groupDelayDifference;
61  
62      /** User range accuracy (m).
63       * @since 12.0
64       */
65      private double ura;
66  
67      /** Constructor. */
68      public GLONASSNavigationMessage() {
69          // Nothing to do ...
70      }
71  
72      /**
73       * Get the propagator corresponding to the navigation message.
74       * <p>The attitude provider is set by default to EME2000 aligned in the
75       *  default data context.<br>
76       * The mass is set by default to the
77       *  {@link org.orekit.propagation.Propagator#DEFAULT_MASS DEFAULT_MASS}.<br>
78       * The data context is by default to the
79       *  {@link DataContext#getDefault() default data context}.<br>
80       * The ECI frame is set by default to the
81       *  {@link org.orekit.frames.Predefined#EME2000 EME2000 frame} in the default data
82       *  context.<br>
83       * </p>
84       * @param step integration step in seconds
85       * @return the propagator corresponding to the navigation message
86       * @see #getPropagator(double, DataContext)
87       * @see #getPropagator(double, DataContext, AttitudeProvider, Frame, double)
88       * @since 12.0
89       */
90      @DefaultDataContext
91      public GLONASSNumericalPropagator getPropagator(final double step) {
92          return new GLONASSNumericalPropagatorBuilder(new ClassicalRungeKuttaIntegrator(step),
93                                                       this, isAccAvailable()).build();
94      }
95  
96      /**
97       * Get the propagator corresponding to the navigation message.
98       * <p>The attitude provider is set by default to EME2000 aligned in the
99       *  default data context.<br>
100      * The mass is set by default to the
101      *  {@link org.orekit.propagation.Propagator#DEFAULT_MASS DEFAULT_MASS}.<br>
102      * The data context is by default to the
103      *  {@link DataContext#getDefault() default data context}.<br>
104      * The ECI frame is set by default to the
105      *  {@link org.orekit.frames.Predefined#EME2000 EME2000 frame} in the default data
106      *  context.<br>
107      * </p>
108      * @param step integration step in seconds
109      * @param context data context
110      * @return the propagator corresponding to the navigation message
111      * @see #getPropagator(double)
112      * @see #getPropagator(double, DataContext, AttitudeProvider, Frame, double)
113      * @since 12.0
114      */
115     public GLONASSNumericalPropagator getPropagator(final double step, final DataContext context) {
116         return new GLONASSNumericalPropagatorBuilder(new ClassicalRungeKuttaIntegrator(step),
117                                                      this, isAccAvailable(), context).build();
118     }
119 
120     /**
121      * Get the propagator corresponding to the navigation message.
122      * @param step integration step in seconds
123      * @param context data context
124      * @param provider attitude provider
125      * @param inertial inertial frame, use to provide the propagated orbit
126      * @param mass spacecraft mass in kg
127      * @return the propagator corresponding to the navigation message
128      * @see #getPropagator(double)
129      * @see #getPropagator(double, DataContext)
130      * @since 12.0
131      */
132     public GLONASSNumericalPropagator getPropagator(final double step, final DataContext context,
133                                                     final AttitudeProvider provider, final Frame inertial,
134                                                     final double mass) {
135         return new GLONASSNumericalPropagatorBuilder(new ClassicalRungeKuttaIntegrator(step),
136                                                      this, isAccAvailable(), context).attitudeProvider(provider)
137                                                                                      .eci(inertial)
138                                                                                      .mass(mass)
139                                                                                      .build();
140     }
141 
142     /** {@inheritDoc} */
143     @Override
144     public double getTN() {
145         return tauN;
146     }
147 
148     /**
149      * Setter for the SV clock bias.
150      * @param tn the SV clock bias
151      */
152     public void setTauN(final double tn) {
153         this.tauN = tn;
154     }
155 
156     /** {@inheritDoc} */
157     @Override
158     public double getGammaN() {
159         return gammaN;
160     }
161 
162     /**
163      * Setter for the SV relative frequency bias.
164      * @param gammaN the SV relative frequency bias.
165      */
166     public void setGammaN(final double gammaN) {
167         this.gammaN = gammaN;
168     }
169 
170     /**
171      * Getter for the frequency number.
172      * @return the frequency number
173      */
174     public int getFrequencyNumber() {
175         return frequencyNumber;
176     }
177 
178     /**
179      * Setter for the frequency number.
180      * @param frequencyNumber the number to set
181      */
182     public void setFrequencyNumber(final double frequencyNumber) {
183         this.frequencyNumber = (int) frequencyNumber;
184     }
185 
186     /** {@inheritDoc} */
187     @Override
188     public double getTime() {
189         return time;
190     }
191 
192     /**
193      * Setter for the message frame time.
194      * @param time the time to set
195      */
196     public void setTime(final double time) {
197         this.time = time;
198     }
199 
200     /** Get status flags.
201      * @return status flags
202      * @since 12.0
203      */
204     public int getStatusFlags() {
205         return statusFlags;
206     }
207 
208     /** Set status flag.
209      * @param statusFlags status flag (parsed as a double)
210      * @since 12.0
211      */
212     public void setStatusFlags(final double statusFlags) {
213         this.statusFlags = (int) FastMath.rint(statusFlags);
214     }
215 
216     /** Set health flag.
217      * @param healthFlags health flag (parsed as a double)
218      * @since 12.0
219      */
220     public void setHealthFlags(final double healthFlags) {
221         this.healthFlags = Double.isNaN(healthFlags) ? 15 : (int) FastMath.rint(healthFlags);
222     }
223 
224     /** Get health flags.
225      * @return health flags
226      * @since 12.0
227      */
228     public int getHealthFlags() {
229         return healthFlags;
230     }
231 
232     /** Get group delay difference.
233      * @return group delay difference
234      * @since 12.0
235      */
236     public double getGroupDelayDifference() {
237         return groupDelayDifference;
238     }
239 
240     /** Set group delay difference.
241      * @param groupDelayDifference group delay difference
242      * @since 12.0
243      */
244     public void setGroupDelayDifference(final double groupDelayDifference) {
245         this.groupDelayDifference = Double.isNaN(groupDelayDifference) ?
246                                     0.999999999999e+09 :
247                                     groupDelayDifference;
248     }
249 
250     /**
251      * Getter for the user range accuray (meters).
252      * @return the user range accuracy
253      * @since 12.0
254      */
255     public double getURA() {
256         return ura;
257     }
258 
259     /**
260      * Setter for the user range accuracy.
261      * @param accuracy the value to set
262      * @since 12.0
263      */
264     public void setURA(final double accuracy) {
265         this.ura = accuracy;
266     }
267 
268     /**
269      * Check if the acceleration is available in the navigation message.
270      * @return true if the acceleration is available
271      */
272     private boolean isAccAvailable() {
273         return getXDotDot() != 0.0 || getYDotDot() != 0.0 || getZDotDot() != 0.0;
274     }
275 
276 }