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