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.analysis.differentiation.Gradient;
24 import org.hipparchus.analysis.differentiation.GradientField;
25 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26 import org.hipparchus.geometry.euclidean.threed.Rotation;
27 import org.hipparchus.geometry.euclidean.threed.Vector3D;
28 import org.orekit.frames.FieldTransform;
29 import org.orekit.frames.Transform;
30 import org.orekit.propagation.SpacecraftState;
31 import org.orekit.time.AbsoluteDate;
32 import org.orekit.time.FieldAbsoluteDate;
33 import org.orekit.utils.AngularCoordinates;
34 import org.orekit.utils.Constants;
35 import org.orekit.utils.PVCoordinates;
36 import org.orekit.utils.ParameterDriver;
37 import org.orekit.utils.TimeStampedFieldPVCoordinates;
38 import org.orekit.utils.TimeStampedPVCoordinates;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 public class RangeAnalytic extends Range {
63
64
65
66
67 public RangeAnalytic(final Range range) {
68 super(range.getStation(), true, range.getDate(), range.getObservedValue()[0],
69 range.getTheoreticalStandardDeviation()[0],
70 range.getBaseWeight()[0],
71 new ObservableSatellite(0));
72 }
73
74
75
76
77
78
79
80
81
82
83 protected EstimatedMeasurement<Range> theoreticalEvaluationAnalytic(final int iteration, final int evaluation,
84 final SpacecraftState state) {
85
86
87 final GroundStation groundStation = this.getStation();
88
89
90 final AbsoluteDate downlinkDate = getDate();
91 final Transform topoToInertDownlink =
92 groundStation.getOffsetToInertial(state.getFrame(), downlinkDate);
93 final TimeStampedPVCoordinates stationDownlink =
94 topoToInertDownlink.transformPVCoordinates(new TimeStampedPVCoordinates(downlinkDate,
95 PVCoordinates.ZERO));
96
97
98
99
100
101
102 final double tauD = signalTimeOfFlight(state.getPVCoordinates(),
103 stationDownlink.getPosition(),
104 downlinkDate);
105 final double delta = downlinkDate.durationFrom(state.getDate());
106 final double dt = delta - tauD;
107
108
109 final SpacecraftState transitState = state.shiftedBy(dt);
110 final AbsoluteDate transitDate = transitState.getDate();
111 final Vector3D transitP = transitState.getPVCoordinates().getPosition();
112
113
114 final Transform topoToInertAtTransitDate =
115 groundStation.getOffsetToInertial(state.getFrame(), transitDate);
116 final TimeStampedPVCoordinates stationAtTransitDate = topoToInertAtTransitDate.
117 transformPVCoordinates(new TimeStampedPVCoordinates(transitDate, PVCoordinates.ZERO));
118
119
120 final double tauU = signalTimeOfFlight(stationAtTransitDate, transitP, transitDate);
121 final double tau = tauD + tauU;
122
123
124 final AbsoluteDate uplinkDate = downlinkDate.shiftedBy(-tau);
125 final TimeStampedPVCoordinates stationUplink = topoToInertDownlink.shiftedBy(-tau).
126 transformPVCoordinates(new TimeStampedPVCoordinates(uplinkDate, PVCoordinates.ZERO));
127
128
129 final EstimatedMeasurement<Range> estimated =
130 new EstimatedMeasurement<Range>(this, iteration, evaluation,
131 new SpacecraftState[] {
132 transitState
133 }, new TimeStampedPVCoordinates[] {
134 stationUplink,
135 transitState.getPVCoordinates(),
136 stationDownlink
137 });
138
139
140 final double cOver2 = 0.5 * Constants.SPEED_OF_LIGHT;
141 estimated.setEstimatedValue(tau * cOver2);
142
143
144
145
146
147
148 final Vector3D v = state.getPVCoordinates().getVelocity();
149 final Vector3D qv = stationDownlink.getVelocity();
150 final Vector3D downInert = stationDownlink.getPosition().subtract(transitP);
151 final double dDown = Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT * tauD -
152 Vector3D.dotProduct(downInert, v);
153 final Vector3D upInert = transitP.subtract(stationUplink.getPosition());
154
155
156
157
158
159 final double dUp = Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT * tauU -
160 Vector3D.dotProduct(upInert, stationUplink.getVelocity());
161
162
163
164 final double dTauDdPx = -downInert.getX() / dDown;
165 final double dTauDdPy = -downInert.getY() / dDown;
166 final double dTauDdPz = -downInert.getZ() / dDown;
167
168
169
170 final double dTauUdPx = 1./dUp*upInert
171 .dotProduct(Vector3D.PLUS_I
172 .add((qv.subtract(v))
173 .scalarMultiply(dTauDdPx)));
174 final double dTauUdPy = 1./dUp*upInert
175 .dotProduct(Vector3D.PLUS_J
176 .add((qv.subtract(v))
177 .scalarMultiply(dTauDdPy)));
178 final double dTauUdPz = 1./dUp*upInert
179 .dotProduct(Vector3D.PLUS_K
180 .add((qv.subtract(v))
181 .scalarMultiply(dTauDdPz)));
182
183
184
185 final double dRdPx = (dTauDdPx + dTauUdPx) * cOver2;
186 final double dRdPy = (dTauDdPy + dTauUdPy) * cOver2;
187 final double dRdPz = (dTauDdPz + dTauUdPz) * cOver2;
188 estimated.setStateDerivatives(0, new double[] {
189 dRdPx, dRdPy, dRdPz,
190 dRdPx * dt, dRdPy * dt, dRdPz * dt
191 });
192
193 if (groundStation.getClockOffsetDriver().isSelected() ||
194 groundStation.getEastOffsetDriver().isSelected() ||
195 groundStation.getNorthOffsetDriver().isSelected() ||
196 groundStation.getZenithOffsetDriver().isSelected()) {
197
198
199 final AngularCoordinates ac = topoToInertDownlink.getAngular().revert();
200
201 final Vector3D omega = ac.getRotationRate();
202
203
204 final double dTauDdQIx = downInert.getX()/dDown;
205 final double dTauDdQIy = downInert.getY()/dDown;
206 final double dTauDdQIz = downInert.getZ()/dDown;
207
208
209
210 final double dTauUdQIx = 1/dUp*upInert
211 .dotProduct(Vector3D.MINUS_I
212 .add((qv.subtract(v)).scalarMultiply(dTauDdQIx))
213 .subtract(Vector3D.PLUS_I.crossProduct(omega).scalarMultiply(tau)));
214 final double dTauUdQIy = 1/dUp*upInert
215 .dotProduct(Vector3D.MINUS_J
216 .add((qv.subtract(v)).scalarMultiply(dTauDdQIy))
217 .subtract(Vector3D.PLUS_J.crossProduct(omega).scalarMultiply(tau)));
218 final double dTauUdQIz = 1/dUp*upInert
219 .dotProduct(Vector3D.MINUS_K
220 .add((qv.subtract(v)).scalarMultiply(dTauDdQIz))
221 .subtract(Vector3D.PLUS_K.crossProduct(omega).scalarMultiply(tau)));
222
223
224
225
226 final Vector3D dRdQI = new Vector3D((dTauDdQIx + dTauUdQIx) * cOver2,
227 (dTauDdQIy + dTauUdQIy) * cOver2,
228 (dTauDdQIz + dTauUdQIz) * cOver2);
229
230
231
232 final Vector3D dRdQT = ac.getRotation().applyTo(dRdQI);
233
234 if (groundStation.getEastOffsetDriver().isSelected()) {
235 estimated.setParameterDerivatives(groundStation.getEastOffsetDriver(), dRdQT.getX());
236 }
237 if (groundStation.getNorthOffsetDriver().isSelected()) {
238 estimated.setParameterDerivatives(groundStation.getNorthOffsetDriver(), dRdQT.getY());
239 }
240 if (groundStation.getZenithOffsetDriver().isSelected()) {
241 estimated.setParameterDerivatives(groundStation.getZenithOffsetDriver(), dRdQT.getZ());
242 }
243
244 }
245
246 return estimated;
247
248 }
249
250
251
252
253
254
255
256
257
258
259 protected EstimatedMeasurement<Range> theoreticalEvaluationValidation(final int iteration, final int evaluation,
260 final SpacecraftState state) {
261
262
263 final GroundStation groundStation = getStation();
264
265
266 int nbParams = 6;
267 final Map<String, Integer> indices = new HashMap<>();
268 for (ParameterDriver driver : getParametersDrivers()) {
269 if (driver.isSelected()) {
270 indices.put(driver.getName(), nbParams++);
271 }
272 }
273 final FieldVector3D<Gradient> zero = FieldVector3D.getZero(GradientField.getField(nbParams));
274
275
276
277
278
279
280
281
282
283
284
285 final TimeStampedFieldPVCoordinates<Gradient> pvaDS = getCoordinates(state, 0, nbParams);
286
287
288
289 final AbsoluteDate downlinkDate = getDate();
290 final FieldTransform<Gradient> offsetToInertialDownlink =
291 groundStation.getOffsetToInertial(state.getFrame(), downlinkDate, nbParams, indices);
292 final FieldAbsoluteDate<Gradient> downlinkDateDS =
293 offsetToInertialDownlink.getFieldDate();
294
295
296 final TimeStampedFieldPVCoordinates<Gradient> stationDownlink =
297 offsetToInertialDownlink.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(downlinkDateDS,
298 zero, zero, zero));
299
300
301
302
303
304
305
306 final Gradient tauD = signalTimeOfFlight(pvaDS, stationDownlink.getPosition(), downlinkDateDS);
307
308
309 final double delta = downlinkDate.durationFrom(state.getDate());
310 final Gradient tauDMDelta = tauD.negate().add(delta);
311 final SpacecraftState transitState = state.shiftedBy(tauDMDelta.getValue());
312
313
314 final TimeStampedFieldPVCoordinates<Gradient> transitStateDS = pvaDS.shiftedBy(tauDMDelta);
315
316
317 final TimeStampedFieldPVCoordinates<Gradient> stationAtTransitDate =
318 stationDownlink.shiftedBy(tauD.negate());
319
320 final Gradient tauU =
321 signalTimeOfFlight(stationAtTransitDate, transitStateDS.getPosition(), transitStateDS.getDate());
322
323
324 final EstimatedMeasurement<Range> estimated =
325 new EstimatedMeasurement<Range>(this, iteration, evaluation,
326 new SpacecraftState[] {
327 transitState
328 }, null);
329
330
331 final Gradient tau = tauD.add(tauU);
332 final double cOver2 = 0.5 * Constants.SPEED_OF_LIGHT;
333 final Gradient range = tau.multiply(cOver2);
334 estimated.setEstimatedValue(range.getValue());
335
336
337 final double[] derivatives = range.getGradient();
338 estimated.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 0, 6));
339
340
341
342 for (final ParameterDriver driver : getParametersDrivers()) {
343 final Integer index = indices.get(driver.getName());
344 if (index != null) {
345 estimated.setParameterDerivatives(driver, derivatives[index]);
346 }
347 }
348
349
350
351
352
353
354
355
356
357
358
359 final Transform topoToInertDownlink =
360 groundStation.getOffsetToInertial(state.getFrame(), downlinkDate);
361 final PVCoordinates QDownlink = topoToInertDownlink.
362 transformPVCoordinates(PVCoordinates.ZERO);
363
364
365 final double td = signalTimeOfFlight(state.getPVCoordinates(), QDownlink.getPosition(), downlinkDate);
366 final double dt = delta - td;
367
368
369 final AbsoluteDate transitT = state.getDate().shiftedBy(dt);
370 final SpacecraftState transit = state.shiftedBy(dt);
371 final Vector3D transitP = transitState.getPVCoordinates().getPosition();
372
373
374
375
376
377
378
379
380
381
382 final Transform topoToInertAtTransitDate =
383 groundStation.getOffsetToInertial(state.getFrame(), transitT);
384 TimeStampedPVCoordinates QAtTransitDate = topoToInertAtTransitDate.
385 transformPVCoordinates(new TimeStampedPVCoordinates(transitT, PVCoordinates.ZERO));
386
387
388 final double tu = signalTimeOfFlight(QAtTransitDate, transitP, transitT);
389
390
391 final double t = td + tu;
392
393
394 AbsoluteDate uplinkDate = downlinkDate.shiftedBy(-t);
395
396 TimeStampedPVCoordinates QUplink = topoToInertDownlink.shiftedBy(-t).
397 transformPVCoordinates(new TimeStampedPVCoordinates(uplinkDate, PVCoordinates.ZERO));
398
399
400
401 double r = t * cOver2;
402 double dR = r-range.getValue();
403
404
405
406
407
408
409
410 final Vector3D vel = state.getPVCoordinates().getVelocity();
411 final Vector3D Qt_V = QDownlink.getVelocity();
412 final Vector3D Ptr = transit.getPVCoordinates().getPosition();
413 final Vector3D Ptr_Qt = QDownlink.getPosition().subtract(Ptr);
414 final double dDown = Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT * td -
415 Vector3D.dotProduct(Ptr_Qt, vel);
416
417
418 final double dtddPx = -Ptr_Qt.getX() / dDown;
419 final double dtddPy = -Ptr_Qt.getY() / dDown;
420 final double dtddPz = -Ptr_Qt.getZ() / dDown;
421
422 final double dtddVx = dtddPx*dt;
423 final double dtddVy = dtddPy*dt;
424 final double dtddVz = dtddPz*dt;
425
426
427 final double dtddPxDS = tauD.getPartialDerivative(0);
428 final double dtddPyDS = tauD.getPartialDerivative(1);
429 final double dtddPzDS = tauD.getPartialDerivative(2);
430 final double dtddVxDS = tauD.getPartialDerivative(3);
431 final double dtddVyDS = tauD.getPartialDerivative(4);
432 final double dtddVzDS = tauD.getPartialDerivative(5);
433
434
435 final double d_dtddPx = dtddPxDS-dtddPx;
436 final double d_dtddPy = dtddPyDS-dtddPy;
437 final double d_dtddPz = dtddPzDS-dtddPz;
438 final double d_dtddVx = dtddVxDS-dtddVx;
439 final double d_dtddVy = dtddVyDS-dtddVy;
440 final double d_dtddVz = dtddVzDS-dtddVz;
441
442
443
444
445
446
447
448 final Vector3D Qt2_Ptr = Ptr.subtract(QUplink.getPosition());
449 final double dUp = Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT * tu -
450 Vector3D.dotProduct(Qt2_Ptr, Qt_V);
451
452
453
454
455
456
457
458
459
460
461
462 final double dtudPx = 1./dUp*Qt2_Ptr
463 .dotProduct(Vector3D.PLUS_I
464 .add((Qt_V.subtract(vel))
465 .scalarMultiply(dtddPx)));
466 final double dtudPy = 1./dUp*Qt2_Ptr
467 .dotProduct(Vector3D.PLUS_J
468 .add((Qt_V.subtract(vel))
469 .scalarMultiply(dtddPy)));
470 final double dtudPz = 1./dUp*Qt2_Ptr
471 .dotProduct(Vector3D.PLUS_K
472 .add((Qt_V.subtract(vel))
473 .scalarMultiply(dtddPz)));
474
475 final double dtudVx = dtudPx*dt;
476 final double dtudVy = dtudPy*dt;
477 final double dtudVz = dtudPz*dt;
478
479
480
481 final double dtudPxDS = tauU.getPartialDerivative(0);
482 final double dtudPyDS = tauU.getPartialDerivative(1);
483 final double dtudPzDS = tauU.getPartialDerivative(2);
484 final double dtudVxDS = tauU.getPartialDerivative(3);
485 final double dtudVyDS = tauU.getPartialDerivative(4);
486 final double dtudVzDS = tauU.getPartialDerivative(5);
487
488
489 final double d_dtudPx = dtudPxDS-dtudPx;
490 final double d_dtudPy = dtudPyDS-dtudPy;
491 final double d_dtudPz = dtudPzDS-dtudPz;
492 final double d_dtudVx = dtudVxDS-dtudVx;
493 final double d_dtudVy = dtudVyDS-dtudVy;
494 final double d_dtudVz = dtudVzDS-dtudVz;
495
496
497
498
499
500
501 double dRdPx = (dtddPx + dtudPx)*cOver2;
502 double dRdPy = (dtddPy + dtudPy)*cOver2;
503 double dRdPz = (dtddPz + dtudPz)*cOver2;
504 double dRdVx = (dtddVx + dtudVx)*cOver2;
505 double dRdVy = (dtddVy + dtudVy)*cOver2;
506 double dRdVz = (dtddVz + dtudVz)*cOver2;
507
508
509 double dRdPxDS = range.getPartialDerivative(0);
510 double dRdPyDS = range.getPartialDerivative(1);
511 double dRdPzDS = range.getPartialDerivative(2);
512 double dRdVxDS = range.getPartialDerivative(3);
513 double dRdVyDS = range.getPartialDerivative(4);
514 double dRdVzDS = range.getPartialDerivative(5);
515
516
517 final double d_dRdPx = dRdPxDS-dRdPx;
518 final double d_dRdPy = dRdPyDS-dRdPy;
519 final double d_dRdPz = dRdPzDS-dRdPz;
520 final double d_dRdVx = dRdVxDS-dRdVx;
521 final double d_dRdVy = dRdVyDS-dRdVy;
522 final double d_dRdVz = dRdVzDS-dRdVz;
523
524
525
526
527
528 final AngularCoordinates ac = topoToInertDownlink.getAngular().revert();
529 final Rotation rotTopoToInert = ac.getRotation();
530 final Vector3D omega = ac.getRotationRate();
531
532 final Vector3D dtddQI = Ptr_Qt.scalarMultiply(1./dDown);
533 final double dtddQIx = dtddQI.getX();
534 final double dtddQIy = dtddQI.getY();
535 final double dtddQIz = dtddQI.getZ();
536
537 final Vector3D dtddQ = rotTopoToInert.applyTo(dtddQI);
538
539
540 double dtddQxDS = tauD.getPartialDerivative(6);
541 double dtddQyDS = tauD.getPartialDerivative(7);
542 double dtddQzDS = tauD.getPartialDerivative(8);
543
544
545 final double d_dtddQx = dtddQxDS-dtddQ.getX();
546 final double d_dtddQy = dtddQyDS-dtddQ.getY();
547 final double d_dtddQz = dtddQzDS-dtddQ.getZ();
548
549
550
551
552
553
554 final double dtudQIx = 1/dUp*Qt2_Ptr
555 .dotProduct(Vector3D.MINUS_I
556 .add((Qt_V.subtract(vel)).scalarMultiply(dtddQIx))
557 .subtract(Vector3D.PLUS_I.crossProduct(omega).scalarMultiply(t)));
558 final double dtudQIy = 1/dUp*Qt2_Ptr
559 .dotProduct(Vector3D.MINUS_J
560 .add((Qt_V.subtract(vel)).scalarMultiply(dtddQIy))
561 .subtract(Vector3D.PLUS_J.crossProduct(omega).scalarMultiply(t)));
562 final double dtudQIz = 1/dUp*Qt2_Ptr
563 .dotProduct(Vector3D.MINUS_K
564 .add((Qt_V.subtract(vel)).scalarMultiply(dtddQIz))
565 .subtract(Vector3D.PLUS_K.crossProduct(omega).scalarMultiply(t)));
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592 final Vector3D dtudQI = new Vector3D(dtudQIx, dtudQIy, dtudQIz);
593 final Vector3D dtudQ = rotTopoToInert.applyTo(dtudQI);
594
595
596
597 double dtudQxDS = tauU.getPartialDerivative(6);
598 double dtudQyDS = tauU.getPartialDerivative(7);
599 double dtudQzDS = tauU.getPartialDerivative(8);
600
601
602 final double d_dtudQx = dtudQxDS-dtudQ.getX();
603 final double d_dtudQy = dtudQyDS-dtudQ.getY();
604 final double d_dtudQz = dtudQzDS-dtudQ.getZ();
605
606
607
608
609
610 double dRdQx = (dtddQ.getX() + dtudQ.getX())*cOver2;
611 double dRdQy = (dtddQ.getY() + dtudQ.getY())*cOver2;
612 double dRdQz = (dtddQ.getZ() + dtudQ.getZ())*cOver2;
613
614
615 double dRdQxDS = range.getPartialDerivative(6);
616 double dRdQyDS = range.getPartialDerivative(7);
617 double dRdQzDS = range.getPartialDerivative(8);
618
619
620 final double d_dRdQx = dRdQxDS-dRdQx;
621 final double d_dRdQy = dRdQyDS-dRdQy;
622 final double d_dRdQz = dRdQzDS-dRdQz;
623
624
625
626 final boolean printResults = false;
627
628 if (printResults) {
629 System.out.println("dR = " + dR);
630
631 System.out.println("d_dtddPx = " + d_dtddPx);
632 System.out.println("d_dtddPy = " + d_dtddPy);
633 System.out.println("d_dtddPz = " + d_dtddPz);
634 System.out.println("d_dtddVx = " + d_dtddVx);
635 System.out.println("d_dtddVy = " + d_dtddVy);
636 System.out.println("d_dtddVz = " + d_dtddVz);
637
638 System.out.println("d_dtudPx = " + d_dtudPx);
639 System.out.println("d_dtudPy = " + d_dtudPy);
640 System.out.println("d_dtudPz = " + d_dtudPz);
641 System.out.println("d_dtudVx = " + d_dtudVx);
642 System.out.println("d_dtudVy = " + d_dtudVy);
643 System.out.println("d_dtudVz = " + d_dtudVz);
644
645 System.out.println("d_dRdPx = " + d_dRdPx);
646 System.out.println("d_dRdPy = " + d_dRdPy);
647 System.out.println("d_dRdPz = " + d_dRdPz);
648 System.out.println("d_dRdVx = " + d_dRdVx);
649 System.out.println("d_dRdVy = " + d_dRdVy);
650 System.out.println("d_dRdVz = " + d_dRdVz);
651
652 System.out.println("d_dtddQx = " + d_dtddQx);
653 System.out.println("d_dtddQy = " + d_dtddQy);
654 System.out.println("d_dtddQz = " + d_dtddQz);
655
656 System.out.println("d_dtudQx = " + d_dtudQx);
657 System.out.println("d_dtudQy = " + d_dtudQy);
658 System.out.println("d_dtudQz = " + d_dtudQz);
659
660 System.out.println("d_dRdQx = " + d_dRdQx);
661 System.out.println("d_dRdQy = " + d_dRdQy);
662 System.out.println("d_dRdQz = " + d_dRdQz);
663
664 }
665
666
667 return estimated;
668
669 }
670 }