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 java.util.Collections;
20 import java.util.List;
21 import java.util.stream.Stream;
22
23 import org.hipparchus.Field;
24 import org.hipparchus.CalculusFieldElement;
25 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26 import org.hipparchus.geometry.euclidean.threed.Vector3D;
27 import org.hipparchus.util.FastMath;
28 import org.orekit.bodies.CelestialBodies;
29 import org.orekit.bodies.CelestialBody;
30 import org.orekit.forces.AbstractForceModel;
31 import org.orekit.propagation.FieldSpacecraftState;
32 import org.orekit.propagation.SpacecraftState;
33 import org.orekit.propagation.events.EventDetector;
34 import org.orekit.propagation.events.FieldEventDetector;
35 import org.orekit.utils.ParameterDriver;
36
37
38
39
40
41
42 public class ThirdBodyAttraction extends AbstractForceModel {
43
44
45 public static final String ATTRACTION_COEFFICIENT_SUFFIX = " attraction coefficient";
46
47
48
49
50
51
52
53 private static final double MU_SCALE = FastMath.scalb(1.0, 32);
54
55
56 private final ParameterDriver gmParameterDriver;
57
58
59 private final CelestialBody body;
60
61
62
63
64
65
66 public ThirdBodyAttraction(final CelestialBody body) {
67 gmParameterDriver = new ParameterDriver(body.getName() + ATTRACTION_COEFFICIENT_SUFFIX,
68 body.getGM(), MU_SCALE,
69 0.0, Double.POSITIVE_INFINITY);
70
71 this.body = body;
72 }
73
74
75 @Override
76 public boolean dependsOnPositionOnly() {
77 return true;
78 }
79
80
81 @Override
82 public Vector3D acceleration(final SpacecraftState s, final double[] parameters) {
83
84 final double gm = parameters[0];
85
86
87 final Vector3D centralToBody = body.getPVCoordinates(s.getDate(), s.getFrame()).getPosition();
88 final double r2Central = centralToBody.getNormSq();
89 final Vector3D satToBody = centralToBody.subtract(s.getPVCoordinates().getPosition());
90 final double r2Sat = satToBody.getNormSq();
91
92
93 return new Vector3D(gm / (r2Sat * FastMath.sqrt(r2Sat)), satToBody,
94 -gm / (r2Central * FastMath.sqrt(r2Central)), centralToBody);
95
96 }
97
98
99 @Override
100 public <T extends CalculusFieldElement<T>> FieldVector3D<T> acceleration(final FieldSpacecraftState<T> s,
101 final T[] parameters) {
102
103 final T gm = parameters[0];
104
105
106 final FieldVector3D<T> centralToBody = new FieldVector3D<>(s.getA().getField(),
107 body.getPVCoordinates(s.getDate().toAbsoluteDate(), s.getFrame()).getPosition());
108 final T r2Central = centralToBody.getNormSq();
109 final FieldVector3D<T> satToBody = centralToBody.subtract(s.getPVCoordinates().getPosition());
110 final T r2Sat = satToBody.getNormSq();
111
112
113 return new FieldVector3D<>(r2Sat.multiply(r2Sat.sqrt()).reciprocal().multiply(gm), satToBody,
114 r2Central.multiply(r2Central.sqrt()).reciprocal().multiply(gm).negate(), centralToBody);
115
116 }
117
118
119 public Stream<EventDetector> getEventsDetectors() {
120 return Stream.empty();
121 }
122
123
124 @Override
125 public <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventsDetectors(final Field<T> field) {
126 return Stream.empty();
127 }
128
129
130 @Override
131 public List<ParameterDriver> getParametersDrivers() {
132 return Collections.singletonList(gmParameterDriver);
133 }
134
135 }