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.ExtendedPVCoordinatesProvider;
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 ExtendedPVCoordinatesProvider 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 ExtendedPVCoordinatesProvider sun, final double equatorialRadius) {
123 super(sun, new OneAxisEllipsoid(equatorialRadius, 0.0, FramesFactory.getGCRF()));
124 this.nB = nB;
125 this.nD = nD;
126 this.coefficients = new ArrayList<>(2 * (nD + nB) + 3);
127
128
129 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " B0", value, SCALE, MIN_VALUE, MAX_VALUE));
130 for (int i = 1; i < nB + 1; i++) {
131 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " Bcos" + Integer.toString(i - 1), value, SCALE, MIN_VALUE, MAX_VALUE));
132 }
133 for (int i = nB + 1; i < 2 * nB + 1; i++) {
134 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " Bsin" + Integer.toString(i - (nB + 1)), value, SCALE, MIN_VALUE, MAX_VALUE));
135 }
136
137 coefficients.add(2 * nB + 1, new ParameterDriver(ECOM_COEFFICIENT + " D0", value, SCALE, MIN_VALUE, MAX_VALUE));
138 for (int i = 2 * nB + 2; i < 2 * nB + 2 + nD; i++) {
139 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " Dcos" + Integer.toString(i - (2 * nB + 2)), value, SCALE, MIN_VALUE, MAX_VALUE));
140 }
141 for (int i = 2 * nB + 2 + nD; i < 2 * (nB + nD) + 2; i++) {
142 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " Dsin" + Integer.toString(i - (2 * nB + nD + 2)), value, SCALE, MIN_VALUE, MAX_VALUE));
143 }
144
145 coefficients.add(new ParameterDriver(ECOM_COEFFICIENT + " Y0", value, SCALE, MIN_VALUE, MAX_VALUE));
146
147
148 coefficients.forEach(parameter -> parameter.setSelected(true));
149 this.sun = sun;
150 }
151
152
153 @Override
154 public Vector3D acceleration(final SpacecraftState s, final double[] parameters) {
155
156
157 final Vector3D satPos = s.getPosition();
158 final Vector3D sunPos = sun.getPosition(s.getDate(), s.getFrame());
159
160
161 final Vector3D Z = s.getPVCoordinates().getMomentum();
162 final Vector3D Y = Z.crossProduct(sunPos).normalize();
163 final Vector3D X = Y.crossProduct(Z).normalize();
164
165
166 final Vector3D eD = sunPos.subtract(satPos).normalize();
167 final Vector3D eY = eD.crossProduct(satPos).normalize();
168 final Vector3D eB = eD.crossProduct(eY);
169
170
171 final double delta_u = FastMath.atan2(satPos.dotProduct(Y), satPos.dotProduct(X));
172
173
174 double b_u = parameters[0];
175 for (int i = 1; i < nB + 1; i++) {
176 final SinCos sc = FastMath.sinCos((2 * i - 1) * delta_u);
177 b_u += parameters[i] * sc.cos() + parameters[i + nB] * sc.sin();
178 }
179
180 double d_u = parameters[2 * nB + 1];
181 for (int i = 1; i < nD + 1; i++) {
182 final SinCos sc = FastMath.sinCos(2 * i * delta_u);
183 d_u += parameters[2 * nB + 1 + i] * sc.cos() + parameters[2 * nB + 1 + i + nD] * sc.sin();
184 }
185
186 return new Vector3D(d_u, eD, parameters[2 * (nD + nB) + 2], eY, b_u, eB);
187 }
188
189
190 @Override
191 public <T extends CalculusFieldElement<T>> FieldVector3D<T> acceleration(final FieldSpacecraftState<T> s, final T[] parameters) {
192
193
194 final FieldVector3D<T> satPos = s.getPosition();
195 final FieldVector3D<T> sunPos = sun.getPosition(s.getDate(), s.getFrame());
196
197
198 final FieldVector3D<T> Z = s.getPVCoordinates().getMomentum();
199 final FieldVector3D<T> Y = Z.crossProduct(sunPos).normalize();
200 final FieldVector3D<T> X = Y.crossProduct(Z).normalize();
201
202
203 final FieldVector3D<T> eD = sunPos.subtract(satPos).normalize();
204 final FieldVector3D<T> eY = eD.crossProduct(satPos).normalize();
205 final FieldVector3D<T> eB = eD.crossProduct(eY);
206
207
208 final T delta_u = FastMath.atan2(satPos.dotProduct(Y), satPos.dotProduct(X));
209
210
211 T b_u = parameters[0];
212 for (int i = 1; i < nB + 1; i++) {
213 final FieldSinCos<T> sc = FastMath.sinCos(delta_u.multiply(2 * i - 1));
214 b_u = b_u.add(sc.cos().multiply(parameters[i])).add(sc.sin().multiply(parameters[i + nB]));
215 }
216
217 T d_u = parameters[2 * nB + 1];
218
219 for (int i = 1; i < nD + 1; i++) {
220 final FieldSinCos<T> sc = FastMath.sinCos(delta_u.multiply(2 * i));
221 d_u = d_u.add(sc.cos().multiply(parameters[2 * nB + 1 + i])).add(sc.sin().multiply(parameters[2 * nB + 1 + i + nD]));
222 }
223
224 return new FieldVector3D<>(d_u, eD, parameters[2 * (nD + nB) + 2], eY, b_u, eB);
225 }
226
227
228 @Override
229 public List<ParameterDriver> getParametersDrivers() {
230 return Collections.unmodifiableList(coefficients);
231 }
232
233 }
234