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;
18  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.orekit.propagation.AdditionalDataProvider;
21  import org.orekit.propagation.SpacecraftState;
22  import org.orekit.propagation.analytical.gnss.data.GNSSClockElements;
23  import org.orekit.time.AbsoluteDate;
24  import org.orekit.utils.Constants;
25  import org.orekit.utils.PVCoordinates;
26  
27  /** Provider for clock corrections as additional states.
28   * <p>
29   * The value of this additional state is a three elements array containing
30   * </p>
31   * <ul>
32   *   <li>at index 0, the polynomial satellite clock model
33   *       Δtₛₐₜ = {@link GNSSClockElements#getAf0() a₀} +
34   *               {@link GNSSClockElements#getAf1() a₁} (t - {@link GNSSClockElements#getToc() toc}) +
35   *               {@link GNSSClockElements#getAf1() a₂} (t - {@link GNSSClockElements#getToc() toc})²
36   *   </li>
37   *   <li>at index 1 the relativistic clock correction due to eccentricity</li>
38   *   <li>at index 2 the estimated group delay differential {@link GNSSClockElements#getTGD() TGD} for L1-L2 correction</li>
39   * </ul>
40   * <p>
41   * Since Orekit 10.3 the relativistic clock correction can be used as an
42   * {@link org.orekit.estimation.measurements.EstimationModifier} in orbit determination applications
43   * to take into consideration this effect in measurement modeling.
44   * </p>
45   *
46   * @author Luc Maisonobe
47   * @since 9.3
48   */
49  public class ClockCorrectionsProvider implements AdditionalDataProvider<double[]> {
50  
51      /** Name of the additional state for satellite clock corrections.
52       * @since 9.3
53       */
54      public static final String CLOCK_CORRECTIONS = "";
55  
56      /** The GPS clock elements. */
57      private final GNSSClockElements gnssClk;
58  
59      /** Clock reference epoch. */
60      private final AbsoluteDate clockRef;
61  
62      /** Duration of the GNSS cycle in seconds. */
63      private final double cycleDuration;
64  
65      /** Simple constructor.
66       * @param gnssClk GNSS clock elements
67       * @param cycleDuration duration of the GNSS cycle in seconds
68       */
69      public ClockCorrectionsProvider(final GNSSClockElements gnssClk,
70                                      final double cycleDuration) {
71          this.gnssClk       = gnssClk;
72          this.clockRef      = gnssClk.getDate();
73          this.cycleDuration = cycleDuration;
74      }
75  
76      /** {@inheritDoc} */
77      @Override
78      public String getName() {
79          return CLOCK_CORRECTIONS;
80      }
81  
82      /**
83       * Get the duration from clock Reference epoch.
84       * <p>This takes the GNSS week roll-over into account.</p>
85       *
86       * @param date the considered date
87       * @return the duration from clock Reference epoch (s)
88       */
89      private double getDT(final AbsoluteDate date) {
90          // Time from ephemeris reference epoch
91          double dt = date.durationFrom(clockRef);
92          // Adjusts the time to take roll over week into account
93          while (dt > 0.5 * cycleDuration) {
94              dt -= cycleDuration;
95          }
96          while (dt < -0.5 * cycleDuration) {
97              dt += cycleDuration;
98          }
99          // Returns the time from ephemeris reference epoch
100         return dt;
101     }
102 
103     /** {@inheritDoc} */
104     @Override
105     public double[] getAdditionalData(final SpacecraftState state) {
106 
107         // polynomial clock model
108         final double  dt    = getDT(state.getDate());
109         final double  dtSat = gnssClk.getAf0() + dt * (gnssClk.getAf1() + dt * gnssClk.getAf2());
110 
111         // relativistic effect due to eccentricity
112         final PVCoordinates pv    = state.getPVCoordinates();
113         final double        dtRel = -2 * Vector3D.dotProduct(pv.getPosition(), pv.getVelocity()) /
114                         (Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT);
115 
116         // estimated group delay differential
117         final double tg = gnssClk.getTGD();
118 
119         return new double[] {
120             dtSat, dtRel, tg
121         };
122     }
123 
124 }