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