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.forces.AbstractForceModel;
29 import org.orekit.frames.FieldTransform;
30 import org.orekit.frames.Frame;
31 import org.orekit.frames.Transform;
32 import org.orekit.propagation.FieldSpacecraftState;
33 import org.orekit.propagation.SpacecraftState;
34 import org.orekit.propagation.events.EventDetector;
35 import org.orekit.propagation.events.FieldEventDetector;
36 import org.orekit.utils.Constants;
37 import org.orekit.utils.FieldPVCoordinates;
38 import org.orekit.utils.PVCoordinates;
39 import org.orekit.utils.ParameterDriver;
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class LenseThirringRelativity extends AbstractForceModel {
54
55
56 private static final double J = 9.8e8;
57
58
59
60
61
62
63
64 private static final double MU_SCALE = FastMath.scalb(1.0, 32);
65
66
67 private final ParameterDriver gmParameterDriver;
68
69
70 private final Frame bodyFrame;
71
72
73
74
75
76
77 public LenseThirringRelativity(final double gm, final Frame bodyFrame) {
78 gmParameterDriver = new ParameterDriver(NewtonianAttraction.CENTRAL_ATTRACTION_COEFFICIENT,
79 gm, MU_SCALE,
80 0.0, Double.POSITIVE_INFINITY);
81 this.bodyFrame = bodyFrame;
82 }
83
84
85 @Override
86 public boolean dependsOnPositionOnly() {
87 return false;
88 }
89
90
91 @Override
92 public Vector3D acceleration(final SpacecraftState s, final double[] parameters) {
93
94
95 final double c2 = Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT;
96
97
98 final double gm = parameters[0];
99
100
101 final PVCoordinates pv = s.getPVCoordinates();
102 final Vector3D p = pv.getPosition();
103 final Vector3D v = pv.getVelocity();
104
105
106 final double r = p.getNorm();
107 final double r2 = r * r;
108
109
110 final Transform t = bodyFrame.getTransformTo(s.getFrame(), s.getDate());
111 final Vector3D j = t.transformVector(Vector3D.PLUS_K).scalarMultiply(J);
112
113
114 return new Vector3D(3.0 * p.dotProduct(j) / r2,
115 p.crossProduct(v),
116 1.0,
117 v.crossProduct(j))
118 .scalarMultiply((2.0 * gm) / (r2 * r * c2));
119 }
120
121
122 @Override
123 public <T extends CalculusFieldElement<T>> FieldVector3D<T> acceleration(final FieldSpacecraftState<T> s,
124 final T[] parameters) {
125
126
127 final double c2 = Constants.SPEED_OF_LIGHT * Constants.SPEED_OF_LIGHT;
128
129
130 final T gm = parameters[0];
131
132
133 final FieldPVCoordinates<T> pv = s.getPVCoordinates();
134 final FieldVector3D<T> p = pv.getPosition();
135 final FieldVector3D<T> v = pv.getVelocity();
136
137
138 final T r = p.getNorm();
139 final T r2 = r.multiply(r);
140
141
142 final FieldTransform<T> t = bodyFrame.getTransformTo(s.getFrame(), s.getDate());
143 final FieldVector3D<T> j = t.transformVector(Vector3D.PLUS_K).scalarMultiply(J);
144
145 return new FieldVector3D<>(p.dotProduct(j).multiply(3.0).divide(r2),
146 p.crossProduct(v),
147 r.getField().getOne(),
148 v.crossProduct(j))
149 .scalarMultiply(gm.multiply(2.0).divide(r2.multiply(r).multiply(c2)));
150 }
151
152
153 @Override
154 public Stream<EventDetector> getEventsDetectors() {
155 return Stream.empty();
156 }
157
158
159 @Override
160 public <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventsDetectors(final Field<T> field) {
161 return Stream.empty();
162 }
163
164
165 @Override
166 public List<ParameterDriver> getParametersDrivers() {
167 return Collections.singletonList(gmParameterDriver);
168 }
169
170 }