1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.radiation;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22
23 import org.hipparchus.CalculusFieldElement;
24 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
25 import org.hipparchus.geometry.euclidean.threed.Vector3D;
26 import org.hipparchus.util.FastMath;
27 import org.hipparchus.util.FieldSinCos;
28 import org.hipparchus.util.SinCos;
29 import org.orekit.annotation.DefaultDataContext;
30 import org.orekit.bodies.OneAxisEllipsoid;
31 import org.orekit.frames.FramesFactory;
32 import org.orekit.propagation.FieldSpacecraftState;
33 import org.orekit.propagation.SpacecraftState;
34 import org.orekit.utils.ExtendedPositionProvider;
35 import org.orekit.utils.ParameterDriver;
36
37
38
39
40
41
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 public class ECOM2 extends AbstractRadiationForceModel {
77
78
79 public static final String ECOM_COEFFICIENT = "ECOM coefficient";
80
81
82 private static final double MIN_VALUE = Double.NEGATIVE_INFINITY;
83
84
85 private static final double MAX_VALUE = Double.POSITIVE_INFINITY;
86
87
88
89
90
91
92
93 private final double SCALE = FastMath.scalb(1.0, -22);
94
95
96 private final int nD;
97
98
99 private final int nB;
100
101
102
103
104
105
106
107 private final List<ParameterDriver> coefficients;
108
109
110 private final ExtendedPositionProvider sun;
111
112
113
114
115
116
117
118
119
120 @DefaultDataContext
121 public ECOM2(final int nD, final int nB, final double value,
122 final ExtendedPositionProvider sun, final double equatorialRadius) {
123 super(sun, new OneAxisEllipsoid(equatorialRadius, 0.0, FramesFactory.getGCRF()),
124 getDefaultEclipseDetectionSettings());
125 this.nB = nB;
126 this.nD = nD;
127 this.coefficients = new ArrayList<>(2 * (nD + nB) + 3);
128
129
130 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " B0", value, SCALE, MIN_VALUE, MAX_VALUE));
131 for (int i = 1; i < nB + 1; i++) {
132 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " Bcos" + Integer.toString(i - 1), value, SCALE, MIN_VALUE, MAX_VALUE));
133 }
134 for (int i = nB + 1; i < 2 * nB + 1; i++) {
135 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " Bsin" + Integer.toString(i - (nB + 1)), value, SCALE, MIN_VALUE, MAX_VALUE));
136 }
137
138 coefficients.add(2 * nB + 1, new ParameterDriver(ECOM_COEFFICIENT + " D0", value, SCALE, MIN_VALUE, MAX_VALUE));
139 for (int i = 2 * nB + 2; i < 2 * nB + 2 + nD; i++) {
140 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " Dcos" + Integer.toString(i - (2 * nB + 2)), value, SCALE, MIN_VALUE, MAX_VALUE));
141 }
142 for (int i = 2 * nB + 2 + nD; i < 2 * (nB + nD) + 2; i++) {
143 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " Dsin" + Integer.toString(i - (2 * nB + nD + 2)), value, SCALE, MIN_VALUE, MAX_VALUE));
144 }
145
146 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " Y0", value, SCALE, MIN_VALUE, MAX_VALUE));
147
148
149 coefficients.forEach(parameter -> parameter.setSelected(true));
150 this.sun = sun;
151 }
152
153
154 @Override
155 public Vector3D acceleration(final SpacecraftState s, final double[] parameters) {
156
157
158 final Vector3D satPos = s.getPosition();
159 final Vector3D sunPos = sun.getPosition(s.getDate(), s.getFrame());
160
161
162 final Vector3D Z = s.getPVCoordinates().getMomentum();
163 final Vector3D Y = Z.crossProduct(sunPos).normalize();
164 final Vector3D X = Y.crossProduct(Z).normalize();
165
166
167 final Vector3D eD = sunPos.subtract(satPos).normalize();
168 final Vector3D eY = eD.crossProduct(satPos).normalize();
169 final Vector3D eB = eD.crossProduct(eY);
170
171
172 final double delta_u = FastMath.atan2(satPos.dotProduct(Y), satPos.dotProduct(X));
173
174
175 double b_u = parameters[0];
176 for (int i = 1; i < nB + 1; i++) {
177 final SinCos sc = FastMath.sinCos((2 * i - 1) * delta_u);
178 b_u += parameters[i] * sc.cos() + parameters[i + nB] * sc.sin();
179 }
180
181 double d_u = parameters[2 * nB + 1];
182 for (int i = 1; i < nD + 1; i++) {
183 final SinCos sc = FastMath.sinCos(2 * i * delta_u);
184 d_u += parameters[2 * nB + 1 + i] * sc.cos() + parameters[2 * nB + 1 + i + nD] * sc.sin();
185 }
186
187 return new Vector3D(d_u, eD, parameters[2 * (nD + nB) + 2], eY, b_u, eB);
188 }
189
190
191 @Override
192 public <T extends CalculusFieldElement<T>> FieldVector3D<T> acceleration(final FieldSpacecraftState<T> s, final T[] parameters) {
193
194
195 final FieldVector3D<T> satPos = s.getPosition();
196 final FieldVector3D<T> sunPos = sun.getPosition(s.getDate(), s.getFrame());
197
198
199 final FieldVector3D<T> Z = s.getPVCoordinates().getMomentum();
200 final FieldVector3D<T> Y = Z.crossProduct(sunPos).normalize();
201 final FieldVector3D<T> X = Y.crossProduct(Z).normalize();
202
203
204 final FieldVector3D<T> eD = sunPos.subtract(satPos).normalize();
205 final FieldVector3D<T> eY = eD.crossProduct(satPos).normalize();
206 final FieldVector3D<T> eB = eD.crossProduct(eY);
207
208
209 final T delta_u = FastMath.atan2(satPos.dotProduct(Y), satPos.dotProduct(X));
210
211
212 T b_u = parameters[0];
213 for (int i = 1; i < nB + 1; i++) {
214 final FieldSinCos<T> sc = FastMath.sinCos(delta_u.multiply(2 * i - 1));
215 b_u = b_u.add(sc.cos().multiply(parameters[i])).add(sc.sin().multiply(parameters[i + nB]));
216 }
217
218 T d_u = parameters[2 * nB + 1];
219
220 for (int i = 1; i < nD + 1; i++) {
221 final FieldSinCos<T> sc = FastMath.sinCos(delta_u.multiply(2 * i));
222 d_u = d_u.add(sc.cos().multiply(parameters[2 * nB + 1 + i])).add(sc.sin().multiply(parameters[2 * nB + 1 + i + nD]));
223 }
224
225 return new FieldVector3D<>(d_u, eD, parameters[2 * (nD + nB) + 2], eY, b_u, eB);
226 }
227
228
229 @Override
230 public List<ParameterDriver> getParametersDrivers() {
231 return Collections.unmodifiableList(coefficients);
232 }
233
234 }
235