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.TimeInterpolable;
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.TimeStampedFieldPVCoordinates;
41 import org.orekit.utils.TimeStampedPVCoordinates;
42
43
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 public class Transform implements
100 TimeInterpolable<Transform>,
101 TimeShiftable<Transform>,
102 Serializable,
103 StaticTransform {
104
105
106 public static final Transform IDENTITY = new IdentityTransform();
107
108
109 private static final long serialVersionUID = 210140410L;
110
111
112 private final AbsoluteDate date;
113
114
115 private final PVCoordinates cartesian;
116
117
118 private final AngularCoordinates angular;
119
120
121
122
123
124
125 private Transform(final AbsoluteDate date,
126 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
373 public Transform interpolate(final AbsoluteDate interpolationDate, final Stream<Transform> sample) {
374 return interpolate(interpolationDate,
375 CartesianDerivativesFilter.USE_PVA, AngularDerivativesFilter.USE_RRA,
376 sample.collect(Collectors.toList()));
377 }
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403 public static Transform interpolate(final AbsoluteDate date,
404 final CartesianDerivativesFilter cFilter,
405 final AngularDerivativesFilter aFilter,
406 final Collection<Transform> sample) {
407 final List<TimeStampedPVCoordinates> datedPV = new ArrayList<>(sample.size());
408 final List<TimeStampedAngularCoordinates> datedAC = new ArrayList<>(sample.size());
409 for (final Transform t : sample) {
410 datedPV.add(new TimeStampedPVCoordinates(t.getDate(), t.getTranslation(), t.getVelocity(), t.getAcceleration()));
411 datedAC.add(new TimeStampedAngularCoordinates(t.getDate(), t.getRotation(), t.getRotationRate(), t.getRotationAcceleration()));
412 }
413 final TimeStampedPVCoordinates interpolatedPV = TimeStampedPVCoordinates.interpolate(date, cFilter, datedPV);
414 final TimeStampedAngularCoordinates interpolatedAC = TimeStampedAngularCoordinates.interpolate(date, aFilter, datedAC);
415 return new Transform(date, interpolatedPV, interpolatedAC);
416 }
417
418
419
420
421 @Override
422 public Transform getInverse() {
423
424 final Rotation r = angular.getRotation();
425 final Vector3D o = angular.getRotationRate();
426 final Vector3D oDot = angular.getRotationAcceleration();
427 final Vector3D rp = r.applyTo(cartesian.getPosition());
428 final Vector3D rv = r.applyTo(cartesian.getVelocity());
429 final Vector3D ra = r.applyTo(cartesian.getAcceleration());
430
431 final Vector3D pInv = rp.negate();
432 final Vector3D crossP = Vector3D.crossProduct(o, rp);
433 final Vector3D vInv = crossP.subtract(rv);
434 final Vector3D crossV = Vector3D.crossProduct(o, rv);
435 final Vector3D crossDotP = Vector3D.crossProduct(oDot, rp);
436 final Vector3D crossCrossP = Vector3D.crossProduct(o, crossP);
437 final Vector3D aInv = new Vector3D(-1, ra,
438 2, crossV,
439 1, crossDotP,
440 -1, crossCrossP);
441
442 return new Transform(getDate(), new PVCoordinates(pInv, vInv, aInv), angular.revert());
443
444 }
445
446
447
448
449
450
451
452
453 public Transform freeze() {
454 return new Transform(date,
455 new PVCoordinates(cartesian.getPosition(), Vector3D.ZERO, Vector3D.ZERO),
456 new AngularCoordinates(angular.getRotation(), Vector3D.ZERO, Vector3D.ZERO));
457 }
458
459
460
461
462
463 public PVCoordinates transformPVCoordinates(final PVCoordinates pva) {
464 return angular.applyTo(new PVCoordinates(1, pva, 1, cartesian));
465 }
466
467
468
469
470
471
472
473
474
475
476
477
478
479 public TimeStampedPVCoordinates transformPVCoordinates(final TimeStampedPVCoordinates pv) {
480 return angular.applyTo(new TimeStampedPVCoordinates(pv.getDate(), 1, pv, 1, cartesian));
481 }
482
483
484
485
486
487
488 public <T extends CalculusFieldElement<T>> FieldPVCoordinates<T> transformPVCoordinates(final FieldPVCoordinates<T> pv) {
489 return angular.applyTo(new FieldPVCoordinates<>(pv.getPosition().add(cartesian.getPosition()),
490 pv.getVelocity().add(cartesian.getVelocity()),
491 pv.getAcceleration().add(cartesian.getAcceleration())));
492 }
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507 public <T extends CalculusFieldElement<T>> TimeStampedFieldPVCoordinates<T> transformPVCoordinates(final TimeStampedFieldPVCoordinates<T> pv) {
508 return angular.applyTo(new TimeStampedFieldPVCoordinates<>(pv.getDate(),
509 pv.getPosition().add(cartesian.getPosition()),
510 pv.getVelocity().add(cartesian.getVelocity()),
511 pv.getAcceleration().add(cartesian.getAcceleration())));
512 }
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538 public void getJacobian(final CartesianDerivativesFilter selector, final double[][] jacobian) {
539
540
541 final double[][] mData = angular.getRotation().getMatrix();
542
543
544 System.arraycopy(mData[0], 0, jacobian[0], 0, 3);
545 System.arraycopy(mData[1], 0, jacobian[1], 0, 3);
546 System.arraycopy(mData[2], 0, jacobian[2], 0, 3);
547
548 if (selector.getMaxOrder() >= 1) {
549
550
551 Arrays.fill(jacobian[0], 3, 6, 0.0);
552 Arrays.fill(jacobian[1], 3, 6, 0.0);
553 Arrays.fill(jacobian[2], 3, 6, 0.0);
554
555
556 final Vector3D o = angular.getRotationRate();
557 final double ox = o.getX();
558 final double oy = o.getY();
559 final double oz = o.getZ();
560 for (int i = 0; i < 3; ++i) {
561 jacobian[3][i] = -(oy * mData[2][i] - oz * mData[1][i]);
562 jacobian[4][i] = -(oz * mData[0][i] - ox * mData[2][i]);
563 jacobian[5][i] = -(ox * mData[1][i] - oy * mData[0][i]);
564 }
565
566
567 System.arraycopy(mData[0], 0, jacobian[3], 3, 3);
568 System.arraycopy(mData[1], 0, jacobian[4], 3, 3);
569 System.arraycopy(mData[2], 0, jacobian[5], 3, 3);
570
571 if (selector.getMaxOrder() >= 2) {
572
573
574 Arrays.fill(jacobian[0], 6, 9, 0.0);
575 Arrays.fill(jacobian[1], 6, 9, 0.0);
576 Arrays.fill(jacobian[2], 6, 9, 0.0);
577
578
579 Arrays.fill(jacobian[3], 6, 9, 0.0);
580 Arrays.fill(jacobian[4], 6, 9, 0.0);
581 Arrays.fill(jacobian[5], 6, 9, 0.0);
582
583
584 final Vector3D oDot = angular.getRotationAcceleration();
585 final double oDotx = oDot.getX();
586 final double oDoty = oDot.getY();
587 final double oDotz = oDot.getZ();
588 for (int i = 0; i < 3; ++i) {
589 jacobian[6][i] = -(oDoty * mData[2][i] - oDotz * mData[1][i]) - (oy * jacobian[5][i] - oz * jacobian[4][i]);
590 jacobian[7][i] = -(oDotz * mData[0][i] - oDotx * mData[2][i]) - (oz * jacobian[3][i] - ox * jacobian[5][i]);
591 jacobian[8][i] = -(oDotx * mData[1][i] - oDoty * mData[0][i]) - (ox * jacobian[4][i] - oy * jacobian[3][i]);
592 }
593
594
595 for (int i = 0; i < 3; ++i) {
596 jacobian[6][i + 3] = -2 * (oy * mData[2][i] - oz * mData[1][i]);
597 jacobian[7][i + 3] = -2 * (oz * mData[0][i] - ox * mData[2][i]);
598 jacobian[8][i + 3] = -2 * (ox * mData[1][i] - oy * mData[0][i]);
599 }
600
601
602 System.arraycopy(mData[0], 0, jacobian[6], 6, 3);
603 System.arraycopy(mData[1], 0, jacobian[7], 6, 3);
604 System.arraycopy(mData[2], 0, jacobian[8], 6, 3);
605
606 }
607
608 }
609
610 }
611
612
613
614
615
616
617
618
619
620 public PVCoordinates getCartesian() {
621 return cartesian;
622 }
623
624
625
626
627
628
629
630
631
632
633 public Vector3D getTranslation() {
634 return cartesian.getPosition();
635 }
636
637
638
639
640
641
642
643 public Vector3D getVelocity() {
644 return cartesian.getVelocity();
645 }
646
647
648
649
650
651
652
653 public Vector3D getAcceleration() {
654 return cartesian.getAcceleration();
655 }
656
657
658
659
660
661
662
663
664
665
666 public AngularCoordinates getAngular() {
667 return angular;
668 }
669
670
671
672
673
674
675
676
677
678
679 public Rotation getRotation() {
680 return angular.getRotation();
681 }
682
683
684
685
686
687
688
689
690 public Vector3D getRotationRate() {
691 return angular.getRotationRate();
692 }
693
694
695
696
697
698
699
700 public Vector3D getRotationAcceleration() {
701 return angular.getRotationAcceleration();
702 }
703
704
705 private static class IdentityTransform extends Transform {
706
707
708 private static final long serialVersionUID = -9042082036141830517L;
709
710
711 IdentityTransform() {
712 super(AbsoluteDate.ARBITRARY_EPOCH, PVCoordinates.ZERO, AngularCoordinates.IDENTITY);
713 }
714
715
716 @Override
717 public Transform shiftedBy(final double dt) {
718 return this;
719 }
720
721
722 @Override
723 public Transform getInverse() {
724 return this;
725 }
726
727
728 @Override
729 public Vector3D transformPosition(final Vector3D position) {
730 return position;
731 }
732
733
734 @Override
735 public Vector3D transformVector(final Vector3D vector) {
736 return vector;
737 }
738
739
740 @Override
741 public Line transformLine(final Line line) {
742 return line;
743 }
744
745
746 @Override
747 public PVCoordinates transformPVCoordinates(final PVCoordinates pv) {
748 return pv;
749 }
750
751 @Override
752 public Transform freeze() {
753 return this;
754 }
755
756 @Override
757 public TimeStampedPVCoordinates transformPVCoordinates(
758 final TimeStampedPVCoordinates pv) {
759 return pv;
760 }
761
762 @Override
763 public <T extends CalculusFieldElement<T>> FieldPVCoordinates<T>
764 transformPVCoordinates(final FieldPVCoordinates<T> pv) {
765 return pv;
766 }
767
768 @Override
769 public <T extends CalculusFieldElement<T>>
770 TimeStampedFieldPVCoordinates<T> transformPVCoordinates(
771 final TimeStampedFieldPVCoordinates<T> pv) {
772 return pv;
773 }
774
775
776 @Override
777 public void getJacobian(final CartesianDerivativesFilter selector, final double[][] jacobian) {
778 final int n = 3 * (selector.getMaxOrder() + 1);
779 for (int i = 0; i < n; ++i) {
780 Arrays.fill(jacobian[i], 0, n, 0.0);
781 jacobian[i][i] = 1.0;
782 }
783 }
784
785 }
786
787 }