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