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.drivers.ParameterDriver;
50 import org.orekit.utils.TimeStampedFieldPVCoordinates;
51 import org.orekit.utils.TimeStampedPVCoordinates;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public class Phase extends SignalBasedMeasurement<Phase> {
69
70
71 public static final String MEASUREMENT_TYPE = "Phase";
72
73
74 private final AmbiguityDriver ambiguityDriver;
75
76
77 private final double wavelength;
78
79
80 private final Observer observer;
81
82
83
84
85
86
87
88
89
90
91
92
93 public Phase(final Observer observer, final AbsoluteDate date,
94 final double phase, final double wavelength, final double sigma,
95 final double baseWeight, final ObservableSatellite satellite,
96 final AmbiguityCache cache) {
97 this(observer, date, phase, wavelength, new MeasurementQuality(sigma, baseWeight), new SignalTravelTimeModel(),
98 satellite, cache);
99 }
100
101
102
103
104
105
106
107
108
109
110
111
112 public Phase(final Observer observer, final AbsoluteDate date,
113 final double phase, final double wavelength, final MeasurementQuality measurementQuality,
114 final SignalTravelTimeModel signalTravelTimeModel, final ObservableSatellite satellite,
115 final AmbiguityCache cache) {
116 super(date, false, phase, measurementQuality, signalTravelTimeModel,
117 Collections.singletonList(satellite));
118 ambiguityDriver = cache.getAmbiguity(satellite.getName(), observer.getName(), wavelength);
119 addParametersDrivers(observer.getParametersDrivers());
120 addParameterDriver(ambiguityDriver);
121 this.observer = observer;
122 this.wavelength = wavelength;
123 }
124
125
126
127
128 public final Observer getObserver() {
129 return observer;
130 }
131
132
133
134
135 public double getWavelength() {
136 return wavelength;
137 }
138
139
140
141
142
143 public AmbiguityDriver getAmbiguityDriver() {
144 return ambiguityDriver;
145 }
146
147
148 @Override
149 protected EstimatedMeasurementBase<Phase> theoreticalEvaluationWithoutDerivatives(final int iteration,
150 final int evaluation,
151 final SpacecraftState[] states,
152 final boolean fillParticipants) {
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 = new EstimatedMeasurementBase<>(this, iteration, evaluation,
184 new SpacecraftState[] { transitState }, fillParticipants ? new TimeStampedPVCoordinates[] {
185 transitState.getPVCoordinates(), satelliteDownlink } : new TimeStampedPVCoordinates[0]);
186
187
188 final ObservableSatellite satellite = getSatellites().getFirst();
189
190 final double dts = satellite.getOffsetValue(state.getDate());
191 final double dtg = getObserver().getOffsetValue(getDate());
192
193
194 final double cOverLambda = Constants.SPEED_OF_LIGHT / wavelength;
195 final double ambiguity = ambiguityDriver.getValue();
196 final double phase = (tauD + dtg - dts) * cOverLambda + ambiguity;
197
198 estimated.setEstimatedValue(phase);
199
200 return estimated;
201
202 }
203
204
205 @Override
206 protected EstimatedMeasurement<Phase> theoreticalEvaluation(final int iteration,
207 final int evaluation,
208 final SpacecraftState[] states) {
209
210 final SpacecraftState state = states[0];
211 final Frame frame = state.getFrame();
212 final Map<String, Integer> paramIndices = getParameterIndices(states);
213 final int nbParams = 6 * states.length + paramIndices.size();
214
215
216 final TimeStampedFieldPVCoordinates<Gradient> pva = AbstractMeasurement.getCoordinates(states[0], 0, nbParams);
217
218
219
220 final FieldTransform<Gradient> offsetToInertialDownlink = getObserver().
221 getOffsetToInertial(frame, getDate(), nbParams, paramIndices);
222 final FieldAbsoluteDate<Gradient> downlinkDate = offsetToInertialDownlink.getFieldDate();
223
224
225 final GradientField field = GradientField.getField(nbParams);
226 final TimeStampedFieldPVCoordinates<Gradient> satelliteDownlink =
227 offsetToInertialDownlink.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(downlinkDate,
228 FieldPVCoordinates.getZero(field)));
229
230
231 final FieldPVCoordinatesProvider<Gradient> fieldPVCoordinatesProvider = AbstractParticipant.extractFieldPVCoordinatesProvider(states[0], pva);
232
233
234 final FieldAdjustableEmitterSignalTimer<Gradient> fieldComputer = getSignalTravelTimeModel()
235 .getFieldAdjustableEmitterComputer(field, fieldPVCoordinatesProvider);
236 final FieldSignalReceptionCondition<Gradient> receptionCondition = new FieldSignalReceptionCondition<>(downlinkDate,
237 satelliteDownlink.getPosition(), frame);
238 final Gradient tauD = fieldComputer.computeDelay(receptionCondition, pva.getDate());
239
240
241 final Gradient delta = downlinkDate.durationFrom(states[0].getDate());
242 final Gradient deltaMTauD = tauD.negate().add(delta);
243 final SpacecraftState transitState = states[0].shiftedBy(deltaMTauD.getValue());
244 final FieldAbsoluteDate<Gradient> fieldDate = new FieldAbsoluteDate<>(field, states[0].getDate()).shiftedBy(deltaMTauD);
245 final TimeStampedFieldPVCoordinates<Gradient> transitPV = fieldPVCoordinatesProvider.getPVCoordinates(fieldDate, frame);
246
247
248 final EstimatedMeasurement<Phase> estimated =
249 new EstimatedMeasurement<>(this, iteration, evaluation,
250 new SpacecraftState[] { transitState},
251 new TimeStampedPVCoordinates[] {
252 transitPV.toTimeStampedPVCoordinates(),
253 satelliteDownlink.toTimeStampedPVCoordinates()});
254
255
256 final ObservableSatellite satellite = getSatellites().getFirst();
257
258 final Gradient dts = satellite.getFieldOffsetValue(nbParams, paramIndices, state.getDate());
259 final Gradient dtg = getObserver().getFieldOffsetValue(nbParams, paramIndices, getDate());
260
261
262 final double cOverLambda = Constants.SPEED_OF_LIGHT / wavelength;
263 final Gradient ambiguity = ambiguityDriver.getValue(nbParams, paramIndices);
264 final Gradient phase = tauD.add(dtg).subtract(dts).multiply(cOverLambda).add(ambiguity);
265
266 estimated.setEstimatedValue(phase.getValue());
267
268
269 final double[] derivatives = phase.getGradient();
270 estimated.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 0, 6));
271
272
273 for (final ParameterDriver driver : getParametersDrivers()) {
274 final Integer index = paramIndices.get(driver.getName());
275 if (index != null) {
276 estimated.setParameterDerivatives(driver, derivatives[index]);
277 }
278 }
279
280 return estimated;
281
282 }
283
284 }