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