1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.rugged.los;
18
19 import java.util.stream.Stream;
20
21 import org.hipparchus.Field;
22 import org.hipparchus.analysis.differentiation.Derivative;
23 import org.hipparchus.analysis.polynomials.PolynomialFunction;
24 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
25 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26 import org.hipparchus.geometry.euclidean.threed.Rotation;
27 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
28 import org.hipparchus.geometry.euclidean.threed.Vector3D;
29 import org.hipparchus.util.FastMath;
30 import org.hipparchus.util.MathArrays;
31 import org.orekit.rugged.utils.DerivativeGenerator;
32 import org.orekit.time.AbsoluteDate;
33 import org.orekit.utils.ParameterDriver;
34 import org.orekit.utils.ParameterObserver;
35 import org.orekit.utils.TimeSpanMap;
36
37
38
39
40
41 public class PolynomialRotation implements LOSTransform {
42
43
44
45
46
47
48
49 private final double SCALE = FastMath.scalb(1.0, -20);
50
51
52 private final Vector3D axis;
53
54
55 private PolynomialFunction angle;
56
57
58 private FieldVector3D<?> axisDS;
59
60
61 private Derivative<?>[] angleDS;
62
63
64 private final AbsoluteDate referenceDate;
65
66
67 private final ParameterDriver[] coefficientsDrivers;
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 public PolynomialRotation(final String name,
83 final Vector3D axis,
84 final AbsoluteDate referenceDate,
85 final double... angleCoeffs) {
86 this.axis = axis;
87 this.referenceDate = referenceDate;
88 this.coefficientsDrivers = new ParameterDriver[angleCoeffs.length];
89 final ParameterObserver resettingObserver = new ParameterObserver() {
90 @Override
91 public void valueChanged(final double previousValue, final ParameterDriver driver, final AbsoluteDate date) {
92
93 angle = null;
94 axisDS = null;
95 angleDS = null;
96 }
97
98 @Override
99 public void valueSpanMapChanged(final TimeSpanMap<Double> previousValueSpanMap, final ParameterDriver driver) {
100
101 angle = null;
102 axisDS = null;
103 angleDS = null;
104 }
105 };
106 for (int i = 0; i < angleCoeffs.length; ++i) {
107 coefficientsDrivers[i] = new ParameterDriver(name + "[" + i + "]", angleCoeffs[i], SCALE,
108 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
109 coefficientsDrivers[i].addObserver(resettingObserver);
110 }
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125 public PolynomialRotation(final String name,
126 final Vector3D axis,
127 final AbsoluteDate referenceDate,
128 final PolynomialFunction angle) {
129 this(name, axis, referenceDate, angle.getCoefficients());
130 }
131
132
133
134
135 @Override
136 public Stream<ParameterDriver> getParametersDrivers() {
137 return Stream.of(coefficientsDrivers);
138 }
139
140
141 @Override
142 public Vector3D transformLOS(final int i, final Vector3D los, final AbsoluteDate date) {
143 if (angle == null) {
144
145 final double[] coefficients = new double[coefficientsDrivers.length];
146 for (int k = 0; k < coefficients.length; ++k) {
147 coefficients[k] = coefficientsDrivers[k].getValue();
148 }
149 angle = new PolynomialFunction(coefficients);
150 }
151 return new Rotation(axis,
152 angle.value(date.durationFrom(referenceDate)),
153 RotationConvention.VECTOR_OPERATOR).applyTo(los);
154 }
155
156
157 @SuppressWarnings("unchecked")
158 @Override
159 public <T extends Derivative<T>> FieldVector3D<T> transformLOS(final int i, final FieldVector3D<T> los,
160 final AbsoluteDate date,
161 final DerivativeGenerator<T> generator) {
162
163 final Field<T> field = generator.getField();
164 final FieldVector3D<T> axisD;
165 final T[] angleD;
166 if (axisDS == null || !axisDS.getX().getField().equals(field)) {
167
168
169 axisD = new FieldVector3D<>(generator.constant(axis.getX()),
170 generator.constant(axis.getY()),
171 generator.constant(axis.getZ()));
172 angleD = MathArrays.buildArray(field, coefficientsDrivers.length);
173 for (int k = 0; k < angleD.length; ++k) {
174 angleD[k] = generator.variable(coefficientsDrivers[k]);
175 }
176
177
178 axisDS = axisD;
179 angleDS = angleD;
180
181 } else {
182
183 axisD = (FieldVector3D<T>) axisDS;
184 angleD = (T[]) angleDS;
185 }
186
187
188 final double t = date.durationFrom(referenceDate);
189 T alpha = field.getZero();
190 for (int k = angleDS.length - 1; k >= 0; --k) {
191 alpha = alpha.multiply(t).add(angleD[k]);
192 }
193
194 return new FieldRotation<>(axisD, alpha, RotationConvention.VECTOR_OPERATOR).applyTo(los);
195
196 }
197
198 }