1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.ssa.collision.shorttermencounter.probability.twod;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22 import org.hipparchus.geometry.euclidean.twod.FieldVector2D;
23 import org.hipparchus.geometry.euclidean.twod.Vector2D;
24 import org.hipparchus.linear.Array2DRowFieldMatrix;
25 import org.hipparchus.linear.BlockFieldMatrix;
26 import org.hipparchus.linear.FieldLUDecomposition;
27 import org.hipparchus.linear.FieldMatrix;
28 import org.hipparchus.util.FastMath;
29 import org.hipparchus.util.MathArrays;
30 import org.hipparchus.util.MathUtils;
31 import org.orekit.errors.OrekitException;
32 import org.orekit.errors.OrekitMessages;
33 import org.orekit.frames.FieldKinematicTransform;
34 import org.orekit.frames.FieldStaticTransform;
35 import org.orekit.frames.FieldTransform;
36 import org.orekit.frames.Frame;
37 import org.orekit.frames.LOF;
38 import org.orekit.frames.LOFType;
39 import org.orekit.frames.encounter.EncounterLOF;
40 import org.orekit.frames.encounter.EncounterLOFType;
41 import org.orekit.orbits.FieldOrbit;
42 import org.orekit.orbits.OrbitType;
43 import org.orekit.orbits.PositionAngleType;
44 import org.orekit.propagation.FieldStateCovariance;
45 import org.orekit.time.FieldAbsoluteDate;
46 import org.orekit.utils.FieldPVCoordinates;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 public class FieldShortTermEncounter2DDefinition<T extends CalculusFieldElement<T>> {
77
78
79 private static final double DEFAULT_ZERO_THRESHOLD = 1e-15;
80
81
82 private final Field<T> instanceField;
83
84
85
86
87
88
89 private final FieldAbsoluteDate<T> tca;
90
91
92 private final FieldOrbit<T> referenceAtTCA;
93
94
95 private final FieldStateCovariance<T> referenceCovariance;
96
97
98 private final FieldOrbit<T> otherAtTCA;
99
100
101 private final FieldStateCovariance<T> otherCovariance;
102
103
104 private final T combinedRadius;
105
106
107 private final EncounterLOF encounterFrame;
108
109
110
111
112
113
114
115
116
117
118
119
120
121 public FieldShortTermEncounter2DDefinition(final FieldOrbit<T> referenceAtTCA,
122 final FieldStateCovariance<T> referenceCovariance,
123 final T referenceRadius,
124 final FieldOrbit<T> otherAtTCA,
125 final FieldStateCovariance<T> otherCovariance,
126 final T otherRadius) {
127 this(referenceAtTCA, referenceCovariance, otherAtTCA, otherCovariance, referenceRadius.add(otherRadius));
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141 public FieldShortTermEncounter2DDefinition(final FieldOrbit<T> referenceAtTCA,
142 final FieldStateCovariance<T> referenceCovariance,
143 final FieldOrbit<T> otherAtTCA,
144 final FieldStateCovariance<T> otherCovariance,
145 final T combinedRadius) {
146 this(referenceAtTCA, referenceCovariance, otherAtTCA, otherCovariance, combinedRadius,
147 EncounterLOFType.DEFAULT, 1e-6);
148 }
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 public FieldShortTermEncounter2DDefinition(final FieldOrbit<T> referenceAtTCA,
165 final FieldStateCovariance<T> referenceCovariance,
166 final T referenceRadius,
167 final FieldOrbit<T> otherAtTCA,
168 final FieldStateCovariance<T> otherCovariance,
169 final T otherRadius,
170 final EncounterLOFType encounterFrameType,
171 final double tcaTolerance) {
172 this(referenceAtTCA, referenceCovariance, otherAtTCA, otherCovariance, referenceRadius.add(otherRadius),
173 encounterFrameType, tcaTolerance);
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189 public FieldShortTermEncounter2DDefinition(final FieldOrbit<T> referenceAtTCA,
190 final FieldStateCovariance<T> referenceCovariance,
191 final FieldOrbit<T> otherAtTCA,
192 final FieldStateCovariance<T> otherCovariance,
193 final T combinedRadius,
194 final EncounterLOFType encounterFrameType,
195 final double tcaTolerance) {
196
197 if (referenceAtTCA.getDate().isCloseTo(otherAtTCA.getDate(), tcaTolerance)) {
198
199 this.tca = referenceAtTCA.getDate();
200 this.instanceField = tca.getField();
201
202 this.referenceAtTCA = referenceAtTCA;
203 this.referenceCovariance = referenceCovariance;
204
205 this.otherAtTCA = otherAtTCA;
206 this.otherCovariance = otherCovariance;
207
208 this.combinedRadius = combinedRadius;
209
210 this.encounterFrame = encounterFrameType.getFrame(otherAtTCA.getPVCoordinates());
211 } else {
212 throw new OrekitException(OrekitMessages.DIFFERENT_TIME_OF_CLOSEST_APPROACH);
213 }
214
215 }
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230 public static <T extends CalculusFieldElement<T>> T computeSquaredMahalanobisDistance(final T xm, final T ym,
231 final T sigmaX, final T sigmaY) {
232
233 final T[][] positionData = MathArrays.buildArray(xm.getField(), 2, 1);
234 positionData[0][0] = xm;
235 positionData[1][0] = ym;
236 final FieldVector2D<T> position = new FieldVector2D<>(xm, ym);
237
238 final T[][] covarianceMatrixData = MathArrays.buildArray(sigmaX.getField(), 2, 2);
239 covarianceMatrixData[0][0] = sigmaX.multiply(sigmaX);
240 covarianceMatrixData[1][1] = sigmaY.multiply(sigmaY);
241 final FieldMatrix<T> covariance = new BlockFieldMatrix<>(covarianceMatrixData);
242
243 return computeSquaredMahalanobisDistance(position, covariance);
244 }
245
246
247
248
249
250
251
252
253
254
255
256 public static <T extends CalculusFieldElement<T>> T computeSquaredMahalanobisDistance(
257 final FieldVector2D<T> otherPosition,
258 final FieldMatrix<T> covarianceMatrix) {
259
260 final FieldMatrix<T> covarianceMatrixInverse = new FieldLUDecomposition<>(covarianceMatrix).getSolver().getInverse();
261
262 final FieldMatrix<T> otherPositionOnCollisionPlaneMatrix = new Array2DRowFieldMatrix<>(otherPosition.toArray());
263
264 return otherPositionOnCollisionPlaneMatrix.transposeMultiply(
265 covarianceMatrixInverse.multiply(otherPositionOnCollisionPlaneMatrix)).getEntry(0, 0);
266 }
267
268
269
270
271
272
273
274
275 public FieldPVCoordinates<T> computeOtherRelativeToReferencePVInReferenceInertial() {
276
277
278 final Frame referenceInertial = referenceAtTCA.getFrame();
279
280
281 final FieldPVCoordinates<T> referencePV = referenceAtTCA.getPVCoordinates();
282 final FieldKinematicTransform<T> kinematicTransform = otherAtTCA.getFrame()
283 .getKinematicTransformTo(referenceInertial, referenceAtTCA.getDate());
284 final FieldPVCoordinates<T> otherPVInReferenceInertial = kinematicTransform
285 .transformOnlyPV(otherAtTCA.getPVCoordinates());
286
287
288 final FieldVector3D<T> relativePosition = otherPVInReferenceInertial.getPosition()
289 .subtract(referencePV.getPosition());
290 final FieldVector3D<T> relativeVelocity = otherPVInReferenceInertial.getVelocity()
291 .subtract(referencePV.getVelocity());
292
293 return new FieldPVCoordinates<>(relativePosition, relativeVelocity);
294 }
295
296
297
298
299
300
301
302
303
304
305 public FieldMatrix<T> computeReferenceInertialToCollisionPlaneProjectionMatrix() {
306
307
308 final FieldStaticTransform<T> referenceInertialToEncounterFrameTransform =
309 FieldStaticTransform.compose(tca,
310 computeReferenceInertialToReferenceTNWTransform(),
311 computeReferenceTNWToEncounterFrameTransform());
312
313
314 final FieldMatrix<T> referenceInertialToEncounterFrameRotationMatrix =
315 new Array2DRowFieldMatrix<>(referenceInertialToEncounterFrameTransform.getRotation().getMatrix());
316
317
318 final FieldMatrix<T> encounterFrameToCollisionPlaneProjectionMatrix =
319 encounterFrame.computeProjectionMatrix(tca.getField());
320
321
322 return encounterFrameToCollisionPlaneProjectionMatrix.multiply(referenceInertialToEncounterFrameRotationMatrix);
323 }
324
325
326
327
328
329
330
331
332
333 public FieldMatrix<T> computeProjectedAndDiagonalizedCombinedPositionalCovarianceMatrix() {
334
335 final FieldMatrix<T> covarianceMatrixToDiagonalize = computeProjectedCombinedPositionalCovarianceMatrix();
336
337 final T sigmaXSquared = covarianceMatrixToDiagonalize.getEntry(0, 0);
338 final T sigmaYSquared = covarianceMatrixToDiagonalize.getEntry(1, 1);
339
340 final T crossTerm = covarianceMatrixToDiagonalize.getEntry(0, 1);
341 final T recurrentTerm = sigmaXSquared.subtract(sigmaYSquared).multiply(0.5).pow(2)
342 .add(crossTerm.square()).sqrt();
343
344 final T eigenValueX = sigmaXSquared.add(sigmaYSquared).multiply(0.5).subtract(recurrentTerm);
345 final T eigenValueY = sigmaXSquared.add(sigmaYSquared).multiply(0.5).add(recurrentTerm);
346
347 final FieldMatrix<T> projectedAndDiagonalizedCombinedPositionalCovarianceMatrix =
348 new BlockFieldMatrix<>(instanceField, 2, 2);
349 projectedAndDiagonalizedCombinedPositionalCovarianceMatrix.setEntry(0, 0, eigenValueX);
350 projectedAndDiagonalizedCombinedPositionalCovarianceMatrix.setEntry(0, 1, instanceField.getZero());
351 projectedAndDiagonalizedCombinedPositionalCovarianceMatrix.setEntry(1, 0, instanceField.getZero());
352 projectedAndDiagonalizedCombinedPositionalCovarianceMatrix.setEntry(1, 1, eigenValueY);
353
354 return projectedAndDiagonalizedCombinedPositionalCovarianceMatrix;
355 }
356
357
358
359
360
361
362 public FieldMatrix<T> computeProjectedCombinedPositionalCovarianceMatrix() {
363
364
365 final FieldMatrix<T> combinedPositionalCovarianceMatrixInEncounterFrame =
366 computeCombinedCovarianceInEncounterFrame().getMatrix().getSubMatrix(0, 2, 0, 2);
367
368
369 return encounterFrame.projectOntoCollisionPlane(combinedPositionalCovarianceMatrixInEncounterFrame);
370 }
371
372
373
374
375
376
377 public FieldStateCovariance<T> computeCombinedCovarianceInEncounterFrame() {
378 return computeCombinedCovarianceInReferenceTNW().changeCovarianceFrame(referenceAtTCA, encounterFrame);
379 }
380
381
382
383
384
385
386 public FieldVector2D<T> computeOtherPositionInCollisionPlane() {
387
388
389 final FieldVector3D<T> otherInReferenceInertial = otherAtTCA.getPosition(referenceAtTCA.getFrame());
390
391
392 final FieldVector3D<T> otherPositionInReferenceTNW =
393 computeReferenceInertialToReferenceTNWTransform().transformPosition(otherInReferenceInertial);
394
395
396 final FieldVector3D<T> otherPositionInEncounterFrame =
397 computeReferenceTNWToEncounterFrameTransform().transformPosition(otherPositionInReferenceTNW);
398
399 return encounterFrame.projectOntoCollisionPlane(otherPositionInEncounterFrame);
400
401 }
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 public FieldVector2D<T> computeOtherPositionInRotatedCollisionPlane() {
418 return computeOtherPositionInRotatedCollisionPlane(DEFAULT_ZERO_THRESHOLD);
419
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433
434 public FieldVector2D<T> computeOtherPositionInRotatedCollisionPlane(final double zeroThreshold) {
435
436
437 final FieldMatrix<T> otherPositionInCollisionPlaneMatrix =
438 new Array2DRowFieldMatrix<>(computeOtherPositionInCollisionPlane().toArray());
439
440
441 final FieldMatrix<T> otherPositionRotatedInCollisionPlane =
442 computeEncounterPlaneRotationMatrix(zeroThreshold).multiply(otherPositionInCollisionPlaneMatrix);
443
444 return new FieldVector2D<>(otherPositionRotatedInCollisionPlane.getColumn(0));
445
446 }
447
448
449
450
451
452
453
454
455
456
457
458
459 public T computeCoppolaEncounterDuration() {
460
461
462 final T DEFAULT_ALPHA_C = instanceField.getZero().newInstance(5.864);
463
464 final FieldMatrix<T> combinedPositionalCovarianceMatrix = computeCombinedCovarianceInEncounterFrame()
465 .getMatrix().getSubMatrix(0, 2, 0, 2);
466
467
468 final FieldMatrix<T> projectionMatrix = encounterFrame.computeProjectionMatrix(instanceField);
469 final FieldMatrix<T> axisNormalToCollisionPlane =
470 new Array2DRowFieldMatrix<>(encounterFrame.getAxisNormalToCollisionPlane(instanceField).toArray());
471 final FieldMatrix<T> offPlaneCrossTermMatrix =
472 projectionMatrix.multiply(combinedPositionalCovarianceMatrix.multiply(axisNormalToCollisionPlane));
473
474
475 final FieldMatrix<T> probabilityDensity =
476 encounterFrame.projectOntoCollisionPlane(combinedPositionalCovarianceMatrix);
477 final FieldMatrix<T> probabilityDensityInverse =
478 new FieldLUDecomposition<>(probabilityDensity).getSolver().getInverse();
479
480
481 final FieldMatrix<T> b = offPlaneCrossTermMatrix.transposeMultiply(probabilityDensityInverse).transpose();
482 final T recurrentTerm = b.multiplyTransposed(b).getEntry(0, 0);
483
484
485 final T sigmaSqNormalToPlan = axisNormalToCollisionPlane.transposeMultiply(
486 combinedPositionalCovarianceMatrix.multiply(axisNormalToCollisionPlane)).getEntry(0, 0);
487 final T sigmaV = sigmaSqNormalToPlan.subtract(b.multiplyTransposed(offPlaneCrossTermMatrix).getEntry(0, 0))
488 .sqrt();
489
490 final T relativeVelocity = computeOtherRelativeToReferencePVInReferenceInertial().getVelocity().getNorm();
491
492 return DEFAULT_ALPHA_C.multiply(sigmaV).multiply(2 * FastMath.sqrt(2)).add(
493 combinedRadius.multiply(recurrentTerm.add(1).sqrt().add(recurrentTerm.sqrt()))).divide(relativeVelocity);
494 }
495
496
497
498
499
500
501 public T computeMissDistance() {
502
503
504 final FieldVector3D<T> referencePositionAtTCA = referenceAtTCA.getPosition();
505 final FieldVector3D<T> otherPositionAtTCA = otherAtTCA.getPosition(referenceAtTCA.getFrame());
506
507
508 final FieldVector3D<T> relativePosition = otherPositionAtTCA.subtract(referencePositionAtTCA);
509
510 return relativePosition.getNorm();
511 }
512
513
514
515
516
517
518
519
520
521
522
523
524 public T computeMahalanobisDistance() {
525 return computeMahalanobisDistance(DEFAULT_ZERO_THRESHOLD);
526 }
527
528
529
530
531
532
533
534
535
536
537
538
539 public T computeMahalanobisDistance(final double zeroThreshold) {
540 return computeSquaredMahalanobisDistance(zeroThreshold).sqrt();
541 }
542
543
544
545
546
547
548
549
550
551
552
553
554 public T computeSquaredMahalanobisDistance() {
555 return computeSquaredMahalanobisDistance(DEFAULT_ZERO_THRESHOLD);
556 }
557
558
559
560
561
562
563
564
565
566
567
568
569 public T computeSquaredMahalanobisDistance(final double zeroThreshold) {
570
571 final FieldMatrix<T> otherPositionAfterRotationInCollisionPlane =
572 new Array2DRowFieldMatrix<>(computeOtherPositionInRotatedCollisionPlane(zeroThreshold).toArray());
573
574 final FieldMatrix<T> inverseCovarianceMatrix =
575 new FieldLUDecomposition<>(
576 computeProjectedAndDiagonalizedCombinedPositionalCovarianceMatrix()).getSolver()
577 .getInverse();
578
579 return otherPositionAfterRotationInCollisionPlane.transpose().multiply(
580 inverseCovarianceMatrix.multiply(
581 otherPositionAfterRotationInCollisionPlane))
582 .getEntry(0, 0);
583 }
584
585
586
587
588 public ShortTermEncounter2DDefinition toEncounter() {
589 return new ShortTermEncounter2DDefinition(referenceAtTCA.toOrbit(), referenceCovariance.toStateCovariance(),
590 otherAtTCA.toOrbit(), otherCovariance.toStateCovariance(),
591 combinedRadius.getReal());
592 }
593
594
595
596
597
598
599
600
601 public FieldStateCovariance<T> computeCombinedCovarianceInReferenceTNW() {
602
603
604 final FieldMatrix<T> referenceCovarianceMatrixInTNW =
605 referenceCovariance.changeCovarianceFrame(referenceAtTCA, LOFType.TNW_INERTIAL).getMatrix();
606
607
608 final FieldMatrix<T> otherCovarianceMatrixInReferenceInertial =
609 otherCovariance.changeCovarianceFrame(otherAtTCA, referenceAtTCA.getFrame()).getMatrix();
610
611 final FieldStateCovariance<T> otherCovarianceInReferenceInertial = new FieldStateCovariance<>(
612 otherCovarianceMatrixInReferenceInertial, tca, referenceAtTCA.getFrame(),
613 OrbitType.CARTESIAN, PositionAngleType.MEAN);
614
615
616 final FieldMatrix<T> otherCovarianceMatrixInReferenceTNW = otherCovarianceInReferenceInertial.changeCovarianceFrame(
617 referenceAtTCA, LOFType.TNW_INERTIAL).getMatrix();
618
619
620 return new FieldStateCovariance<>(referenceCovarianceMatrixInTNW.add(otherCovarianceMatrixInReferenceTNW), tca,
621 LOFType.TNW_INERTIAL);
622 }
623
624
625
626
627
628
629
630 private FieldTransform<T> computeReferenceInertialToReferenceTNWTransform() {
631 return LOFType.TNW.transformFromInertial(tca, referenceAtTCA.getPVCoordinates());
632 }
633
634
635
636
637
638
639
640 private FieldTransform<T> computeReferenceTNWToEncounterFrameTransform() {
641 return LOF.transformFromLOFInToLOFOut(LOFType.TNW_INERTIAL, encounterFrame, tca,
642 referenceAtTCA.getPVCoordinates());
643 }
644
645
646
647
648
649
650
651
652
653 private FieldMatrix<T> computeEncounterPlaneRotationMatrix(final double zeroThreshold) {
654
655 final FieldMatrix<T> combinedCovarianceMatrixInEncounterFrame =
656 computeCombinedCovarianceInEncounterFrame().getMatrix();
657
658 final FieldMatrix<T> combinedPositionalCovarianceMatrixProjectedOntoBPlane =
659 encounterFrame.projectOntoCollisionPlane(
660 combinedCovarianceMatrixInEncounterFrame.getSubMatrix(0, 2, 0, 2));
661
662 final T sigmaXSquared = combinedPositionalCovarianceMatrixProjectedOntoBPlane.getEntry(0, 0);
663 final T sigmaYSquared = combinedPositionalCovarianceMatrixProjectedOntoBPlane.getEntry(1, 1);
664 final T crossTerm = combinedPositionalCovarianceMatrixProjectedOntoBPlane.getEntry(0, 1);
665 final T correlation = crossTerm.divide(sigmaXSquared.multiply(sigmaYSquared).sqrt());
666
667
668 final T theta;
669 if (FastMath.abs(crossTerm).getReal() > zeroThreshold) {
670 final T recurrentTerm = sigmaYSquared.subtract(sigmaXSquared).divide(crossTerm.multiply(2));
671 theta = recurrentTerm.subtract(correlation.sign().multiply(recurrentTerm.pow(2).add(1).sqrt())).atan();
672 }
673
674 else {
675
676 if (sigmaXSquared.subtract(sigmaYSquared).getReal() > 0) {
677 theta = tca.getField().getZero().newInstance(MathUtils.SEMI_PI);
678 }
679
680 else {
681 theta = tca.getField().getZero();
682 }
683 }
684
685 final T cosTheta = theta.cos();
686 final T sinTheta = theta.sin();
687 final Array2DRowFieldMatrix<T> rotationMatrix = new Array2DRowFieldMatrix<>(tca.getField(), 2, 2);
688 rotationMatrix.setEntry(0, 0, cosTheta);
689 rotationMatrix.setEntry(0, 1, sinTheta);
690 rotationMatrix.setEntry(1, 0, sinTheta.negate());
691 rotationMatrix.setEntry(1, 1, cosTheta);
692
693 return rotationMatrix;
694 }
695
696
697
698
699
700
701
702
703 public FieldAbsoluteDate<T> getTca() {
704 return tca;
705 }
706
707
708
709
710 public FieldOrbit<T> getReferenceAtTCA() {
711 return referenceAtTCA;
712 }
713
714
715
716
717 public FieldOrbit<T> getOtherAtTCA() {
718 return otherAtTCA;
719 }
720
721
722
723
724 public FieldStateCovariance<T> getReferenceCovariance() {
725 return referenceCovariance;
726 }
727
728
729
730
731 public FieldStateCovariance<T> getOtherCovariance() {
732 return otherCovariance;
733 }
734
735
736
737
738 public T getCombinedRadius() {
739 return combinedRadius;
740 }
741
742
743
744
745 public EncounterLOF getEncounterFrame() {
746 return encounterFrame;
747 }
748
749 }