1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.utils;
18
19 import org.hipparchus.Field;
20 import org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.analysis.differentiation.FDSFactory;
22 import org.hipparchus.analysis.differentiation.FieldDerivative;
23 import org.hipparchus.analysis.differentiation.FieldDerivativeStructure;
24 import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative1;
25 import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative2;
26 import org.hipparchus.analysis.differentiation.UnivariateDerivative1;
27 import org.hipparchus.analysis.differentiation.UnivariateDerivative2;
28 import org.hipparchus.exception.LocalizedCoreFormats;
29 import org.hipparchus.exception.MathIllegalArgumentException;
30 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
31 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
32 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
33 import org.hipparchus.linear.FieldDecompositionSolver;
34 import org.hipparchus.linear.FieldMatrix;
35 import org.hipparchus.linear.FieldQRDecomposition;
36 import org.hipparchus.linear.FieldVector;
37 import org.hipparchus.linear.MatrixUtils;
38 import org.hipparchus.util.MathArrays;
39 import org.orekit.errors.OrekitException;
40 import org.orekit.errors.OrekitMessages;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class FieldAngularCoordinates<T extends CalculusFieldElement<T>> {
60
61
62
63 private final FieldRotation<T> rotation;
64
65
66 private final FieldVector3D<T> rotationRate;
67
68
69 private final FieldVector3D<T> rotationAcceleration;
70
71
72
73
74
75 public FieldAngularCoordinates(final FieldRotation<T> rotation,
76 final FieldVector3D<T> rotationRate) {
77 this(rotation, rotationRate,
78 new FieldVector3D<>(rotation.getQ0().getField().getZero(),
79 rotation.getQ0().getField().getZero(),
80 rotation.getQ0().getField().getZero()));
81 }
82
83
84
85
86
87
88 public FieldAngularCoordinates(final FieldRotation<T> rotation,
89 final FieldVector3D<T> rotationRate,
90 final FieldVector3D<T> rotationAcceleration) {
91 this.rotation = rotation;
92 this.rotationRate = rotationRate;
93 this.rotationAcceleration = rotationAcceleration;
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 public FieldAngularCoordinates(final FieldPVCoordinates<T> u1, final FieldPVCoordinates<T> u2,
117 final FieldPVCoordinates<T> v1, final FieldPVCoordinates<T> v2,
118 final double tolerance) {
119
120 try {
121
122 rotation = new FieldRotation<>(u1.getPosition(), u2.getPosition(),
123 v1.getPosition(), v2.getPosition());
124
125
126
127
128 final FieldVector3D<T> ru1Dot = rotation.applyTo(u1.getVelocity());
129 final FieldVector3D<T> ru2Dot = rotation.applyTo(u2.getVelocity());
130
131
132 rotationRate = inverseCrossProducts(v1.getPosition(), ru1Dot.subtract(v1.getVelocity()),
133 v2.getPosition(), ru2Dot.subtract(v2.getVelocity()),
134 tolerance);
135
136
137
138
139
140 final FieldVector3D<T> ru1DotDot = rotation.applyTo(u1.getAcceleration());
141 final FieldVector3D<T> oDotv1 = FieldVector3D.crossProduct(rotationRate, v1.getVelocity());
142 final FieldVector3D<T> oov1 = FieldVector3D.crossProduct(rotationRate, rotationRate.crossProduct(v1.getPosition()));
143 final FieldVector3D<T> c1 = new FieldVector3D<>(1, ru1DotDot, -2, oDotv1, -1, oov1, -1, v1.getAcceleration());
144 final FieldVector3D<T> ru2DotDot = rotation.applyTo(u2.getAcceleration());
145 final FieldVector3D<T> oDotv2 = FieldVector3D.crossProduct(rotationRate, v2.getVelocity());
146 final FieldVector3D<T> oov2 = FieldVector3D.crossProduct(rotationRate, rotationRate.crossProduct( v2.getPosition()));
147 final FieldVector3D<T> c2 = new FieldVector3D<>(1, ru2DotDot, -2, oDotv2, -1, oov2, -1, v2.getAcceleration());
148 rotationAcceleration = inverseCrossProducts(v1.getPosition(), c1, v2.getPosition(), c2, tolerance);
149
150 } catch (MathIllegalArgumentException miae) {
151 throw new OrekitException(miae);
152 }
153
154 }
155
156
157
158
159
160 public FieldAngularCoordinates(final Field<T> field, final AngularCoordinates ang) {
161 this.rotation = new FieldRotation<>(field, ang.getRotation());
162 this.rotationRate = new FieldVector3D<>(field, ang.getRotationRate());
163 this.rotationAcceleration = new FieldVector3D<>(field, ang.getRotationAcceleration());
164 }
165
166
167
168
169
170
171
172
173
174
175 public <U extends FieldDerivative<T, U>> FieldAngularCoordinates(final FieldRotation<U> r) {
176
177 final T q0 = r.getQ0().getValue();
178 final T q1 = r.getQ1().getValue();
179 final T q2 = r.getQ2().getValue();
180 final T q3 = r.getQ3().getValue();
181
182 rotation = new FieldRotation<>(q0, q1, q2, q3, false);
183 if (r.getQ0().getOrder() >= 1) {
184 final T q0Dot = r.getQ0().getPartialDerivative(1);
185 final T q1Dot = r.getQ1().getPartialDerivative(1);
186 final T q2Dot = r.getQ2().getPartialDerivative(1);
187 final T q3Dot = r.getQ3().getPartialDerivative(1);
188 rotationRate =
189 new FieldVector3D<>(q0.linearCombination(q1.negate(), q0Dot, q0, q1Dot,
190 q3, q2Dot, q2.negate(), q3Dot).multiply(2),
191 q0.linearCombination(q2.negate(), q0Dot, q3.negate(), q1Dot,
192 q0, q2Dot, q1, q3Dot).multiply(2),
193 q0.linearCombination(q3.negate(), q0Dot, q2, q1Dot,
194 q1.negate(), q2Dot, q0, q3Dot).multiply(2));
195 if (r.getQ0().getOrder() >= 2) {
196 final T q0DotDot = r.getQ0().getPartialDerivative(2);
197 final T q1DotDot = r.getQ1().getPartialDerivative(2);
198 final T q2DotDot = r.getQ2().getPartialDerivative(2);
199 final T q3DotDot = r.getQ3().getPartialDerivative(2);
200 rotationAcceleration =
201 new FieldVector3D<>(q0.linearCombination(q1.negate(), q0DotDot, q0, q1DotDot,
202 q3, q2DotDot, q2.negate(), q3DotDot).multiply(2),
203 q0.linearCombination(q2.negate(), q0DotDot, q3.negate(), q1DotDot,
204 q0, q2DotDot, q1, q3DotDot).multiply(2),
205 q0.linearCombination(q3.negate(), q0DotDot, q2, q1DotDot,
206 q1.negate(), q2DotDot, q0, q3DotDot).multiply(2));
207 } else {
208 rotationAcceleration = FieldVector3D.getZero(q0.getField());
209 }
210 } else {
211 rotationRate = FieldVector3D.getZero(q0.getField());
212 rotationAcceleration = FieldVector3D.getZero(q0.getField());
213 }
214
215 }
216
217
218
219
220
221
222
223 public static <T extends CalculusFieldElement<T>> FieldAngularCoordinates<T> getIdentity(final Field<T> field) {
224 return new FieldAngularCoordinates<>(field, AngularCoordinates.IDENTITY);
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 private static <T extends CalculusFieldElement<T>> FieldVector3D<T> inverseCrossProducts(final FieldVector3D<T> v1, final FieldVector3D<T> c1,
246 final FieldVector3D<T> v2, final FieldVector3D<T> c2,
247 final double tolerance)
248 throws MathIllegalArgumentException {
249
250 final T v12 = v1.getNormSq();
251 final T v1n = v12.sqrt();
252 final T v22 = v2.getNormSq();
253 final T v2n = v22.sqrt();
254 final T threshold;
255 if (v1n.getReal() >= v2n.getReal()) {
256 threshold = v1n.multiply(tolerance);
257 }
258 else {
259 threshold = v2n.multiply(tolerance);
260 }
261 FieldVector3D<T> omega = null;
262
263 try {
264
265 final FieldMatrix<T> m = MatrixUtils.createFieldMatrix(v12.getField(), 6, 3);
266 m.setEntry(0, 1, v1.getZ());
267 m.setEntry(0, 2, v1.getY().negate());
268 m.setEntry(1, 0, v1.getZ().negate());
269 m.setEntry(1, 2, v1.getX());
270 m.setEntry(2, 0, v1.getY());
271 m.setEntry(2, 1, v1.getX().negate());
272 m.setEntry(3, 1, v2.getZ());
273 m.setEntry(3, 2, v2.getY().negate());
274 m.setEntry(4, 0, v2.getZ().negate());
275 m.setEntry(4, 2, v2.getX());
276 m.setEntry(5, 0, v2.getY());
277 m.setEntry(5, 1, v2.getX().negate());
278
279 final T[] kk = MathArrays.buildArray(v2n.getField(), 6);
280 kk[0] = c1.getX();
281 kk[1] = c1.getY();
282 kk[2] = c1.getZ();
283 kk[3] = c2.getX();
284 kk[4] = c2.getY();
285 kk[5] = c2.getZ();
286 final FieldVector<T> rhs = MatrixUtils.createFieldVector(kk);
287
288
289 final FieldDecompositionSolver<T> solver = new FieldQRDecomposition<>(m).getSolver();
290 final FieldVector<T> v = solver.solve(rhs);
291 omega = new FieldVector3D<>(v.getEntry(0), v.getEntry(1), v.getEntry(2));
292
293 } catch (MathIllegalArgumentException miae) {
294 if (miae.getSpecifier() == LocalizedCoreFormats.SINGULAR_MATRIX) {
295
296
297 final T c12 = c1.getNormSq();
298 final T c1n = c12.sqrt();
299 final T c22 = c2.getNormSq();
300 final T c2n = c22.sqrt();
301 if (c1n.getReal() <= threshold.getReal() && c2n.getReal() <= threshold.getReal()) {
302
303 return new FieldVector3D<>(v12.getField().getZero(), v12.getField().getZero(), v12.getField().getZero());
304 } else if (v1n.getReal() <= threshold.getReal() && c1n.getReal() >= threshold.getReal()) {
305
306 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
307 c1n.getReal(), 0, true);
308 } else if (v2n.getReal() <= threshold.getReal() && c2n.getReal() >= threshold.getReal()) {
309
310 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
311 c2n.getReal(), 0, true);
312 } else if (v1.crossProduct(v1).getNorm().getReal() <= threshold.getReal() && v12.getReal() > threshold.getReal()) {
313
314
315 omega = new FieldVector3D<>(v12.reciprocal(), v1.crossProduct(c1));
316 } else {
317 throw miae;
318 }
319 } else {
320 throw miae;
321 }
322 }
323
324 final T d1 = FieldVector3D.distance(omega.crossProduct(v1), c1);
325 if (d1.getReal() > threshold.getReal()) {
326 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE, 0, true);
327 }
328
329 final T d2 = FieldVector3D.distance(omega.crossProduct(v2), c2);
330 if (d2.getReal() > threshold.getReal()) {
331 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE, 0, true);
332 }
333
334 return omega;
335
336 }
337
338
339
340
341
342
343
344
345
346
347 public FieldRotation<FieldDerivativeStructure<T>> toDerivativeStructureRotation(final int order) {
348
349
350 final T q0 = rotation.getQ0();
351 final T q1 = rotation.getQ1();
352 final T q2 = rotation.getQ2();
353 final T q3 = rotation.getQ3();
354
355
356 final T oX = rotationRate.getX();
357 final T oY = rotationRate.getY();
358 final T oZ = rotationRate.getZ();
359 final T q0Dot = q0.linearCombination(q1.negate(), oX, q2.negate(), oY, q3.negate(), oZ).multiply(0.5);
360 final T q1Dot = q0.linearCombination(q0, oX, q3.negate(), oY, q2, oZ).multiply(0.5);
361 final T q2Dot = q0.linearCombination(q3, oX, q0, oY, q1.negate(), oZ).multiply(0.5);
362 final T q3Dot = q0.linearCombination(q2.negate(), oX, q1, oY, q0, oZ).multiply(0.5);
363
364
365 final T oXDot = rotationAcceleration.getX();
366 final T oYDot = rotationAcceleration.getY();
367 final T oZDot = rotationAcceleration.getZ();
368 final T q0DotDot = q0.linearCombination(array6(q1, q2, q3, q1Dot, q2Dot, q3Dot),
369 array6(oXDot, oYDot, oZDot, oX, oY, oZ)).multiply(-0.5);
370 final T q1DotDot = q0.linearCombination(array6(q0, q2, q3.negate(), q0Dot, q2Dot, q3Dot.negate()),
371 array6(oXDot, oZDot, oYDot, oX, oZ, oY)).multiply(0.5);
372 final T q2DotDot = q0.linearCombination(array6(q0, q3, q1.negate(), q0Dot, q3Dot, q1Dot.negate()),
373 array6(oYDot, oXDot, oZDot, oY, oX, oZ)).multiply(0.5);
374 final T q3DotDot = q0.linearCombination(array6(q0, q1, q2.negate(), q0Dot, q1Dot, q2Dot.negate()),
375 array6(oZDot, oYDot, oXDot, oZ, oY, oX)).multiply(0.5);
376
377 final FDSFactory<T> factory;
378 final FieldDerivativeStructure<T> q0DS;
379 final FieldDerivativeStructure<T> q1DS;
380 final FieldDerivativeStructure<T> q2DS;
381 final FieldDerivativeStructure<T> q3DS;
382 switch(order) {
383 case 0 :
384 factory = new FDSFactory<>(q0.getField(), 1, order);
385 q0DS = factory.build(q0);
386 q1DS = factory.build(q1);
387 q2DS = factory.build(q2);
388 q3DS = factory.build(q3);
389 break;
390 case 1 :
391 factory = new FDSFactory<>(q0.getField(), 1, order);
392 q0DS = factory.build(q0, q0Dot);
393 q1DS = factory.build(q1, q1Dot);
394 q2DS = factory.build(q2, q2Dot);
395 q3DS = factory.build(q3, q3Dot);
396 break;
397 case 2 :
398 factory = new FDSFactory<>(q0.getField(), 1, order);
399 q0DS = factory.build(q0, q0Dot, q0DotDot);
400 q1DS = factory.build(q1, q1Dot, q1DotDot);
401 q2DS = factory.build(q2, q2Dot, q2DotDot);
402 q3DS = factory.build(q3, q3Dot, q3DotDot);
403 break;
404 default :
405 throw new OrekitException(OrekitMessages.OUT_OF_RANGE_DERIVATION_ORDER, order);
406 }
407
408 return new FieldRotation<>(q0DS, q1DS, q2DS, q3DS, false);
409
410 }
411
412
413
414
415
416
417
418
419 public FieldRotation<FieldUnivariateDerivative1<T>> toUnivariateDerivative1Rotation() {
420
421
422 final T q0 = rotation.getQ0();
423 final T q1 = rotation.getQ1();
424 final T q2 = rotation.getQ2();
425 final T q3 = rotation.getQ3();
426
427
428 final T oX = rotationRate.getX();
429 final T oY = rotationRate.getY();
430 final T oZ = rotationRate.getZ();
431 final T q0Dot = q0.linearCombination(q1.negate(), oX, q2.negate(), oY, q3.negate(), oZ).multiply(0.5);
432 final T q1Dot = q0.linearCombination(q0, oX, q3.negate(), oY, q2, oZ).multiply(0.5);
433 final T q2Dot = q0.linearCombination(q3, oX, q0, oY, q1.negate(), oZ).multiply(0.5);
434 final T q3Dot = q0.linearCombination(q2.negate(), oX, q1, oY, q0, oZ).multiply(0.5);
435
436 final FieldUnivariateDerivative1<T> q0UD = new FieldUnivariateDerivative1<>(q0, q0Dot);
437 final FieldUnivariateDerivative1<T> q1UD = new FieldUnivariateDerivative1<>(q1, q1Dot);
438 final FieldUnivariateDerivative1<T> q2UD = new FieldUnivariateDerivative1<>(q2, q2Dot);
439 final FieldUnivariateDerivative1<T> q3UD = new FieldUnivariateDerivative1<>(q3, q3Dot);
440
441 return new FieldRotation<>(q0UD, q1UD, q2UD, q3UD, false);
442
443 }
444
445
446
447
448
449
450
451
452 public FieldRotation<FieldUnivariateDerivative2<T>> toUnivariateDerivative2Rotation() {
453
454
455 final T q0 = rotation.getQ0();
456 final T q1 = rotation.getQ1();
457 final T q2 = rotation.getQ2();
458 final T q3 = rotation.getQ3();
459
460
461 final T oX = rotationRate.getX();
462 final T oY = rotationRate.getY();
463 final T oZ = rotationRate.getZ();
464 final T q0Dot = q0.linearCombination(q1.negate(), oX, q2.negate(), oY, q3.negate(), oZ).multiply(0.5);
465 final T q1Dot = q0.linearCombination(q0, oX, q3.negate(), oY, q2, oZ).multiply(0.5);
466 final T q2Dot = q0.linearCombination(q3, oX, q0, oY, q1.negate(), oZ).multiply(0.5);
467 final T q3Dot = q0.linearCombination(q2.negate(), oX, q1, oY, q0, oZ).multiply(0.5);
468
469
470 final T oXDot = rotationAcceleration.getX();
471 final T oYDot = rotationAcceleration.getY();
472 final T oZDot = rotationAcceleration.getZ();
473 final T q0DotDot = q0.linearCombination(array6(q1, q2, q3, q1Dot, q2Dot, q3Dot),
474 array6(oXDot, oYDot, oZDot, oX, oY, oZ)).multiply(-0.5);
475 final T q1DotDot = q0.linearCombination(array6(q0, q2, q3.negate(), q0Dot, q2Dot, q3Dot.negate()),
476 array6(oXDot, oZDot, oYDot, oX, oZ, oY)).multiply(0.5);
477 final T q2DotDot = q0.linearCombination(array6(q0, q3, q1.negate(), q0Dot, q3Dot, q1Dot.negate()),
478 array6(oYDot, oXDot, oZDot, oY, oX, oZ)).multiply(0.5);
479 final T q3DotDot = q0.linearCombination(array6(q0, q1, q2.negate(), q0Dot, q1Dot, q2Dot.negate()),
480 array6(oZDot, oYDot, oXDot, oZ, oY, oX)).multiply(0.5);
481
482 final FieldUnivariateDerivative2<T> q0UD = new FieldUnivariateDerivative2<>(q0, q0Dot, q0DotDot);
483 final FieldUnivariateDerivative2<T> q1UD = new FieldUnivariateDerivative2<>(q1, q1Dot, q1DotDot);
484 final FieldUnivariateDerivative2<T> q2UD = new FieldUnivariateDerivative2<>(q2, q2Dot, q2DotDot);
485 final FieldUnivariateDerivative2<T> q3UD = new FieldUnivariateDerivative2<>(q3, q3Dot, q3DotDot);
486
487 return new FieldRotation<>(q0UD, q1UD, q2UD, q3UD, false);
488
489 }
490
491
492
493
494
495
496
497
498
499
500
501 private T[] array6(final T e1, final T e2, final T e3, final T e4, final T e5, final T e6) {
502 final T[] array = MathArrays.buildArray(e1.getField(), 6);
503 array[0] = e1;
504 array[1] = e2;
505 array[2] = e3;
506 array[3] = e4;
507 array[4] = e5;
508 array[5] = e6;
509 return array;
510 }
511
512
513
514
515
516
517
518
519
520
521 public static <T extends CalculusFieldElement<T>>
522 FieldVector3D<T> estimateRate(final FieldRotation<T> start,
523 final FieldRotation<T> end,
524 final double dt) {
525 return estimateRate(start, end, start.getQ0().getField().getZero().add(dt));
526 }
527
528
529
530
531
532
533
534
535
536
537 public static <T extends CalculusFieldElement<T>>
538 FieldVector3D<T> estimateRate(final FieldRotation<T> start,
539 final FieldRotation<T> end,
540 final T dt) {
541 final FieldRotation<T> evolution = start.compose(end.revert(), RotationConvention.VECTOR_OPERATOR);
542 return new FieldVector3D<>(evolution.getAngle().divide(dt),
543 evolution.getAxis(RotationConvention.VECTOR_OPERATOR));
544 }
545
546
547
548
549
550
551
552
553
554 public FieldAngularCoordinates<T> revert() {
555 return new FieldAngularCoordinates<>(rotation.revert(),
556 rotation.applyInverseTo(rotationRate.negate()),
557 rotation.applyInverseTo(rotationAcceleration.negate()));
558 }
559
560
561
562
563
564
565
566
567
568
569
570 public FieldAngularCoordinates<T> shiftedBy(final double dt) {
571 return shiftedBy(rotation.getQ0().getField().getZero().add(dt));
572 }
573
574
575
576
577
578
579
580
581
582
583
584 public FieldAngularCoordinates<T> shiftedBy(final T dt) {
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600 final T rate = rotationRate.getNorm();
601 final T zero = rate.getField().getZero();
602 final T one = rate.getField().getOne();
603 final FieldRotation<T> rateContribution = (rate.getReal() == 0.0) ?
604 new FieldRotation<>(one, zero, zero, zero, false) :
605 new FieldRotation<>(rotationRate,
606 rate.multiply(dt),
607 RotationConvention.FRAME_TRANSFORM);
608
609
610 final FieldAngularCoordinates<T> linearPart =
611 new FieldAngularCoordinates<>(rateContribution.compose(rotation, RotationConvention.VECTOR_OPERATOR),
612 rotationRate);
613
614 final T acc = rotationAcceleration.getNorm();
615 if (acc.getReal() == 0.0) {
616
617 return linearPart;
618 }
619
620
621
622
623
624 final FieldAngularCoordinates<T> quadraticContribution =
625 new FieldAngularCoordinates<>(new FieldRotation<>(rotationAcceleration,
626 acc.multiply(dt.multiply(0.5).multiply(dt)),
627 RotationConvention.FRAME_TRANSFORM),
628 new FieldVector3D<>(dt, rotationAcceleration),
629 rotationAcceleration);
630
631
632
633
634
635 return quadraticContribution.addOffset(linearPart);
636
637 }
638
639
640
641
642 public FieldRotation<T> getRotation() {
643 return rotation;
644 }
645
646
647
648
649 public FieldVector3D<T> getRotationRate() {
650 return rotationRate;
651 }
652
653
654
655
656 public FieldVector3D<T> getRotationAcceleration() {
657 return rotationAcceleration;
658 }
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678 public FieldAngularCoordinates<T> addOffset(final FieldAngularCoordinates<T> offset) {
679 final FieldVector3D<T> rOmega = rotation.applyTo(offset.rotationRate);
680 final FieldVector3D<T> rOmegaDot = rotation.applyTo(offset.rotationAcceleration);
681 return new FieldAngularCoordinates<>(rotation.compose(offset.rotation, RotationConvention.VECTOR_OPERATOR),
682 rotationRate.add(rOmega),
683 new FieldVector3D<>( 1.0, rotationAcceleration,
684 1.0, rOmegaDot,
685 -1.0, FieldVector3D.crossProduct(rotationRate, rOmega)));
686 }
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706 public FieldAngularCoordinates<T> subtractOffset(final FieldAngularCoordinates<T> offset) {
707 return addOffset(offset.revert());
708 }
709
710
711
712
713 public AngularCoordinates toAngularCoordinates() {
714 return new AngularCoordinates(rotation.toRotation(), rotationRate.toVector3D(),
715 rotationAcceleration.toVector3D());
716 }
717
718
719
720
721
722 public FieldPVCoordinates<T> applyTo(final PVCoordinates pv) {
723
724 final FieldVector3D<T> transformedP = rotation.applyTo(pv.getPosition());
725 final FieldVector3D<T> crossP = FieldVector3D.crossProduct(rotationRate, transformedP);
726 final FieldVector3D<T> transformedV = rotation.applyTo(pv.getVelocity()).subtract(crossP);
727 final FieldVector3D<T> crossV = FieldVector3D.crossProduct(rotationRate, transformedV);
728 final FieldVector3D<T> crossCrossP = FieldVector3D.crossProduct(rotationRate, crossP);
729 final FieldVector3D<T> crossDotP = FieldVector3D.crossProduct(rotationAcceleration, transformedP);
730 final FieldVector3D<T> transformedA = new FieldVector3D<>( 1, rotation.applyTo(pv.getAcceleration()),
731 -2, crossV,
732 -1, crossCrossP,
733 -1, crossDotP);
734
735 return new FieldPVCoordinates<>(transformedP, transformedV, transformedA);
736
737 }
738
739
740
741
742
743 public TimeStampedFieldPVCoordinates<T> applyTo(final TimeStampedPVCoordinates pv) {
744
745 final FieldVector3D<T> transformedP = rotation.applyTo(pv.getPosition());
746 final FieldVector3D<T> crossP = FieldVector3D.crossProduct(rotationRate, transformedP);
747 final FieldVector3D<T> transformedV = rotation.applyTo(pv.getVelocity()).subtract(crossP);
748 final FieldVector3D<T> crossV = FieldVector3D.crossProduct(rotationRate, transformedV);
749 final FieldVector3D<T> crossCrossP = FieldVector3D.crossProduct(rotationRate, crossP);
750 final FieldVector3D<T> crossDotP = FieldVector3D.crossProduct(rotationAcceleration, transformedP);
751 final FieldVector3D<T> transformedA = new FieldVector3D<>( 1, rotation.applyTo(pv.getAcceleration()),
752 -2, crossV,
753 -1, crossCrossP,
754 -1, crossDotP);
755
756 return new TimeStampedFieldPVCoordinates<>(pv.getDate(), transformedP, transformedV, transformedA);
757
758 }
759
760
761
762
763
764
765 public FieldPVCoordinates<T> applyTo(final FieldPVCoordinates<T> pv) {
766
767 final FieldVector3D<T> transformedP = rotation.applyTo(pv.getPosition());
768 final FieldVector3D<T> crossP = FieldVector3D.crossProduct(rotationRate, transformedP);
769 final FieldVector3D<T> transformedV = rotation.applyTo(pv.getVelocity()).subtract(crossP);
770 final FieldVector3D<T> crossV = FieldVector3D.crossProduct(rotationRate, transformedV);
771 final FieldVector3D<T> crossCrossP = FieldVector3D.crossProduct(rotationRate, crossP);
772 final FieldVector3D<T> crossDotP = FieldVector3D.crossProduct(rotationAcceleration, transformedP);
773 final FieldVector3D<T> transformedA = new FieldVector3D<>( 1, rotation.applyTo(pv.getAcceleration()),
774 -2, crossV,
775 -1, crossCrossP,
776 -1, crossDotP);
777
778 return new FieldPVCoordinates<>(transformedP, transformedV, transformedA);
779
780 }
781
782
783
784
785
786
787 public TimeStampedFieldPVCoordinates<T> applyTo(final TimeStampedFieldPVCoordinates<T> pv) {
788
789 final FieldVector3D<T> transformedP = rotation.applyTo(pv.getPosition());
790 final FieldVector3D<T> crossP = FieldVector3D.crossProduct(rotationRate, transformedP);
791 final FieldVector3D<T> transformedV = rotation.applyTo(pv.getVelocity()).subtract(crossP);
792 final FieldVector3D<T> crossV = FieldVector3D.crossProduct(rotationRate, transformedV);
793 final FieldVector3D<T> crossCrossP = FieldVector3D.crossProduct(rotationRate, crossP);
794 final FieldVector3D<T> crossDotP = FieldVector3D.crossProduct(rotationAcceleration, transformedP);
795 final FieldVector3D<T> transformedA = new FieldVector3D<>( 1, rotation.applyTo(pv.getAcceleration()),
796 -2, crossV,
797 -1, crossCrossP,
798 -1, crossDotP);
799
800 return new TimeStampedFieldPVCoordinates<>(pv.getDate(), transformedP, transformedV, transformedA);
801
802 }
803
804
805
806
807
808
809
810
811
812
813
814
815 public T[][] getModifiedRodrigues(final double sign) {
816
817 final T q0 = getRotation().getQ0().multiply(sign);
818 final T q1 = getRotation().getQ1().multiply(sign);
819 final T q2 = getRotation().getQ2().multiply(sign);
820 final T q3 = getRotation().getQ3().multiply(sign);
821 final T oX = getRotationRate().getX();
822 final T oY = getRotationRate().getY();
823 final T oZ = getRotationRate().getZ();
824 final T oXDot = getRotationAcceleration().getX();
825 final T oYDot = getRotationAcceleration().getY();
826 final T oZDot = getRotationAcceleration().getZ();
827
828
829 final T q0Dot = q0.linearCombination(q1.negate(), oX, q2.negate(), oY, q3.negate(), oZ).multiply(0.5);
830 final T q1Dot = q0.linearCombination( q0, oX, q3.negate(), oY, q2, oZ).multiply(0.5);
831 final T q2Dot = q0.linearCombination( q3, oX, q0, oY, q1.negate(), oZ).multiply(0.5);
832 final T q3Dot = q0.linearCombination(q2.negate(), oX, q1, oY, q0, oZ).multiply(0.5);
833
834
835 final T q0DotDot = linearCombination(q1, oXDot, q2, oYDot, q3, oZDot,
836 q1Dot, oX, q2Dot, oY, q3Dot, oZ).
837 multiply(-0.5);
838 final T q1DotDot = linearCombination(q0, oXDot, q2, oZDot, q3.negate(), oYDot,
839 q0Dot, oX, q2Dot, oZ, q3Dot.negate(), oY).
840 multiply(0.5);
841 final T q2DotDot = linearCombination(q0, oYDot, q3, oXDot, q1.negate(), oZDot,
842 q0Dot, oY, q3Dot, oX, q1Dot.negate(), oZ).
843 multiply(0.5);
844 final T q3DotDot = linearCombination(q0, oZDot, q1, oYDot, q2.negate(), oXDot,
845 q0Dot, oZ, q1Dot, oY, q2Dot.negate(), oX).
846 multiply(0.5);
847
848
849
850
851
852 final T inv = q0.add(1).reciprocal();
853 final T mTwoInvQ0Dot = inv.multiply(q0Dot).multiply(-2);
854
855 final T r1 = inv.multiply(q1);
856 final T r2 = inv.multiply(q2);
857 final T r3 = inv.multiply(q3);
858
859 final T mInvR1 = inv.multiply(r1).negate();
860 final T mInvR2 = inv.multiply(r2).negate();
861 final T mInvR3 = inv.multiply(r3).negate();
862
863 final T r1Dot = q0.linearCombination(inv, q1Dot, mInvR1, q0Dot);
864 final T r2Dot = q0.linearCombination(inv, q2Dot, mInvR2, q0Dot);
865 final T r3Dot = q0.linearCombination(inv, q3Dot, mInvR3, q0Dot);
866
867 final T r1DotDot = q0.linearCombination(inv, q1DotDot, mTwoInvQ0Dot, r1Dot, mInvR1, q0DotDot);
868 final T r2DotDot = q0.linearCombination(inv, q2DotDot, mTwoInvQ0Dot, r2Dot, mInvR2, q0DotDot);
869 final T r3DotDot = q0.linearCombination(inv, q3DotDot, mTwoInvQ0Dot, r3Dot, mInvR3, q0DotDot);
870
871 final T[][] rodrigues = MathArrays.buildArray(q0.getField(), 3, 3);
872 rodrigues[0][0] = r1;
873 rodrigues[0][1] = r2;
874 rodrigues[0][2] = r3;
875 rodrigues[1][0] = r1Dot;
876 rodrigues[1][1] = r2Dot;
877 rodrigues[1][2] = r3Dot;
878 rodrigues[2][0] = r1DotDot;
879 rodrigues[2][1] = r2DotDot;
880 rodrigues[2][2] = r3DotDot;
881 return rodrigues;
882
883 }
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903 private T linearCombination(final T a1, final T b1, final T a2, final T b2, final T a3, final T b3,
904 final T a4, final T b4, final T a5, final T b5, final T a6, final T b6) {
905
906 final T[] a = MathArrays.buildArray(a1.getField(), 6);
907 a[0] = a1;
908 a[1] = a2;
909 a[2] = a3;
910 a[3] = a4;
911 a[4] = a5;
912 a[5] = a6;
913
914 final T[] b = MathArrays.buildArray(b1.getField(), 6);
915 b[0] = b1;
916 b[1] = b2;
917 b[2] = b3;
918 b[3] = b4;
919 b[4] = b5;
920 b[5] = b6;
921
922 return a1.linearCombination(a, b);
923
924 }
925
926
927
928
929
930
931
932
933 public static <T extends CalculusFieldElement<T>> FieldAngularCoordinates<T> createFromModifiedRodrigues(final T[][] r) {
934
935
936 final T rSquared = r[0][0].multiply(r[0][0]).add(r[0][1].multiply(r[0][1])).add(r[0][2].multiply(r[0][2]));
937 final T oPQ0 = rSquared.add(1).reciprocal().multiply(2);
938 final T q0 = oPQ0.subtract(1);
939 final T q1 = oPQ0.multiply(r[0][0]);
940 final T q2 = oPQ0.multiply(r[0][1]);
941 final T q3 = oPQ0.multiply(r[0][2]);
942
943
944 final T oPQ02 = oPQ0.multiply(oPQ0);
945 final T q0Dot = oPQ02.multiply(q0.linearCombination(r[0][0], r[1][0], r[0][1], r[1][1], r[0][2], r[1][2])).negate();
946 final T q1Dot = oPQ0.multiply(r[1][0]).add(r[0][0].multiply(q0Dot));
947 final T q2Dot = oPQ0.multiply(r[1][1]).add(r[0][1].multiply(q0Dot));
948 final T q3Dot = oPQ0.multiply(r[1][2]).add(r[0][2].multiply(q0Dot));
949 final T oX = q0.linearCombination(q1.negate(), q0Dot, q0, q1Dot, q3, q2Dot, q2.negate(), q3Dot).multiply(2);
950 final T oY = q0.linearCombination(q2.negate(), q0Dot, q3.negate(), q1Dot, q0, q2Dot, q1, q3Dot).multiply(2);
951 final T oZ = q0.linearCombination(q3.negate(), q0Dot, q2, q1Dot, q1.negate(), q2Dot, q0, q3Dot).multiply(2);
952
953
954 final T q0DotDot = q0.subtract(1).negate().divide(oPQ0).multiply(q0Dot).multiply(q0Dot).
955 subtract(oPQ02.multiply(q0.linearCombination(r[0][0], r[2][0], r[0][1], r[2][1], r[0][2], r[2][2]))).
956 subtract(q1Dot.multiply(q1Dot).add(q2Dot.multiply(q2Dot)).add(q3Dot.multiply(q3Dot)));
957 final T q1DotDot = q0.linearCombination(oPQ0, r[2][0], r[1][0].add(r[1][0]), q0Dot, r[0][0], q0DotDot);
958 final T q2DotDot = q0.linearCombination(oPQ0, r[2][1], r[1][1].add(r[1][1]), q0Dot, r[0][1], q0DotDot);
959 final T q3DotDot = q0.linearCombination(oPQ0, r[2][2], r[1][2].add(r[1][2]), q0Dot, r[0][2], q0DotDot);
960 final T oXDot = q0.linearCombination(q1.negate(), q0DotDot, q0, q1DotDot, q3, q2DotDot, q2.negate(), q3DotDot).multiply(2);
961 final T oYDot = q0.linearCombination(q2.negate(), q0DotDot, q3.negate(), q1DotDot, q0, q2DotDot, q1, q3DotDot).multiply(2);
962 final T oZDot = q0.linearCombination(q3.negate(), q0DotDot, q2, q1DotDot, q1.negate(), q2DotDot, q0, q3DotDot).multiply(2);
963
964 return new FieldAngularCoordinates<>(new FieldRotation<>(q0, q1, q2, q3, false),
965 new FieldVector3D<>(oX, oY, oZ),
966 new FieldVector3D<>(oXDot, oYDot, oZDot));
967
968 }
969
970 }