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
154 final SpacecraftState state = states[0];
155 final Frame frame = state.getFrame();
156 final TimeStampedPVCoordinates pva = state.getPVCoordinates();
157
158
159 final AbsoluteDate measurementDate = getDate();
160 final Transform offsetToInertialDownlink = getObserver().getOffsetToInertial(frame, measurementDate, false);
161 final AbsoluteDate downlinkDate = offsetToInertialDownlink.getDate();
162
163
164 final TimeStampedPVCoordinates origin = new TimeStampedPVCoordinates(downlinkDate, PVCoordinates.ZERO);
165 final TimeStampedPVCoordinates satelliteDownlink = offsetToInertialDownlink.transformPVCoordinates(origin);
166
167
168 final PVCoordinatesProvider pvCoordinatesProvider = AbstractParticipant.extractPVCoordinatesProvider(states[0], pva);
169
170
171 final AdjustableEmitterSignalTimer signalTimeOfFlight = getSignalTravelTimeModel()
172 .getAdjustableEmitterComputer(pvCoordinatesProvider);
173 final SignalReceptionCondition receptionCondition = new SignalReceptionCondition(downlinkDate,
174 satelliteDownlink.getPosition(), frame);
175 final double tauD = signalTimeOfFlight.computeDelay(receptionCondition, pva.getDate());
176
177
178 final double delta = downlinkDate.durationFrom(state.getDate());
179 final double deltaMTauD = delta - tauD;
180 final SpacecraftState transitState = states[0].shiftedBy(deltaMTauD);
181
182
183 final EstimatedMeasurementBase<Phase> estimated =
184 new EstimatedMeasurementBase<>(this, iteration, evaluation,
185 new SpacecraftState[] {
186 transitState
187 }, new TimeStampedPVCoordinates[] {
188 transitState.getPVCoordinates(), satelliteDownlink
189 });
190
191
192 final ObservableSatellite satellite = getSatellites().getFirst();
193
194 final double dts = satellite.getOffsetValue(state.getDate());
195 final double dtg = getObserver().getOffsetValue(getDate());
196
197
198 final double cOverLambda = Constants.SPEED_OF_LIGHT / wavelength;
199 final double ambiguity = ambiguityDriver.getValue(state.getDate());
200 final double phase = (tauD + dtg - dts) * cOverLambda + ambiguity;
201
202 estimated.setEstimatedValue(phase);
203
204 return estimated;
205
206 }
207
208
209 @Override
210 protected EstimatedMeasurement<Phase> theoreticalEvaluation(final int iteration,
211 final int evaluation,
212 final SpacecraftState[] states) {
213
214 final SpacecraftState state = states[0];
215 final Frame frame = state.getFrame();
216 final Map<String, Integer> paramIndices = getParameterIndices(states);
217 final int nbParams = 6 * states.length + paramIndices.size();
218
219
220 final TimeStampedFieldPVCoordinates<Gradient> pva = AbstractMeasurement.getCoordinates(states[0], 0, nbParams);
221
222
223
224 final FieldTransform<Gradient> offsetToInertialDownlink = getObserver().
225 getOffsetToInertial(frame, getDate(), nbParams, paramIndices);
226 final FieldAbsoluteDate<Gradient> downlinkDate = offsetToInertialDownlink.getFieldDate();
227
228
229 final GradientField field = GradientField.getField(nbParams);
230 final TimeStampedFieldPVCoordinates<Gradient> satelliteDownlink =
231 offsetToInertialDownlink.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(downlinkDate,
232 FieldPVCoordinates.getZero(field)));
233
234
235 final FieldPVCoordinatesProvider<Gradient> fieldPVCoordinatesProvider = AbstractParticipant.extractFieldPVCoordinatesProvider(states[0], pva);
236
237
238 final FieldAdjustableEmitterSignalTimer<Gradient> fieldComputer = getSignalTravelTimeModel()
239 .getFieldAdjustableEmitterComputer(field, fieldPVCoordinatesProvider);
240 final FieldSignalReceptionCondition<Gradient> receptionCondition = new FieldSignalReceptionCondition<>(downlinkDate,
241 satelliteDownlink.getPosition(), frame);
242 final Gradient tauD = fieldComputer.computeDelay(receptionCondition, pva.getDate());
243
244
245 final Gradient delta = downlinkDate.durationFrom(states[0].getDate());
246 final Gradient deltaMTauD = tauD.negate().add(delta);
247 final SpacecraftState transitState = states[0].shiftedBy(deltaMTauD.getValue());
248 final FieldAbsoluteDate<Gradient> fieldDate = new FieldAbsoluteDate<>(field, states[0].getDate()).shiftedBy(deltaMTauD);
249 final TimeStampedFieldPVCoordinates<Gradient> transitPV = fieldPVCoordinatesProvider.getPVCoordinates(fieldDate, frame);
250
251
252 final EstimatedMeasurement<Phase> estimated =
253 new EstimatedMeasurement<>(this, iteration, evaluation,
254 new SpacecraftState[] { transitState},
255 new TimeStampedPVCoordinates[] {
256 transitPV.toTimeStampedPVCoordinates(),
257 satelliteDownlink.toTimeStampedPVCoordinates()});
258
259
260 final ObservableSatellite satellite = getSatellites().getFirst();
261
262 final Gradient dts = satellite.getFieldOffsetValue(nbParams, state.getDate(), paramIndices);
263 final Gradient dtg = getObserver().getFieldOffsetValue(nbParams, getDate(), paramIndices);
264
265
266 final double cOverLambda = Constants.SPEED_OF_LIGHT / wavelength;
267 final Gradient ambiguity = ambiguityDriver.getValue(nbParams, paramIndices, state.getDate());
268 final Gradient phase = tauD.add(dtg).subtract(dts).multiply(cOverLambda).add(ambiguity);
269
270 estimated.setEstimatedValue(phase.getValue());
271
272
273 final double[] derivatives = phase.getGradient();
274 estimated.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 0, 6));
275
276
277 for (final ParameterDriver driver : getParametersDrivers()) {
278 for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
279
280 final Integer index = paramIndices.get(span.getData());
281 if (index != null) {
282 estimated.setParameterDerivatives(driver, span.getStart(), derivatives[index]);
283 }
284 }
285 }
286
287 return estimated;
288
289 }
290
291 }