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