1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.gravity;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
21 import org.hipparchus.geometry.euclidean.threed.Vector3D;
22 import org.hipparchus.util.FastMath;
23 import org.orekit.forces.ForceModel;
24 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
25 import org.orekit.frames.FieldStaticTransform;
26 import org.orekit.frames.Frame;
27 import org.orekit.frames.StaticTransform;
28 import org.orekit.propagation.FieldSpacecraftState;
29 import org.orekit.propagation.SpacecraftState;
30 import org.orekit.time.AbsoluteDate;
31 import org.orekit.time.FieldAbsoluteDate;
32 import org.orekit.time.TimeScalarFunction;
33 import org.orekit.utils.ParameterDriver;
34
35 import java.util.Collections;
36 import java.util.List;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class J2OnlyPerturbation implements ForceModel {
54
55
56 private final double mu;
57
58
59 private final double rEq;
60
61
62 private final TimeScalarFunction j2OverTime;
63
64
65 private final Frame frame;
66
67
68
69
70
71
72
73
74 public J2OnlyPerturbation(final double mu, final double rEq, final TimeScalarFunction j2OverTime,
75 final Frame frame) {
76 this.mu = mu;
77 this.rEq = rEq;
78 this.j2OverTime = j2OverTime;
79 this.frame = frame;
80 }
81
82
83
84
85
86
87
88 public J2OnlyPerturbation(final double mu, final double rEq, final double constantJ2, final Frame frame) {
89 this.mu = mu;
90 this.rEq = rEq;
91 this.frame = frame;
92 this.j2OverTime = new TimeScalarFunction() {
93 @Override
94 public double value(final AbsoluteDate date) {
95 return constantJ2;
96 }
97
98 @Override
99 public <T extends CalculusFieldElement<T>> T value(final FieldAbsoluteDate<T> date) {
100 return date.getField().getZero().newInstance(constantJ2);
101 }
102 };
103 }
104
105
106
107
108
109 public J2OnlyPerturbation(final UnnormalizedSphericalHarmonicsProvider harmonicsProvider, final Frame frame) {
110 this.mu = harmonicsProvider.getMu();
111 this.rEq = harmonicsProvider.getAe();
112 this.frame = frame;
113 this.j2OverTime = new TimeScalarFunction() {
114 @Override
115 public double value(final AbsoluteDate date) {
116 return -harmonicsProvider.getUnnormalizedC20(date);
117 }
118
119 @Override
120 public <T extends CalculusFieldElement<T>> T value(final FieldAbsoluteDate<T> date) {
121 return date.getField().getZero().newInstance(value(date.toAbsoluteDate()));
122 }
123 };
124 }
125
126
127
128
129 public double getMu() {
130 return mu;
131 }
132
133
134
135
136 public double getrEq() {
137 return rEq;
138 }
139
140
141
142
143 public Frame getFrame() {
144 return frame;
145 }
146
147
148
149
150
151 public double getJ2(final AbsoluteDate date) {
152 return j2OverTime.value(date);
153 }
154
155
156
157
158
159
160 public <T extends CalculusFieldElement<T>> T getJ2(final FieldAbsoluteDate<T> date) {
161 return j2OverTime.value(date);
162 }
163
164
165 @Override
166 public boolean dependsOnPositionOnly() {
167 return true;
168 }
169
170
171 @Override
172 public Vector3D acceleration(final SpacecraftState state, final double[] parameters) {
173 final AbsoluteDate date = state.getDate();
174 final StaticTransform fromPropagationToJ2Frame = state.getFrame().getStaticTransformTo(frame, date);
175 final Vector3D positionInJ2Frame = fromPropagationToJ2Frame.transformPosition(state.getPosition());
176 final double j2 = j2OverTime.value(date);
177 final Vector3D accelerationInJ2Frame = computeAccelerationInJ2Frame(positionInJ2Frame, mu, rEq, j2);
178 final StaticTransform fromJ2FrameToPropagationOne = fromPropagationToJ2Frame.getStaticInverse();
179 return fromJ2FrameToPropagationOne.transformVector(accelerationInJ2Frame);
180 }
181
182
183
184
185
186
187
188
189
190 public static Vector3D computeAccelerationInJ2Frame(final Vector3D positionInJ2Frame, final double mu,
191 final double rEq, final double j2) {
192 final double squaredRadius = positionInJ2Frame.getNormSq();
193 final double squaredZ = positionInJ2Frame.getZ() * positionInJ2Frame.getZ();
194 final double ratioTimesFive = 5. * squaredZ / squaredRadius;
195 final double ratioTimesFiveMinusOne = ratioTimesFive - 1.;
196 final double componentX = positionInJ2Frame.getX() * ratioTimesFiveMinusOne;
197 final double componentY = positionInJ2Frame.getY() * ratioTimesFiveMinusOne;
198 final double componentZ = positionInJ2Frame.getZ() * (ratioTimesFive - 3);
199 final double squaredRadiiRatio = rEq * rEq / squaredRadius;
200 final double cubedRadius = squaredRadius * FastMath.sqrt(squaredRadius);
201 final double factor = 3 * j2 * mu * squaredRadiiRatio / (2 * cubedRadius);
202 return new Vector3D(componentX, componentY, componentZ).scalarMultiply(factor);
203 }
204
205
206 @Override
207 public <T extends CalculusFieldElement<T>> FieldVector3D<T> acceleration(final FieldSpacecraftState<T> state,
208 final T[] parameters) {
209 final FieldAbsoluteDate<T> date = state.getDate();
210 final FieldStaticTransform<T> fromPropagationToJ2Frame = state.getFrame().getStaticTransformTo(frame, date);
211 final FieldVector3D<T> positionInJ2Frame = fromPropagationToJ2Frame.transformPosition(state.getPosition());
212 final FieldVector3D<T> accelerationInJ2Frame = computeAccelerationInJ2Frame(positionInJ2Frame, mu, rEq,
213 j2OverTime.value(date));
214 final FieldStaticTransform<T> fromJ2FrameToPropagation = fromPropagationToJ2Frame.getStaticInverse();
215 return fromJ2FrameToPropagation.transformVector(accelerationInJ2Frame);
216 }
217
218
219
220
221
222
223
224
225
226
227 public static <T extends CalculusFieldElement<T>> FieldVector3D<T> computeAccelerationInJ2Frame(final FieldVector3D<T> positionInJ2Frame,
228 final double mu, final double rEq, final T j2) {
229 final T squaredRadius = positionInJ2Frame.getNormSq();
230 final T squaredZ = positionInJ2Frame.getZ().square();
231 final T ratioTimesFive = squaredZ.multiply(5.).divide(squaredRadius);
232 final T ratioTimesFiveMinusOne = ratioTimesFive.subtract(1.);
233 final T componentX = positionInJ2Frame.getX().multiply(ratioTimesFiveMinusOne);
234 final T componentY = positionInJ2Frame.getY().multiply(ratioTimesFiveMinusOne);
235 final T componentZ = positionInJ2Frame.getZ().multiply(ratioTimesFive.subtract(3.));
236 final T squaredRadiiRatio = squaredRadius.reciprocal().multiply(rEq * rEq);
237 final T cubedRadius = squaredRadius.multiply(FastMath.sqrt(squaredRadius));
238 final T factor = j2.multiply(mu).multiply(3.).multiply(squaredRadiiRatio).divide(cubedRadius.multiply(2));
239 return new FieldVector3D<>(componentX, componentY, componentZ).scalarMultiply(factor);
240 }
241
242
243 @Override
244 public List<ParameterDriver> getParametersDrivers() {
245 return Collections.emptyList();
246 }
247 }