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