1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.frames;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collection;
22 import java.util.List;
23 import java.util.stream.Collectors;
24 import java.util.stream.Stream;
25
26 import org.hipparchus.CalculusFieldElement;
27 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
28 import org.hipparchus.geometry.euclidean.threed.Line;
29 import org.hipparchus.geometry.euclidean.threed.Rotation;
30 import org.hipparchus.geometry.euclidean.threed.Vector3D;
31 import org.orekit.time.AbsoluteDate;
32 import org.orekit.time.TimeOffset;
33 import org.orekit.time.TimeInterpolator;
34 import org.orekit.time.TimeShiftable;
35 import org.orekit.utils.AngularCoordinates;
36 import org.orekit.utils.AngularDerivativesFilter;
37 import org.orekit.utils.CartesianDerivativesFilter;
38 import org.orekit.utils.FieldPVCoordinates;
39 import org.orekit.utils.PVCoordinates;
40 import org.orekit.utils.TimeStampedAngularCoordinates;
41 import org.orekit.utils.TimeStampedAngularCoordinatesHermiteInterpolator;
42 import org.orekit.utils.TimeStampedFieldPVCoordinates;
43 import org.orekit.utils.TimeStampedPVCoordinates;
44 import org.orekit.utils.TimeStampedPVCoordinatesHermiteInterpolator;
45
46
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 public class Transform implements TimeShiftable<Transform>, KinematicTransform {
103
104
105 public static final Transform IDENTITY = new IdentityTransform();
106
107
108 private final AbsoluteDate date;
109
110
111 private final PVCoordinates cartesian;
112
113
114 private final AngularCoordinates angular;
115
116
117
118
119
120
121 public Transform(final AbsoluteDate date, final PVCoordinates cartesian, final AngularCoordinates angular) {
122 this.date = date;
123 this.cartesian = cartesian;
124 this.angular = angular;
125 }
126
127
128
129
130
131
132
133 public Transform(final AbsoluteDate date, final Vector3D translation) {
134 this(date,
135 new PVCoordinates(translation),
136 AngularCoordinates.IDENTITY);
137 }
138
139
140
141
142
143
144
145 public Transform(final AbsoluteDate date, final Rotation rotation) {
146 this(date,
147 PVCoordinates.ZERO,
148 new AngularCoordinates(rotation));
149 }
150
151
152
153
154
155
156
157
158
159
160
161 public Transform(final AbsoluteDate date, final Vector3D translation, final Rotation rotation) {
162 this(date, new PVCoordinates(translation), new AngularCoordinates(rotation));
163 }
164
165
166
167
168
169
170
171
172
173 public Transform(final AbsoluteDate date, final Vector3D translation,
174 final Vector3D velocity) {
175 this(date,
176 new PVCoordinates(translation, velocity, Vector3D.ZERO),
177 AngularCoordinates.IDENTITY);
178 }
179
180
181
182
183
184
185
186
187
188
189
190 public Transform(final AbsoluteDate date, final Vector3D translation,
191 final Vector3D velocity, final Vector3D acceleration) {
192 this(date,
193 new PVCoordinates(translation, velocity, acceleration),
194 AngularCoordinates.IDENTITY);
195 }
196
197
198
199
200
201
202
203 public Transform(final AbsoluteDate date, final PVCoordinates cartesian) {
204 this(date,
205 cartesian,
206 AngularCoordinates.IDENTITY);
207 }
208
209
210
211
212
213
214
215
216
217 public Transform(final AbsoluteDate date, final Rotation rotation, final Vector3D rotationRate) {
218 this(date,
219 PVCoordinates.ZERO,
220 new AngularCoordinates(rotation, rotationRate, Vector3D.ZERO));
221 }
222
223
224
225
226
227
228
229
230
231
232 public Transform(final AbsoluteDate date, final Rotation rotation, final Vector3D rotationRate,
233 final Vector3D rotationAcceleration) {
234 this(date,
235 PVCoordinates.ZERO,
236 new AngularCoordinates(rotation, rotationRate, rotationAcceleration));
237 }
238
239
240
241
242
243
244
245 public Transform(final AbsoluteDate date, final AngularCoordinates angular) {
246 this(date, PVCoordinates.ZERO, angular);
247 }
248
249
250
251
252
253
254
255
256
257
258
259
260 public Transform(final AbsoluteDate date, final Transform first, final Transform second) {
261 this(date,
262 new PVCoordinates(StaticTransform.compositeTranslation(first, second),
263 KinematicTransform.compositeVelocity(first, second),
264 compositeAcceleration(first, second)),
265 new AngularCoordinates(StaticTransform.compositeRotation(first, second),
266 KinematicTransform.compositeRotationRate(first, second),
267 compositeRotationAcceleration(first, second)));
268 }
269
270
271
272
273
274
275 private static Vector3D compositeAcceleration(final Transform first, final Transform second) {
276
277 final Vector3D a1 = first.cartesian.getAcceleration();
278 final Rotation r1 = first.angular.getRotation();
279 final Vector3D o1 = first.angular.getRotationRate();
280 final Vector3D oDot1 = first.angular.getRotationAcceleration();
281 final Vector3D p2 = second.cartesian.getPosition();
282 final Vector3D v2 = second.cartesian.getVelocity();
283 final Vector3D a2 = second.cartesian.getAcceleration();
284
285 final Vector3D crossCrossP = Vector3D.crossProduct(o1, Vector3D.crossProduct(o1, p2));
286 final Vector3D crossV = Vector3D.crossProduct(o1, v2);
287 final Vector3D crossDotP = Vector3D.crossProduct(oDot1, p2);
288
289 return a1.add(r1.applyInverseTo(new Vector3D(1, a2, 2, crossV, 1, crossCrossP, 1, crossDotP)));
290
291 }
292
293
294
295
296
297
298 private static Vector3D compositeRotationAcceleration(final Transform first, final Transform second) {
299
300 final Vector3D o1 = first.angular.getRotationRate();
301 final Vector3D oDot1 = first.angular.getRotationAcceleration();
302 final Rotation r2 = second.angular.getRotation();
303 final Vector3D o2 = second.angular.getRotationRate();
304 final Vector3D oDot2 = second.angular.getRotationAcceleration();
305
306 return new Vector3D( 1, oDot2,
307 1, r2.applyTo(oDot1),
308 -1, Vector3D.crossProduct(o2, r2.applyTo(o1)));
309
310 }
311
312
313 public AbsoluteDate getDate() {
314 return date;
315 }
316
317
318 public Transform shiftedBy(final double dt) {
319 return shiftedBy(new TimeOffset(dt));
320 }
321
322
323 @Override
324 public Transform shiftedBy(final TimeOffset dt) {
325 return new Transform(date.shiftedBy(dt), cartesian.shiftedBy(dt), angular.shiftedBy(dt));
326 }
327
328
329
330
331
332
333
334
335
336
337
338 public StaticTransform staticShiftedBy(final double dt) {
339 return StaticTransform.of(
340 date.shiftedBy(dt),
341 cartesian.positionShiftedBy(dt),
342 angular.rotationShiftedBy(dt));
343 }
344
345
346
347
348
349
350
351
352
353 public StaticTransform toStaticTransform() {
354 return StaticTransform.of(date, cartesian.getPosition(), angular.getRotation());
355 }
356
357
358
359
360
361
362
363
364
365
366
367
368
369 public Transform interpolate(final AbsoluteDate interpolationDate, final Stream<Transform> sample) {
370 return interpolate(interpolationDate,
371 CartesianDerivativesFilter.USE_PVA, AngularDerivativesFilter.USE_RRA,
372 sample.collect(Collectors.toList()));
373 }
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399 public static Transform interpolate(final AbsoluteDate date,
400 final CartesianDerivativesFilter cFilter,
401 final AngularDerivativesFilter aFilter,
402 final Collection<Transform> sample) {
403
404
405 final List<TimeStampedPVCoordinates> datedPV = new ArrayList<>(sample.size());
406 final List<TimeStampedAngularCoordinates> datedAC = new ArrayList<>(sample.size());
407 for (final Transform t : sample) {
408 datedPV.add(new TimeStampedPVCoordinates(t.getDate(), t.getTranslation(), t.getVelocity(), t.getAcceleration()));
409 datedAC.add(new TimeStampedAngularCoordinates(t.getDate(), t.getRotation(), t.getRotationRate(), t.getRotationAcceleration()));
410 }
411
412
413 final TimeInterpolator<TimeStampedPVCoordinates> pvInterpolator =
414 new TimeStampedPVCoordinatesHermiteInterpolator(datedPV.size(), cFilter);
415
416 final TimeInterpolator<TimeStampedAngularCoordinates> angularInterpolator =
417 new TimeStampedAngularCoordinatesHermiteInterpolator(datedPV.size(), aFilter);
418
419
420 final TimeStampedPVCoordinates interpolatedPV = pvInterpolator.interpolate(date, datedPV);
421 final TimeStampedAngularCoordinates interpolatedAC = angularInterpolator.interpolate(date, datedAC);
422 return new Transform(date, interpolatedPV, interpolatedAC);
423 }
424
425
426
427
428 @Override
429 public Transform getInverse() {
430
431 final Rotation r = angular.getRotation();
432 final Vector3D o = angular.getRotationRate();
433 final Vector3D oDot = angular.getRotationAcceleration();
434 final Vector3D rp = r.applyTo(cartesian.getPosition());
435 final Vector3D rv = r.applyTo(cartesian.getVelocity());
436 final Vector3D ra = r.applyTo(cartesian.getAcceleration());
437
438 final Vector3D pInv = rp.negate();
439 final Vector3D crossP = Vector3D.crossProduct(o, rp);
440 final Vector3D vInv = crossP.subtract(rv);
441 final Vector3D crossV = Vector3D.crossProduct(o, rv);
442 final Vector3D crossDotP = Vector3D.crossProduct(oDot, rp);
443 final Vector3D crossCrossP = Vector3D.crossProduct(o, crossP);
444 final Vector3D aInv = new Vector3D(-1, ra,
445 2, crossV,
446 1, crossDotP,
447 -1, crossCrossP);
448
449 return new Transform(getDate(), new PVCoordinates(pInv, vInv, aInv), angular.revert());
450
451 }
452
453
454
455
456
457
458
459
460 public Transform freeze() {
461 return new Transform(date,
462 new PVCoordinates(cartesian.getPosition(), Vector3D.ZERO, Vector3D.ZERO),
463 new AngularCoordinates(angular.getRotation(), Vector3D.ZERO, Vector3D.ZERO));
464 }
465
466
467
468
469
470 public PVCoordinates transformPVCoordinates(final PVCoordinates pva) {
471 return angular.applyTo(new PVCoordinates(1, pva, 1, cartesian));
472 }
473
474
475
476
477
478
479
480
481
482
483
484
485
486 public TimeStampedPVCoordinates transformPVCoordinates(final TimeStampedPVCoordinates pv) {
487 return angular.applyTo(new TimeStampedPVCoordinates(pv.getDate(), 1, pv, 1, cartesian));
488 }
489
490
491
492
493
494
495 public <T extends CalculusFieldElement<T>> FieldPVCoordinates<T> transformPVCoordinates(final FieldPVCoordinates<T> pv) {
496 return angular.applyTo(new FieldPVCoordinates<>(pv.getPosition().add(cartesian.getPosition()),
497 pv.getVelocity().add(cartesian.getVelocity()),
498 pv.getAcceleration().add(cartesian.getAcceleration())));
499 }
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514 public <T extends CalculusFieldElement<T>> TimeStampedFieldPVCoordinates<T> transformPVCoordinates(final TimeStampedFieldPVCoordinates<T> pv) {
515 return angular.applyTo(new TimeStampedFieldPVCoordinates<>(pv.getDate(),
516 pv.getPosition().add(cartesian.getPosition()),
517 pv.getVelocity().add(cartesian.getVelocity()),
518 pv.getAcceleration().add(cartesian.getAcceleration())));
519 }
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545 public void getJacobian(final CartesianDerivativesFilter selector, final double[][] jacobian) {
546
547 if (selector.getMaxOrder() == 0) {
548
549 final double[][] mData = angular.getRotation().getMatrix();
550
551
552 System.arraycopy(mData[0], 0, jacobian[0], 0, 3);
553 System.arraycopy(mData[1], 0, jacobian[1], 0, 3);
554 System.arraycopy(mData[2], 0, jacobian[2], 0, 3);
555 }
556
557 else if (selector.getMaxOrder() == 1) {
558
559 final double[][] mData = getPVJacobian();
560 for (int i = 0; i < mData.length; i++) {
561 System.arraycopy(mData[i], 0, jacobian[i], 0, mData[i].length);
562 }
563 }
564
565 else if (selector.getMaxOrder() >= 2) {
566 getJacobian(CartesianDerivativesFilter.USE_PV, jacobian);
567
568
569 Arrays.fill(jacobian[0], 6, 9, 0.0);
570 Arrays.fill(jacobian[1], 6, 9, 0.0);
571 Arrays.fill(jacobian[2], 6, 9, 0.0);
572
573
574 Arrays.fill(jacobian[3], 6, 9, 0.0);
575 Arrays.fill(jacobian[4], 6, 9, 0.0);
576 Arrays.fill(jacobian[5], 6, 9, 0.0);
577
578
579 final Vector3D o = angular.getRotationRate();
580 final double ox = o.getX();
581 final double oy = o.getY();
582 final double oz = o.getZ();
583 final Vector3D oDot = angular.getRotationAcceleration();
584 final double oDotx = oDot.getX();
585 final double oDoty = oDot.getY();
586 final double oDotz = oDot.getZ();
587 for (int i = 0; i < 3; ++i) {
588 jacobian[6][i] = -(oDoty * jacobian[2][i] - oDotz * jacobian[1][i]) - (oy * jacobian[5][i] - oz * jacobian[4][i]);
589 jacobian[7][i] = -(oDotz * jacobian[0][i] - oDotx * jacobian[2][i]) - (oz * jacobian[3][i] - ox * jacobian[5][i]);
590 jacobian[8][i] = -(oDotx * jacobian[1][i] - oDoty * jacobian[0][i]) - (ox * jacobian[4][i] - oy * jacobian[3][i]);
591 }
592
593
594 for (int i = 0; i < 3; ++i) {
595 jacobian[6][i + 3] = -2 * (oy * jacobian[2][i] - oz * jacobian[1][i]);
596 jacobian[7][i + 3] = -2 * (oz * jacobian[0][i] - ox * jacobian[2][i]);
597 jacobian[8][i + 3] = -2 * (ox * jacobian[1][i] - oy * jacobian[0][i]);
598 }
599
600
601 System.arraycopy(jacobian[0], 0, jacobian[6], 6, 3);
602 System.arraycopy(jacobian[1], 0, jacobian[7], 6, 3);
603 System.arraycopy(jacobian[2], 0, jacobian[8], 6, 3);
604
605 }
606 }
607
608
609
610
611
612
613
614
615
616 public PVCoordinates getCartesian() {
617 return cartesian;
618 }
619
620
621
622
623
624
625
626
627
628
629 public Vector3D getTranslation() {
630 return cartesian.getPosition();
631 }
632
633
634
635
636
637
638
639 public Vector3D getVelocity() {
640 return cartesian.getVelocity();
641 }
642
643
644
645
646
647
648
649 public Vector3D getAcceleration() {
650 return cartesian.getAcceleration();
651 }
652
653
654
655
656
657
658
659
660
661
662 public AngularCoordinates getAngular() {
663 return angular;
664 }
665
666
667
668
669
670
671
672
673
674
675 public Rotation getRotation() {
676 return angular.getRotation();
677 }
678
679
680
681
682
683
684
685
686 public Vector3D getRotationRate() {
687 return angular.getRotationRate();
688 }
689
690
691
692
693
694
695
696 public Vector3D getRotationAcceleration() {
697 return angular.getRotationAcceleration();
698 }
699
700
701 private static class IdentityTransform extends Transform {
702
703
704 IdentityTransform() {
705 super(AbsoluteDate.ARBITRARY_EPOCH, PVCoordinates.ZERO, AngularCoordinates.IDENTITY);
706 }
707
708 @Override
709 public StaticTransform staticShiftedBy(final double dt) {
710 return toStaticTransform();
711 }
712
713
714 @Override
715 public Transform shiftedBy(final double dt) {
716 return this;
717 }
718
719 @Override
720 public StaticTransform getStaticInverse() {
721 return toStaticTransform();
722 }
723
724
725 @Override
726 public Transform shiftedBy(final TimeOffset dt) {
727 return this;
728 }
729
730
731 @Override
732 public Transform getInverse() {
733 return this;
734 }
735
736 @Override
737 public StaticTransform toStaticTransform() {
738 return StaticTransform.getIdentity();
739 }
740
741
742 @Override
743 public Vector3D transformPosition(final Vector3D position) {
744 return position;
745 }
746
747
748 @Override
749 public Vector3D transformVector(final Vector3D vector) {
750 return vector;
751 }
752
753 @Override
754 public <T extends CalculusFieldElement<T>> FieldVector3D<T> transformPosition(final FieldVector3D<T> position) {
755 return transformVector(position);
756 }
757
758 @Override
759 public <T extends CalculusFieldElement<T>> FieldVector3D<T> transformVector(final FieldVector3D<T> vector) {
760 return new FieldVector3D<>(vector.getX(), vector.getY(), vector.getZ());
761 }
762
763
764 @Override
765 public Line transformLine(final Line line) {
766 return line;
767 }
768
769
770 @Override
771 public PVCoordinates transformPVCoordinates(final PVCoordinates pv) {
772 return pv;
773 }
774
775 @Override
776 public PVCoordinates transformOnlyPV(final PVCoordinates pv) {
777 return new PVCoordinates(pv.getPosition(), pv.getVelocity());
778 }
779
780 @Override
781 public TimeStampedPVCoordinates transformOnlyPV(final TimeStampedPVCoordinates pv) {
782 return new TimeStampedPVCoordinates(pv.getDate(), pv.getPosition(), pv.getVelocity());
783 }
784
785 @Override
786 public Transform freeze() {
787 return this;
788 }
789
790 @Override
791 public TimeStampedPVCoordinates transformPVCoordinates(
792 final TimeStampedPVCoordinates pv) {
793 return pv;
794 }
795
796 @Override
797 public <T extends CalculusFieldElement<T>> FieldPVCoordinates<T>
798 transformPVCoordinates(final FieldPVCoordinates<T> pv) {
799 return pv;
800 }
801
802 @Override
803 public <T extends CalculusFieldElement<T>>
804 TimeStampedFieldPVCoordinates<T> transformPVCoordinates(
805 final TimeStampedFieldPVCoordinates<T> pv) {
806 return pv;
807 }
808
809
810 @Override
811 public void getJacobian(final CartesianDerivativesFilter selector, final double[][] jacobian) {
812 final int n = 3 * (selector.getMaxOrder() + 1);
813 for (int i = 0; i < n; ++i) {
814 Arrays.fill(jacobian[i], 0, n, 0.0);
815 jacobian[i][i] = 1.0;
816 }
817 }
818
819 }
820
821 }