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