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