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.HashMap;
21 import java.util.Map;
22
23 import org.hipparchus.Field;
24 import org.hipparchus.analysis.differentiation.DSFactory;
25 import org.hipparchus.analysis.differentiation.DerivativeStructure;
26 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
27 import org.orekit.frames.FieldTransform;
28 import org.orekit.propagation.SpacecraftState;
29 import org.orekit.time.AbsoluteDate;
30 import org.orekit.time.FieldAbsoluteDate;
31 import org.orekit.utils.ParameterDriver;
32 import org.orekit.utils.TimeStampedFieldPVCoordinates;
33 import org.orekit.utils.TimeStampedPVCoordinates;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class RangeRate extends AbstractMeasurement<RangeRate> {
50
51
52 private final GroundStation station;
53
54
55 private final boolean twoway;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 @Deprecated
73 public RangeRate(final GroundStation station, final AbsoluteDate date,
74 final double rangeRate,
75 final double sigma,
76 final double baseWeight,
77 final boolean twoway) {
78 this(station, date, rangeRate, sigma, baseWeight, twoway, new ObservableSatellite(0));
79 }
80
81
82
83
84
85
86
87
88
89
90
91
92
93 @Deprecated
94 public RangeRate(final GroundStation station, final AbsoluteDate date,
95 final double rangeRate,
96 final double sigma,
97 final double baseWeight,
98 final boolean twoway,
99 final int propagatorIndex) {
100 this(station, date, rangeRate, sigma, baseWeight, twoway, new ObservableSatellite(propagatorIndex));
101 }
102
103
104
105
106
107
108
109
110
111
112
113 public RangeRate(final GroundStation station, final AbsoluteDate date,
114 final double rangeRate, final double sigma, final double baseWeight,
115 final boolean twoway, final ObservableSatellite satellite) {
116 super(date, rangeRate, sigma, baseWeight, Arrays.asList(satellite));
117 addParameterDriver(station.getClockOffsetDriver());
118 addParameterDriver(station.getEastOffsetDriver());
119 addParameterDriver(station.getNorthOffsetDriver());
120 addParameterDriver(station.getZenithOffsetDriver());
121 addParameterDriver(station.getPrimeMeridianOffsetDriver());
122 addParameterDriver(station.getPrimeMeridianDriftDriver());
123 addParameterDriver(station.getPolarOffsetXDriver());
124 addParameterDriver(station.getPolarDriftXDriver());
125 addParameterDriver(station.getPolarOffsetYDriver());
126 addParameterDriver(station.getPolarDriftYDriver());
127 this.station = station;
128 this.twoway = twoway;
129 }
130
131
132
133
134 public boolean isTwoWay() {
135 return twoway;
136 }
137
138
139
140
141 public GroundStation getStation() {
142 return station;
143 }
144
145
146 @Override
147 protected EstimatedMeasurement<RangeRate> theoreticalEvaluation(final int iteration, final int evaluation,
148 final SpacecraftState[] states) {
149
150 final ObservableSatellite satellite = getSatellites().get(0);
151 final SpacecraftState state = states[satellite.getPropagatorIndex()];
152
153
154
155
156
157
158
159
160
161 int nbParams = 6;
162 final Map<String, Integer> indices = new HashMap<>();
163 for (ParameterDriver driver : getParametersDrivers()) {
164 if (driver.isSelected()) {
165 indices.put(driver.getName(), nbParams++);
166 }
167 }
168 final DSFactory factory = new DSFactory(nbParams, 1);
169 final Field<DerivativeStructure> field = factory.getDerivativeField();
170 final FieldVector3D<DerivativeStructure> zero = FieldVector3D.getZero(field);
171
172
173 final TimeStampedFieldPVCoordinates<DerivativeStructure> pvaDS = getCoordinates(state, 0, factory);
174
175
176
177 final FieldTransform<DerivativeStructure> offsetToInertialDownlink =
178 station.getOffsetToInertial(state.getFrame(), getDate(), factory, indices);
179 final FieldAbsoluteDate<DerivativeStructure> downlinkDateDS =
180 offsetToInertialDownlink.getFieldDate();
181
182
183 final TimeStampedFieldPVCoordinates<DerivativeStructure> stationDownlink =
184 offsetToInertialDownlink.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(downlinkDateDS,
185 zero, zero, zero));
186
187
188
189
190
191
192 final DerivativeStructure tauD = signalTimeOfFlight(pvaDS, stationDownlink.getPosition(), downlinkDateDS);
193
194
195 final DerivativeStructure delta = downlinkDateDS.durationFrom(state.getDate());
196 final DerivativeStructure deltaMTauD = tauD.negate().add(delta);
197 final SpacecraftState transitState = state.shiftedBy(deltaMTauD.getValue());
198
199
200 final TimeStampedFieldPVCoordinates<DerivativeStructure> transitPV = pvaDS.shiftedBy(deltaMTauD);
201
202
203 final EstimatedMeasurement<RangeRate> evalOneWay1 =
204 oneWayTheoreticalEvaluation(iteration, evaluation, true,
205 stationDownlink, transitPV, transitState, indices);
206 final EstimatedMeasurement<RangeRate> estimated;
207 if (twoway) {
208
209 final FieldTransform<DerivativeStructure> offsetToInertialApproxUplink =
210 station.getOffsetToInertial(state.getFrame(),
211 downlinkDateDS.shiftedBy(tauD.multiply(-2)), factory, indices);
212 final FieldAbsoluteDate<DerivativeStructure> approxUplinkDateDS =
213 offsetToInertialApproxUplink.getFieldDate();
214
215 final TimeStampedFieldPVCoordinates<DerivativeStructure> stationApproxUplink =
216 offsetToInertialApproxUplink.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(approxUplinkDateDS,
217 zero, zero, zero));
218
219 final DerivativeStructure tauU = signalTimeOfFlight(stationApproxUplink, transitPV.getPosition(), transitPV.getDate());
220
221 final TimeStampedFieldPVCoordinates<DerivativeStructure> stationUplink =
222 stationApproxUplink.shiftedBy(transitPV.getDate().durationFrom(approxUplinkDateDS).subtract(tauU));
223
224 final EstimatedMeasurement<RangeRate> evalOneWay2 =
225 oneWayTheoreticalEvaluation(iteration, evaluation, false,
226 stationUplink, transitPV, transitState, indices);
227
228
229 estimated = new EstimatedMeasurement<>(this, iteration, evaluation,
230 evalOneWay1.getStates(),
231 new TimeStampedPVCoordinates[] {
232 evalOneWay2.getParticipants()[0],
233 evalOneWay1.getParticipants()[0],
234 evalOneWay1.getParticipants()[1]
235 });
236 estimated.setEstimatedValue(0.5 * (evalOneWay1.getEstimatedValue()[0] + evalOneWay2.getEstimatedValue()[0]));
237
238
239 final double[][] sd1 = evalOneWay1.getStateDerivatives(0);
240 final double[][] sd2 = evalOneWay2.getStateDerivatives(0);
241 final double[][] sd = new double[sd1.length][sd1[0].length];
242 for (int i = 0; i < sd.length; ++i) {
243 for (int j = 0; j < sd[0].length; ++j) {
244 sd[i][j] = 0.5 * (sd1[i][j] + sd2[i][j]);
245 }
246 }
247 estimated.setStateDerivatives(0, sd);
248
249
250 evalOneWay1.getDerivativesDrivers().forEach(driver -> {
251 final double[] pd1 = evalOneWay1.getParameterDerivatives(driver);
252 final double[] pd2 = evalOneWay2.getParameterDerivatives(driver);
253 final double[] pd = new double[pd1.length];
254 for (int i = 0; i < pd.length; ++i) {
255 pd[i] = 0.5 * (pd1[i] + pd2[i]);
256 }
257 estimated.setParameterDerivatives(driver, pd);
258 });
259
260 } else {
261 estimated = evalOneWay1;
262 }
263
264 return estimated;
265
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279 private EstimatedMeasurement<RangeRate> oneWayTheoreticalEvaluation(final int iteration, final int evaluation, final boolean downlink,
280 final TimeStampedFieldPVCoordinates<DerivativeStructure> stationPV,
281 final TimeStampedFieldPVCoordinates<DerivativeStructure> transitPV,
282 final SpacecraftState transitState,
283 final Map<String, Integer> indices) {
284
285
286 final EstimatedMeasurement<RangeRate> estimated =
287 new EstimatedMeasurement<RangeRate>(this, iteration, evaluation,
288 new SpacecraftState[] {
289 transitState
290 }, new TimeStampedPVCoordinates[] {
291 (downlink ? transitPV : stationPV).toTimeStampedPVCoordinates(),
292 (downlink ? stationPV : transitPV).toTimeStampedPVCoordinates()
293 });
294
295
296 final FieldVector3D<DerivativeStructure> stationPosition = stationPV.getPosition();
297 final FieldVector3D<DerivativeStructure> relativePosition = stationPosition.subtract(transitPV.getPosition());
298
299 final FieldVector3D<DerivativeStructure> stationVelocity = stationPV.getVelocity();
300 final FieldVector3D<DerivativeStructure> relativeVelocity = stationVelocity.subtract(transitPV.getVelocity());
301
302
303 final FieldVector3D<DerivativeStructure> lineOfSight = relativePosition.normalize();
304
305
306 final DerivativeStructure rangeRate = FieldVector3D.dotProduct(relativeVelocity, lineOfSight);
307
308 estimated.setEstimatedValue(rangeRate.getValue());
309
310
311 final double[] derivatives = rangeRate.getAllDerivatives();
312 estimated.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 1, 7));
313
314
315
316 for (final ParameterDriver driver : getParametersDrivers()) {
317 final Integer index = indices.get(driver.getName());
318 if (index != null) {
319 estimated.setParameterDerivatives(driver, derivatives[index + 1]);
320 }
321 }
322
323 return estimated;
324
325 }
326
327 }