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