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.gnss;
18
19 import java.util.Arrays;
20
21 import org.hipparchus.analysis.differentiation.Gradient;
22 import org.orekit.estimation.measurements.EstimatedMeasurement;
23 import org.orekit.estimation.measurements.EstimatedMeasurementBase;
24 import org.orekit.estimation.measurements.InterSatellitesRange;
25 import org.orekit.estimation.measurements.ObservableSatellite;
26 import org.orekit.estimation.measurements.QuadraticClockModel;
27 import org.orekit.propagation.SpacecraftState;
28 import org.orekit.time.AbsoluteDate;
29 import org.orekit.utils.Constants;
30 import org.orekit.utils.PVCoordinatesProvider;
31 import org.orekit.utils.ParameterDriver;
32 import org.orekit.utils.TimeSpanMap.Span;
33 import org.orekit.utils.TimeStampedPVCoordinates;
34
35 /** One-way GNSS range measurement.
36 * <p>
37 * This class can be used in precise orbit determination applications
38 * for modeling a range measurement between a GNSS satellite (emitter)
39 * and a LEO satellite (receiver).
40 * <p>
41 * The one-way GNSS range measurement assumes knowledge of the orbit and
42 * the clock offset of the emitting GNSS satellite. For instance, it is
43 * possible to use a SP3 file or a GNSS navigation message to recover
44 * the satellite's orbit and clock.
45 * <p>
46 * This class is very similar to {@link InterSatellitesRange} measurement
47 * class. However, using the one-way GNSS range measurement, the orbit and clock
48 * of the emitting GNSS satellite are <b>NOT</b> estimated simultaneously with
49 * LEO satellite coordinates.
50 *
51 * @author Bryan Cazabonne
52 * @since 10.3
53 */
54 public class OneWayGNSSRange extends AbstractOneWayGNSSMeasurement<OneWayGNSSRange> {
55
56 /** Type of the measurement. */
57 public static final String MEASUREMENT_TYPE = "OneWayGNSSRange";
58
59 /** Simple constructor.
60 * @param remote provider for GNSS satellite which simply emits the signal
61 * @param dtRemote clock offset of the GNSS satellite, in seconds
62 * @param date date of the measurement
63 * @param range observed value
64 * @param sigma theoretical standard deviation
65 * @param baseWeight base weight
66 * @param local satellite which receives the signal and perform the measurement
67 */
68 public OneWayGNSSRange(final PVCoordinatesProvider remote,
69 final double dtRemote,
70 final AbsoluteDate date,
71 final double range, final double sigma,
72 final double baseWeight, final ObservableSatellite local) {
73 this(remote, new QuadraticClockModel(date, dtRemote, 0.0, 0.0), date, range, sigma, baseWeight, local);
74 }
75
76 /** Simple constructor.
77 * @param remote provider for GNSS satellite which simply emits the signal
78 * @param remoteClock clock offset of the GNSS satellite
79 * @param date date of the measurement
80 * @param range observed value
81 * @param sigma theoretical standard deviation
82 * @param baseWeight base weight
83 * @param local satellite which receives the signal and perform the measurement
84 * @since 12.1
85 */
86 public OneWayGNSSRange(final PVCoordinatesProvider remote,
87 final QuadraticClockModel remoteClock,
88 final AbsoluteDate date,
89 final double range, final double sigma,
90 final double baseWeight, final ObservableSatellite local) {
91 // Call super constructor
92 super(remote, remoteClock, date, range, sigma, baseWeight, local);
93 }
94
95 /** {@inheritDoc} */
96 @Override
97 protected EstimatedMeasurementBase<OneWayGNSSRange> theoreticalEvaluationWithoutDerivatives(final int iteration,
98 final int evaluation,
99 final SpacecraftState[] states) {
100
101
102 final OnBoardCommonParametersWithoutDerivatives common = computeCommonParametersWithout(states, false);
103
104 // Estimated measurement
105 final EstimatedMeasurementBase<OneWayGNSSRange> estimatedRange =
106 new EstimatedMeasurementBase<>(this, iteration, evaluation,
107 new SpacecraftState[] {
108 common.getState()
109 }, new TimeStampedPVCoordinates[] {
110 common.getRemotePV(),
111 common.getTransitPV()
112 });
113
114 // Range value
115 final double range = (common.getTauD() + common.getLocalOffset() - common.getRemoteOffset()) *
116 Constants.SPEED_OF_LIGHT;
117
118 // Set value of the estimated measurement
119 estimatedRange.setEstimatedValue(range);
120
121 // Return the estimated measurement
122 return estimatedRange;
123
124 }
125
126 /** {@inheritDoc} */
127 @Override
128 protected EstimatedMeasurement<OneWayGNSSRange> theoreticalEvaluation(final int iteration,
129 final int evaluation,
130 final SpacecraftState[] states) {
131
132 final OnBoardCommonParametersWithDerivatives common = computeCommonParametersWith(states, false);
133
134 // Estimated measurement
135 final EstimatedMeasurement<OneWayGNSSRange> estimatedRange =
136 new EstimatedMeasurement<>(this, iteration, evaluation,
137 new SpacecraftState[] {
138 common.getState()
139 }, new TimeStampedPVCoordinates[] {
140 common.getRemotePV().toTimeStampedPVCoordinates(),
141 common.getTransitPV().toTimeStampedPVCoordinates()
142 });
143
144 // Range value
145 final Gradient range = common.getTauD().add(common.getLocalOffset()).subtract(common.getRemoteOffset()).
146 multiply(Constants.SPEED_OF_LIGHT);
147 final double[] rangeDerivatives = range.getGradient();
148
149 // Set value and state first order derivatives of the estimated measurement
150 estimatedRange.setEstimatedValue(range.getValue());
151 estimatedRange.setStateDerivatives(0, Arrays.copyOfRange(rangeDerivatives, 0, 6));
152
153 // Set first order derivatives with respect to parameters
154 for (final ParameterDriver measurementDriver : getParametersDrivers()) {
155 for (Span<String> span = measurementDriver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
156
157 final Integer index = common.getIndices().get(span.getData());
158 if (index != null) {
159 estimatedRange.setParameterDerivatives(measurementDriver, span.getStart(), rangeDerivatives[index]);
160 }
161 }
162 }
163
164 // Return the estimated measurement
165 return estimatedRange;
166
167 }
168
169 }