1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements.gnss;
18
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.Map;
22
23 import org.hipparchus.analysis.differentiation.Gradient;
24 import org.hipparchus.analysis.differentiation.GradientField;
25 import org.orekit.estimation.measurements.AbstractMeasurement;
26 import org.orekit.estimation.measurements.AbstractParticipant;
27 import org.orekit.estimation.measurements.EstimatedMeasurement;
28 import org.orekit.estimation.measurements.EstimatedMeasurementBase;
29 import org.orekit.estimation.measurements.MeasurementQuality;
30 import org.orekit.estimation.measurements.ObservableSatellite;
31 import org.orekit.estimation.measurements.Observer;
32 import org.orekit.estimation.measurements.SignalBasedMeasurement;
33 import org.orekit.frames.FieldTransform;
34 import org.orekit.frames.Frame;
35 import org.orekit.frames.Transform;
36 import org.orekit.propagation.SpacecraftState;
37 import org.orekit.signal.AdjustableEmitterSignalTimer;
38 import org.orekit.signal.FieldAdjustableEmitterSignalTimer;
39 import org.orekit.signal.FieldSignalReceptionCondition;
40 import org.orekit.signal.SignalReceptionCondition;
41 import org.orekit.signal.SignalTravelTimeModel;
42 import org.orekit.time.AbsoluteDate;
43 import org.orekit.time.FieldAbsoluteDate;
44 import org.orekit.utils.Constants;
45 import org.orekit.utils.FieldPVCoordinates;
46 import org.orekit.utils.FieldPVCoordinatesProvider;
47 import org.orekit.utils.PVCoordinates;
48 import org.orekit.utils.PVCoordinatesProvider;
49 import org.orekit.utils.ParameterDriver;
50 import org.orekit.utils.TimeSpanMap.Span;
51 import org.orekit.utils.TimeStampedFieldPVCoordinates;
52 import org.orekit.utils.TimeStampedPVCoordinates;
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 public class Phase extends SignalBasedMeasurement<Phase> {
70
71
72 public static final String MEASUREMENT_TYPE = "Phase";
73
74
75 private final AmbiguityDriver ambiguityDriver;
76
77
78 private final double wavelength;
79
80
81 private final Observer observer;
82
83
84
85
86
87
88
89
90
91
92
93
94 public Phase(final Observer observer, final AbsoluteDate date,
95 final double phase, final double wavelength, final double sigma,
96 final double baseWeight, final ObservableSatellite satellite,
97 final AmbiguityCache cache) {
98 this(observer, date, phase, wavelength, new MeasurementQuality(sigma, baseWeight), new SignalTravelTimeModel(),
99 satellite, cache);
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113 public Phase(final Observer observer, final AbsoluteDate date,
114 final double phase, final double wavelength, final MeasurementQuality measurementQuality,
115 final SignalTravelTimeModel signalTravelTimeModel, final ObservableSatellite satellite,
116 final AmbiguityCache cache) {
117 super(date, false, phase, measurementQuality, signalTravelTimeModel,
118 Collections.singletonList(satellite));
119 ambiguityDriver = cache.getAmbiguity(satellite.getName(), observer.getName(), wavelength);
120 addParametersDrivers(observer.getParametersDrivers());
121 addParameterDriver(ambiguityDriver);
122 this.observer = observer;
123 this.wavelength = wavelength;
124 }
125
126
127
128
129 public final Observer getObserver() {
130 return observer;
131 }
132
133
134
135
136 public double getWavelength() {
137 return wavelength;
138 }
139
140
141
142
143
144 public AmbiguityDriver getAmbiguityDriver() {
145 return ambiguityDriver;
146 }
147
148
149 @Override
150 protected EstimatedMeasurementBase<Phase> theoreticalEvaluationWithoutDerivatives(final int iteration,
151 final int evaluation,
152 final SpacecraftState[] states,
153 final boolean fillParticipants) {
154
155 final SpacecraftState state = states[0];
156 final Frame frame = state.getFrame();
157 final TimeStampedPVCoordinates pva = state.getPVCoordinates();
158
159
160 final AbsoluteDate measurementDate = getDate();
161 final Transform offsetToInertialDownlink = getObserver().getOffsetToInertial(frame, measurementDate, false);
162 final AbsoluteDate downlinkDate = offsetToInertialDownlink.getDate();
163
164
165 final TimeStampedPVCoordinates origin = new TimeStampedPVCoordinates(downlinkDate, PVCoordinates.ZERO);
166 final TimeStampedPVCoordinates satelliteDownlink = offsetToInertialDownlink.transformPVCoordinates(origin);
167
168
169 final PVCoordinatesProvider pvCoordinatesProvider = AbstractParticipant.extractPVCoordinatesProvider(states[0], pva);
170
171
172 final AdjustableEmitterSignalTimer signalTimeOfFlight = getSignalTravelTimeModel()
173 .getAdjustableEmitterComputer(pvCoordinatesProvider);
174 final SignalReceptionCondition receptionCondition = new SignalReceptionCondition(downlinkDate,
175 satelliteDownlink.getPosition(), frame);
176 final double tauD = signalTimeOfFlight.computeDelay(receptionCondition, pva.getDate());
177
178
179 final double delta = downlinkDate.durationFrom(state.getDate());
180 final double deltaMTauD = delta - tauD;
181 final SpacecraftState transitState = states[0].shiftedBy(deltaMTauD);
182
183
184 final EstimatedMeasurementBase<Phase> estimated = new EstimatedMeasurementBase<>(this, iteration, evaluation,
185 new SpacecraftState[] { transitState }, fillParticipants ? new TimeStampedPVCoordinates[] {
186 transitState.getPVCoordinates(), satelliteDownlink } : new TimeStampedPVCoordinates[0]);
187
188
189 final ObservableSatellite satellite = getSatellites().getFirst();
190
191 final double dts = satellite.getOffsetValue(state.getDate());
192 final double dtg = getObserver().getOffsetValue(getDate());
193
194
195 final double cOverLambda = Constants.SPEED_OF_LIGHT / wavelength;
196 final double ambiguity = ambiguityDriver.getValue(state.getDate());
197 final double phase = (tauD + dtg - dts) * cOverLambda + ambiguity;
198
199 estimated.setEstimatedValue(phase);
200
201 return estimated;
202
203 }
204
205
206 @Override
207 protected EstimatedMeasurement<Phase> theoreticalEvaluation(final int iteration,
208 final int evaluation,
209 final SpacecraftState[] states) {
210
211 final SpacecraftState state = states[0];
212 final Frame frame = state.getFrame();
213 final Map<String, Integer> paramIndices = getParameterIndices(states);
214 final int nbParams = 6 * states.length + paramIndices.size();
215
216
217 final TimeStampedFieldPVCoordinates<Gradient> pva = AbstractMeasurement.getCoordinates(states[0], 0, nbParams);
218
219
220
221 final FieldTransform<Gradient> offsetToInertialDownlink = getObserver().
222 getOffsetToInertial(frame, getDate(), nbParams, paramIndices);
223 final FieldAbsoluteDate<Gradient> downlinkDate = offsetToInertialDownlink.getFieldDate();
224
225
226 final GradientField field = GradientField.getField(nbParams);
227 final TimeStampedFieldPVCoordinates<Gradient> satelliteDownlink =
228 offsetToInertialDownlink.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(downlinkDate,
229 FieldPVCoordinates.getZero(field)));
230
231
232 final FieldPVCoordinatesProvider<Gradient> fieldPVCoordinatesProvider = AbstractParticipant.extractFieldPVCoordinatesProvider(states[0], pva);
233
234
235 final FieldAdjustableEmitterSignalTimer<Gradient> fieldComputer = getSignalTravelTimeModel()
236 .getFieldAdjustableEmitterComputer(field, fieldPVCoordinatesProvider);
237 final FieldSignalReceptionCondition<Gradient> receptionCondition = new FieldSignalReceptionCondition<>(downlinkDate,
238 satelliteDownlink.getPosition(), frame);
239 final Gradient tauD = fieldComputer.computeDelay(receptionCondition, pva.getDate());
240
241
242 final Gradient delta = downlinkDate.durationFrom(states[0].getDate());
243 final Gradient deltaMTauD = tauD.negate().add(delta);
244 final SpacecraftState transitState = states[0].shiftedBy(deltaMTauD.getValue());
245 final FieldAbsoluteDate<Gradient> fieldDate = new FieldAbsoluteDate<>(field, states[0].getDate()).shiftedBy(deltaMTauD);
246 final TimeStampedFieldPVCoordinates<Gradient> transitPV = fieldPVCoordinatesProvider.getPVCoordinates(fieldDate, frame);
247
248
249 final EstimatedMeasurement<Phase> estimated =
250 new EstimatedMeasurement<>(this, iteration, evaluation,
251 new SpacecraftState[] { transitState},
252 new TimeStampedPVCoordinates[] {
253 transitPV.toTimeStampedPVCoordinates(),
254 satelliteDownlink.toTimeStampedPVCoordinates()});
255
256
257 final ObservableSatellite satellite = getSatellites().getFirst();
258
259 final Gradient dts = satellite.getFieldOffsetValue(nbParams, state.getDate(), paramIndices);
260 final Gradient dtg = getObserver().getFieldOffsetValue(nbParams, getDate(), paramIndices);
261
262
263 final double cOverLambda = Constants.SPEED_OF_LIGHT / wavelength;
264 final Gradient ambiguity = ambiguityDriver.getValue(nbParams, paramIndices, state.getDate());
265 final Gradient phase = tauD.add(dtg).subtract(dts).multiply(cOverLambda).add(ambiguity);
266
267 estimated.setEstimatedValue(phase.getValue());
268
269
270 final double[] derivatives = phase.getGradient();
271 estimated.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 0, 6));
272
273
274 for (final ParameterDriver driver : getParametersDrivers()) {
275 for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
276
277 final Integer index = paramIndices.get(span.getData());
278 if (index != null) {
279 estimated.setParameterDerivatives(driver, span.getStart(), derivatives[index]);
280 }
281 }
282 }
283
284 return estimated;
285
286 }
287
288 }