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.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
103 TimeShiftable<Transform>,
104 Serializable,
105 KinematicTransform {
106
107
108 public static final Transform IDENTITY = new IdentityTransform();
109
110
111 private static final long serialVersionUID = 210140410L;
112
113
114 private final AbsoluteDate date;
115
116
117 private final PVCoordinates cartesian;
118
119
120 private final AngularCoordinates angular;
121
122
123
124
125
126
127 public Transform(final AbsoluteDate date, final PVCoordinates cartesian, final AngularCoordinates angular) {
128 this.date = date;
129 this.cartesian = cartesian;
130 this.angular = angular;
131 }
132
133
134
135
136
137
138
139 public Transform(final AbsoluteDate date, final Vector3D translation) {
140 this(date,
141 new PVCoordinates(translation),
142 AngularCoordinates.IDENTITY);
143 }
144
145
146
147
148
149
150
151 public Transform(final AbsoluteDate date, final Rotation rotation) {
152 this(date,
153 PVCoordinates.ZERO,
154 new AngularCoordinates(rotation));
155 }
156
157
158
159
160
161
162
163
164
165
166
167 public Transform(final AbsoluteDate date, final Vector3D translation, final Rotation rotation) {
168 this(date, new PVCoordinates(translation), new AngularCoordinates(rotation));
169 }
170
171
172
173
174
175
176
177
178
179 public Transform(final AbsoluteDate date, final Vector3D translation,
180 final Vector3D velocity) {
181 this(date,
182 new PVCoordinates(translation, velocity, Vector3D.ZERO),
183 AngularCoordinates.IDENTITY);
184 }
185
186
187
188
189
190
191
192
193
194
195
196 public Transform(final AbsoluteDate date, final Vector3D translation,
197 final Vector3D velocity, final Vector3D acceleration) {
198 this(date,
199 new PVCoordinates(translation, velocity, acceleration),
200 AngularCoordinates.IDENTITY);
201 }
202
203
204
205
206
207
208
209 public Transform(final AbsoluteDate date, final PVCoordinates cartesian) {
210 this(date,
211 cartesian,
212 AngularCoordinates.IDENTITY);
213 }
214
215
216
217
218
219
220
221
222
223 public Transform(final AbsoluteDate date, final Rotation rotation, final Vector3D rotationRate) {
224 this(date,
225 PVCoordinates.ZERO,
226 new AngularCoordinates(rotation, rotationRate, Vector3D.ZERO));
227 }
228
229
230
231
232
233
234
235
236
237
238 public Transform(final AbsoluteDate date, final Rotation rotation, final Vector3D rotationRate,
239 final Vector3D rotationAcceleration) {
240 this(date,
241 PVCoordinates.ZERO,
242 new AngularCoordinates(rotation, rotationRate, rotationAcceleration));
243 }
244
245
246
247
248
249
250
251 public Transform(final AbsoluteDate date, final AngularCoordinates angular) {
252 this(date, PVCoordinates.ZERO, angular);
253 }
254
255
256
257
258
259
260
261
262
263
264
265
266 public Transform(final AbsoluteDate date, final Transform first, final Transform second) {
267 this(date,
268 new PVCoordinates(StaticTransform.compositeTranslation(first, second),
269 KinematicTransform.compositeVelocity(first, second),
270 compositeAcceleration(first, second)),
271 new AngularCoordinates(StaticTransform.compositeRotation(first, second),
272 KinematicTransform.compositeRotationRate(first, second),
273 compositeRotationAcceleration(first, second)));
274 }
275
276
277
278
279
280
281 private static Vector3D compositeAcceleration(final Transform first, final Transform second) {
282
283 final Vector3D a1 = first.cartesian.getAcceleration();
284 final Rotation r1 = first.angular.getRotation();
285 final Vector3D o1 = first.angular.getRotationRate();
286 final Vector3D oDot1 = first.angular.getRotationAcceleration();
287 final Vector3D p2 = second.cartesian.getPosition();
288 final Vector3D v2 = second.cartesian.getVelocity();
289 final Vector3D a2 = second.cartesian.getAcceleration();
290
291 final Vector3D crossCrossP = Vector3D.crossProduct(o1, Vector3D.crossProduct(o1, p2));
292 final Vector3D crossV = Vector3D.crossProduct(o1, v2);
293 final Vector3D crossDotP = Vector3D.crossProduct(oDot1, p2);
294
295 return a1.add(r1.applyInverseTo(new Vector3D(1, a2, 2, crossV, 1, crossCrossP, 1, crossDotP)));
296
297 }
298
299
300
301
302
303
304 private static Vector3D compositeRotationAcceleration(final Transform first, final Transform second) {
305
306 final Vector3D o1 = first.angular.getRotationRate();
307 final Vector3D oDot1 = first.angular.getRotationAcceleration();
308 final Rotation r2 = second.angular.getRotation();
309 final Vector3D o2 = second.angular.getRotationRate();
310 final Vector3D oDot2 = second.angular.getRotationAcceleration();
311
312 return new Vector3D( 1, oDot2,
313 1, r2.applyTo(oDot1),
314 -1, Vector3D.crossProduct(o2, r2.applyTo(o1)));
315
316 }
317
318
319 public AbsoluteDate getDate() {
320 return date;
321 }
322
323
324 public Transform shiftedBy(final double 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 private static final long serialVersionUID = -9042082036141830517L;
705
706
707 IdentityTransform() {
708 super(AbsoluteDate.ARBITRARY_EPOCH, PVCoordinates.ZERO, AngularCoordinates.IDENTITY);
709 }
710
711 @Override
712 public StaticTransform staticShiftedBy(final double dt) {
713 return toStaticTransform();
714 }
715
716
717 @Override
718 public Transform shiftedBy(final double dt) {
719 return this;
720 }
721
722 @Override
723 public StaticTransform getStaticInverse() {
724 return toStaticTransform();
725 }
726
727
728 @Override
729 public Transform getInverse() {
730 return this;
731 }
732
733 @Override
734 public StaticTransform toStaticTransform() {
735 return StaticTransform.getIdentity();
736 }
737
738
739 @Override
740 public Vector3D transformPosition(final Vector3D position) {
741 return position;
742 }
743
744
745 @Override
746 public Vector3D transformVector(final Vector3D vector) {
747 return vector;
748 }
749
750 @Override
751 public <T extends CalculusFieldElement<T>> FieldVector3D<T> transformPosition(final FieldVector3D<T> position) {
752 return transformVector(position);
753 }
754
755 @Override
756 public <T extends CalculusFieldElement<T>> FieldVector3D<T> transformVector(final FieldVector3D<T> vector) {
757 return new FieldVector3D<>(vector.getX(), vector.getY(), vector.getZ());
758 }
759
760
761 @Override
762 public Line transformLine(final Line line) {
763 return line;
764 }
765
766
767 @Override
768 public PVCoordinates transformPVCoordinates(final PVCoordinates pv) {
769 return pv;
770 }
771
772 @Override
773 public PVCoordinates transformOnlyPV(final PVCoordinates pv) {
774 return new PVCoordinates(pv.getPosition(), pv.getVelocity());
775 }
776
777 @Override
778 public TimeStampedPVCoordinates transformOnlyPV(final TimeStampedPVCoordinates pv) {
779 return new TimeStampedPVCoordinates(pv.getDate(), pv.getPosition(), pv.getVelocity());
780 }
781
782 @Override
783 public Transform freeze() {
784 return this;
785 }
786
787 @Override
788 public TimeStampedPVCoordinates transformPVCoordinates(
789 final TimeStampedPVCoordinates pv) {
790 return pv;
791 }
792
793 @Override
794 public <T extends CalculusFieldElement<T>> FieldPVCoordinates<T>
795 transformPVCoordinates(final FieldPVCoordinates<T> pv) {
796 return pv;
797 }
798
799 @Override
800 public <T extends CalculusFieldElement<T>>
801 TimeStampedFieldPVCoordinates<T> transformPVCoordinates(
802 final TimeStampedFieldPVCoordinates<T> pv) {
803 return pv;
804 }
805
806
807 @Override
808 public void getJacobian(final CartesianDerivativesFilter selector, final double[][] jacobian) {
809 final int n = 3 * (selector.getMaxOrder() + 1);
810 for (int i = 0; i < n; ++i) {
811 Arrays.fill(jacobian[i], 0, n, 0.0);
812 jacobian[i][i] = 1.0;
813 }
814 }
815
816 }
817
818 }