1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements;
18
19 import java.util.Arrays;
20 import java.util.Map;
21
22 import org.hipparchus.analysis.differentiation.Gradient;
23 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24 import org.hipparchus.geometry.euclidean.threed.Vector3D;
25 import org.orekit.frames.FieldTransform;
26 import org.orekit.frames.Transform;
27 import org.orekit.propagation.SpacecraftState;
28 import org.orekit.time.AbsoluteDate;
29 import org.orekit.time.FieldAbsoluteDate;
30 import org.orekit.utils.Constants;
31 import org.orekit.utils.ParameterDriver;
32 import org.orekit.utils.TimeSpanMap.Span;
33 import org.orekit.utils.TimeStampedFieldPVCoordinates;
34 import org.orekit.utils.TimeStampedPVCoordinates;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class RangeRate extends GroundReceiverMeasurement<RangeRate> {
51
52
53 public static final String MEASUREMENT_TYPE = "RangeRate";
54
55
56
57
58
59
60
61
62
63
64
65 public RangeRate(final GroundStation station, final AbsoluteDate date,
66 final double rangeRate, final double sigma, final double baseWeight,
67 final boolean twoway, final ObservableSatellite satellite) {
68 super(station, twoway, date, rangeRate, sigma, baseWeight, satellite);
69 }
70
71
72 @Override
73 protected EstimatedMeasurementBase<RangeRate> theoreticalEvaluationWithoutDerivatives(final int iteration,
74 final int evaluation,
75 final SpacecraftState[] states) {
76
77 final GroundReceiverCommonParametersWithoutDerivatives common = computeCommonParametersWithout(states[0]);
78 final TimeStampedPVCoordinates transitPV = common.getTransitPV();
79
80
81 final EstimatedMeasurementBase<RangeRate> evalOneWay1 =
82 oneWayTheoreticalEvaluation(iteration, evaluation, true,
83 common.getStationDownlink(),
84 transitPV,
85 common.getTransitState());
86 final EstimatedMeasurementBase<RangeRate> estimated;
87 if (isTwoWay()) {
88
89 final Transform offsetToInertialApproxUplink =
90 getStation().getOffsetToInertial(common.getState().getFrame(),
91 common.getStationDownlink().getDate().shiftedBy(-2 * common.getTauD()),
92 false);
93 final AbsoluteDate approxUplinkDate = offsetToInertialApproxUplink.getDate();
94
95 final TimeStampedPVCoordinates stationApproxUplink =
96 offsetToInertialApproxUplink.transformPVCoordinates(new TimeStampedPVCoordinates(approxUplinkDate,
97 Vector3D.ZERO, Vector3D.ZERO, Vector3D.ZERO));
98
99 final double tauU = signalTimeOfFlightAdjustableEmitter(stationApproxUplink, transitPV.getPosition(),
100 transitPV.getDate(), common.getState().getFrame());
101
102 final TimeStampedPVCoordinates stationUplink =
103 stationApproxUplink.shiftedBy(transitPV.getDate().durationFrom(approxUplinkDate) - tauU);
104
105 final EstimatedMeasurementBase<RangeRate> evalOneWay2 =
106 oneWayTheoreticalEvaluation(iteration, evaluation, false,
107 stationUplink, transitPV, common.getTransitState());
108
109
110 estimated = new EstimatedMeasurementBase<>(this, iteration, evaluation,
111 evalOneWay1.getStates(),
112 new TimeStampedPVCoordinates[] {
113 evalOneWay2.getParticipants()[0],
114 evalOneWay1.getParticipants()[0],
115 evalOneWay1.getParticipants()[1]
116 });
117 estimated.setEstimatedValue(0.5 * (evalOneWay1.getEstimatedValue()[0] + evalOneWay2.getEstimatedValue()[0]));
118
119 } else {
120 estimated = evalOneWay1;
121 }
122
123 return estimated;
124
125 }
126
127
128 @Override
129 protected EstimatedMeasurement<RangeRate> theoreticalEvaluation(final int iteration, final int evaluation,
130 final SpacecraftState[] states) {
131
132 final SpacecraftState state = states[0];
133
134
135
136
137
138
139
140
141
142 final GroundReceiverCommonParametersWithDerivatives common = computeCommonParametersWithDerivatives(state);
143 final int nbParams = common.getTauD().getFreeParameters();
144 final TimeStampedFieldPVCoordinates<Gradient> transitPV = common.getTransitPV();
145
146
147 final EstimatedMeasurement<RangeRate> evalOneWay1 =
148 oneWayTheoreticalEvaluation(iteration, evaluation, true,
149 common.getStationDownlink(), transitPV,
150 common.getTransitState(), common.getIndices(), nbParams);
151 final EstimatedMeasurement<RangeRate> estimated;
152 if (isTwoWay()) {
153
154 final FieldTransform<Gradient> offsetToInertialApproxUplink =
155 getStation().getOffsetToInertial(state.getFrame(),
156 common.getStationDownlink().getDate().shiftedBy(common.getTauD().multiply(-2)),
157 nbParams, common.getIndices());
158 final FieldAbsoluteDate<Gradient> approxUplinkDateDS =
159 offsetToInertialApproxUplink.getFieldDate();
160
161 final FieldVector3D<Gradient> zero = FieldVector3D.getZero(common.getTauD().getField());
162 final TimeStampedFieldPVCoordinates<Gradient> stationApproxUplink =
163 offsetToInertialApproxUplink.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(approxUplinkDateDS,
164 zero, zero, zero));
165
166 final Gradient tauU = signalTimeOfFlightAdjustableEmitter(stationApproxUplink, transitPV.getPosition(), transitPV.getDate(),
167 state.getFrame());
168
169 final TimeStampedFieldPVCoordinates<Gradient> stationUplink =
170 stationApproxUplink.shiftedBy(transitPV.getDate().durationFrom(approxUplinkDateDS).subtract(tauU));
171
172 final EstimatedMeasurement<RangeRate> evalOneWay2 =
173 oneWayTheoreticalEvaluation(iteration, evaluation, false,
174 stationUplink, transitPV, common.getTransitState(),
175 common.getIndices(), nbParams);
176
177
178 estimated = new EstimatedMeasurement<>(this, iteration, evaluation,
179 evalOneWay1.getStates(),
180 new TimeStampedPVCoordinates[] {
181 evalOneWay2.getParticipants()[0],
182 evalOneWay1.getParticipants()[0],
183 evalOneWay1.getParticipants()[1]
184 });
185 estimated.setEstimatedValue(0.5 * (evalOneWay1.getEstimatedValue()[0] + evalOneWay2.getEstimatedValue()[0]));
186
187
188 final double[][] sd1 = evalOneWay1.getStateDerivatives(0);
189 final double[][] sd2 = evalOneWay2.getStateDerivatives(0);
190 final double[][] sd = new double[sd1.length][sd1[0].length];
191 for (int i = 0; i < sd.length; ++i) {
192 for (int j = 0; j < sd[0].length; ++j) {
193 sd[i][j] = 0.5 * (sd1[i][j] + sd2[i][j]);
194 }
195 }
196 estimated.setStateDerivatives(0, sd);
197
198
199 evalOneWay1.getDerivativesDrivers().forEach(driver -> {
200 for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
201 final double[] pd1 = evalOneWay1.getParameterDerivatives(driver, span.getStart());
202 final double[] pd2 = evalOneWay2.getParameterDerivatives(driver, span.getStart());
203 final double[] pd = new double[pd1.length];
204 for (int i = 0; i < pd.length; ++i) {
205 pd[i] = 0.5 * (pd1[i] + pd2[i]);
206 }
207 estimated.setParameterDerivatives(driver, span.getStart(), pd);
208 }
209 });
210
211 } else {
212 estimated = evalOneWay1;
213 }
214
215 return estimated;
216
217 }
218
219
220
221
222
223
224
225
226
227
228
229 private EstimatedMeasurementBase<RangeRate> oneWayTheoreticalEvaluation(final int iteration, final int evaluation, final boolean downlink,
230 final TimeStampedPVCoordinates stationPV,
231 final TimeStampedPVCoordinates transitPV,
232 final SpacecraftState transitState) {
233
234
235 final EstimatedMeasurementBase<RangeRate> estimated =
236 new EstimatedMeasurementBase<>(this, iteration, evaluation,
237 new SpacecraftState[] {
238 transitState
239 }, new TimeStampedPVCoordinates[] {
240 downlink ? transitPV : stationPV,
241 downlink ? stationPV : transitPV
242 });
243
244
245 final Vector3D stationPosition = stationPV.getPosition();
246 final Vector3D relativePosition = stationPosition.subtract(transitPV.getPosition());
247
248 final Vector3D stationVelocity = stationPV.getVelocity();
249 final Vector3D relativeVelocity = stationVelocity.subtract(transitPV.getVelocity());
250
251
252 final Vector3D lineOfSight = relativePosition.normalize();
253
254
255 final double lineOfSightVelocity = Vector3D.dotProduct(relativeVelocity, lineOfSight);
256
257
258 double rangeRate = lineOfSightVelocity;
259
260 if (!isTwoWay()) {
261
262 final ObservableSatellite satellite = getSatellites().get(0);
263 final double dtsDot = satellite.getClockDriftDriver().getValue(transitState.getDate());
264 final double dtgDot = getStation().getClockDriftDriver().getValue(stationPV.getDate());
265
266 final double clockDriftBiais = (dtgDot - dtsDot) * Constants.SPEED_OF_LIGHT;
267
268 rangeRate = rangeRate + clockDriftBiais;
269 }
270
271 estimated.setEstimatedValue(rangeRate);
272
273 return estimated;
274
275 }
276
277
278
279
280
281
282
283
284
285
286
287
288 private EstimatedMeasurement<RangeRate> oneWayTheoreticalEvaluation(final int iteration, final int evaluation, final boolean downlink,
289 final TimeStampedFieldPVCoordinates<Gradient> stationPV,
290 final TimeStampedFieldPVCoordinates<Gradient> transitPV,
291 final SpacecraftState transitState,
292 final Map<String, Integer> indices,
293 final int nbParams) {
294
295
296 final EstimatedMeasurement<RangeRate> estimated =
297 new EstimatedMeasurement<>(this, iteration, evaluation,
298 new SpacecraftState[] {
299 transitState
300 }, new TimeStampedPVCoordinates[] {
301 (downlink ? transitPV : stationPV).toTimeStampedPVCoordinates(),
302 (downlink ? stationPV : transitPV).toTimeStampedPVCoordinates()
303 });
304
305
306 final FieldVector3D<Gradient> stationPosition = stationPV.getPosition();
307 final FieldVector3D<Gradient> relativePosition = stationPosition.subtract(transitPV.getPosition());
308
309 final FieldVector3D<Gradient> stationVelocity = stationPV.getVelocity();
310 final FieldVector3D<Gradient> relativeVelocity = stationVelocity.subtract(transitPV.getVelocity());
311
312
313 final FieldVector3D<Gradient> lineOfSight = relativePosition.normalize();
314
315
316 final Gradient lineOfSightVelocity = FieldVector3D.dotProduct(relativeVelocity, lineOfSight);
317
318
319 Gradient rangeRate = lineOfSightVelocity;
320
321 if (!isTwoWay()) {
322
323 final ObservableSatellite satellite = getSatellites().get(0);
324 final Gradient dtsDot = satellite.getClockDriftDriver().getValue(nbParams, indices, transitState.getDate());
325 final Gradient dtgDot = getStation().getClockDriftDriver().getValue(nbParams, indices, stationPV.getDate().toAbsoluteDate());
326
327 final Gradient clockDriftBiais = dtgDot.subtract(dtsDot).multiply(Constants.SPEED_OF_LIGHT);
328
329 rangeRate = rangeRate.add(clockDriftBiais);
330 }
331
332 estimated.setEstimatedValue(rangeRate.getValue());
333
334
335 final double[] derivatives = rangeRate.getGradient();
336 estimated.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 0, 6));
337
338
339 for (final ParameterDriver driver : getParametersDrivers()) {
340 for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
341 final Integer index = indices.get(span.getData());
342 if (index != null) {
343 estimated.setParameterDerivatives(driver, span.getStart(), derivatives[index]);
344 }
345 }
346 }
347
348 return estimated;
349
350 }
351
352 }