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.estimation.measurements.modifiers;
18  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.junit.jupiter.api.Assertions;
21  import org.junit.jupiter.api.BeforeEach;
22  import org.junit.jupiter.api.Test;
23  import org.orekit.Utils;
24  import org.orekit.estimation.measurements.EstimatedMeasurement;
25  import org.orekit.estimation.measurements.EstimatedMeasurementBase;
26  import org.orekit.estimation.measurements.EstimationModifier;
27  import org.orekit.estimation.measurements.ObservableSatellite;
28  import org.orekit.estimation.measurements.QuadraticClockModel;
29  import org.orekit.estimation.measurements.gnss.AmbiguityCache;
30  import org.orekit.estimation.measurements.gnss.OneWayGNSSPhase;
31  import org.orekit.gnss.PredefinedGnssSignal;
32  import org.orekit.propagation.SpacecraftState;
33  import org.orekit.propagation.analytical.tle.TLE;
34  import org.orekit.propagation.analytical.tle.TLEPropagator;
35  import org.orekit.time.AbsoluteDate;
36  import org.orekit.time.TimeScalesFactory;
37  import org.orekit.utils.Constants;
38  
39  /**
40   * Check against prediction in
41   * "Springer Handbook oƒ Global Navigation Satellite Systems, Teunissen, Montenbruck".
42   * <p>
43   * An approximate value is given in terms of delay for Galileo satellites.
44   * As these satellites are close to GPS satellites, we consider the delays to be
45   * of the same order, namely around 62ps.
46   * </p>
47   * <p>
48   * The values produced by the modifiers are translated in terms of delay and checked against
49   * the approximate value.
50   * </p>
51   */
52  
53  public class RelativisticJ2ClockOneWayGNSSPhaseModifierTest {
54  
55      /** Date. */
56      private static AbsoluteDate date;
57  
58      /** Spacecraft states. */
59      private static SpacecraftState[] states;
60  
61      @Deprecated
62      @Test
63      public void testRelativisticClockCorrectionDeprecated() {
64  
65          // Measurement
66          final double wavelength = PredefinedGnssSignal.G01.getWavelength();
67          final OneWayGNSSPhase phase = new OneWayGNSSPhase(states[1].getOrbit(), "",
68                                                            new QuadraticClockModel(date, 0.0, 0.0, 0.0), date,
69                                                            Vector3D.distance(states[0].getPosition(),
70                                                                              states[1].getPosition()) / wavelength,
71                                                            wavelength, 1.0, 1.0, new ObservableSatellite(0),
72                                                            new AmbiguityCache());
73  
74          // One-way GNSS phase before applying the modifier
75          final EstimatedMeasurementBase<OneWayGNSSPhase> estimatedBefore = phase.estimateWithoutDerivatives(states);
76  
77          // One-way GNSS phase before applying the modifier
78          final EstimationModifier<OneWayGNSSPhase> modifier = new RelativisticJ2ClockOneWayGNSSPhaseModifier(Constants.WGS84_EARTH_MU,
79                                                                                                              Constants.WGS84_EARTH_C20, Constants.WGS84_EARTH_EQUATORIAL_RADIUS );
80          phase.addModifier(modifier);
81          final EstimatedMeasurement<OneWayGNSSPhase> estimatedAfter = phase.estimate(0, 0, states);
82  
83          // Verify : According to Teunissen and Montenbruck, the delay is supposed to be around 62 ps for Galileo.
84          //          The computed value is equal to 67.284 ps, therefore lying in the supposed range.
85          Assertions.assertEquals(-0.106217, estimatedBefore.getEstimatedValue()[0] - estimatedAfter.getEstimatedValue()[0], 1.0e-6);
86          Assertions.assertEquals(0, modifier.getParametersDrivers().size());
87          Assertions.assertEquals(1,
88                                  estimatedAfter.getAppliedEffects().entrySet().stream().
89                                  filter(e -> e.getKey().getEffectName().equals("J₂ clock relativity")).count());
90  
91      }
92  
93      @Test
94      public void testRelativisticClockCorrection() {
95  
96          // Measurement
97          final double wavelength = PredefinedGnssSignal.G01.getWavelength();
98          final OneWayGNSSPhase phase = new OneWayGNSSPhase(states[1].getOrbit(), "remote",
99                                                            new QuadraticClockModel(date, 0.0, 0.0, 0.0), date,
100                                                           Vector3D.distance(states[0].getPosition(),
101                                                                             states[1].getPosition()) / wavelength,
102                                                           wavelength, 1.0, 1.0, new ObservableSatellite(0),
103                                                           new AmbiguityCache());
104 
105         // One-way GNSS phase before applying the modifier
106         final EstimatedMeasurementBase<OneWayGNSSPhase> estimatedBefore = phase.estimateWithoutDerivatives(states);
107 
108         // One-way GNSS phase before applying the modifier
109         final EstimationModifier<OneWayGNSSPhase> modifier = new RelativisticJ2ClockOneWayGNSSPhaseModifier(Constants.WGS84_EARTH_MU,
110                                                                                                             Constants.WGS84_EARTH_C20, Constants.WGS84_EARTH_EQUATORIAL_RADIUS );
111         phase.addModifier(modifier);
112         final EstimatedMeasurement<OneWayGNSSPhase> estimatedAfter = phase.estimate(0, 0, states);
113 
114         // Verify : According to Teunissen and Montenbruck, the delay is supposed to be around 62 ps for Galileo.
115         //          The computed value is equal to 67.284 ps, therefore lying in the supposed range.
116         Assertions.assertEquals(-0.106217, estimatedBefore.getEstimatedValue()[0] - estimatedAfter.getEstimatedValue()[0], 1.0e-6);
117         Assertions.assertEquals(0, modifier.getParametersDrivers().size());
118 
119     }
120 
121     @BeforeEach
122     public void setUp() {
123         // Data root
124         Utils.setDataRoot("regular-data");
125 
126         // Date
127         date = new AbsoluteDate("2004-01-13T00:00:00.000", TimeScalesFactory.getUTC());
128 
129         // Spacecraft states
130         states = new SpacecraftState[2];
131         final TLE local = new TLE("1 27642U 03002A   04013.91734903  .00000108  00000-0  12227-4 0  3621",
132                                   "2 27642  93.9970   6.8623 0003169  80.1383 280.0205 14.90871424 54508");
133         final TLE remote = new TLE("1 20061U 89044A   04013.44391333  .00000095  00000-0  10000-3 0  3242",
134                                    "2 20061  53.4233 172.2072 0234017 261.4179  95.8975  2.00577231106949");
135         states[0] = TLEPropagator.selectExtrapolator(local).propagate(date);
136         states[1] = TLEPropagator.selectExtrapolator(remote).propagate(date);
137     }
138 
139 }