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 }