1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.frames;
18
19 import org.hipparchus.Field;
20 import org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.analysis.CalculusFieldUnivariateFunction;
22 import org.hipparchus.analysis.UnivariateFunction;
23 import org.hipparchus.analysis.solvers.AllowedSolution;
24 import org.hipparchus.analysis.solvers.BracketingNthOrderBrentSolver;
25 import org.hipparchus.analysis.solvers.FieldBracketingNthOrderBrentSolver;
26 import org.hipparchus.analysis.solvers.UnivariateSolverUtils;
27 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
28 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
29 import org.hipparchus.geometry.euclidean.threed.Rotation;
30 import org.hipparchus.geometry.euclidean.threed.Vector3D;
31 import org.hipparchus.util.FastMath;
32 import org.orekit.bodies.CelestialBody;
33 import org.orekit.time.AbsoluteDate;
34 import org.orekit.time.FieldAbsoluteDate;
35 import org.orekit.utils.FieldPVCoordinates;
36 import org.orekit.utils.PVCoordinates;
37
38
39
40
41
42
43 class L2TransformProvider implements TransformProvider {
44
45
46 private static final double RELATIVE_ACCURACY = 1e-14;
47
48
49 private static final double ABSOLUTE_ACCURACY = 1e-3;
50
51
52 private static final double FUNCTION_ACCURACY = 0;
53
54
55 private static final int MAX_ORDER = 5;
56
57
58 private static final int MAX_EVALUATIONS = 1000;
59
60
61 private final Frame frame;
62
63
64 private final CelestialBody primaryBody;
65
66
67 private final CelestialBody secondaryBody;
68
69
70
71
72
73 L2TransformProvider(final CelestialBody primaryBody, final CelestialBody secondaryBody) {
74 this.primaryBody = primaryBody;
75 this.secondaryBody = secondaryBody;
76 this.frame = primaryBody.getInertiallyOrientedFrame();
77 }
78
79
80 @Override
81 public Transform getTransform(final AbsoluteDate date) {
82 final PVCoordinates pv21 = secondaryBody.getPVCoordinates(date, frame);
83 final Vector3D translation = getL2(pv21.getPosition()).negate();
84 final Rotation rotation = new Rotation(pv21.getPosition(), pv21.getVelocity(),
85 Vector3D.PLUS_I, Vector3D.PLUS_J);
86 return new Transform(date, new Transform(date, translation), new Transform(date, rotation));
87 }
88
89
90 @Override
91 public StaticTransform getStaticTransform(final AbsoluteDate date) {
92 final PVCoordinates pv21 = secondaryBody.getPVCoordinates(date, frame);
93 final Vector3D translation = getL2(pv21.getPosition()).negate();
94 final Rotation rotation = new Rotation(pv21.getPosition(), pv21.getVelocity(),
95 Vector3D.PLUS_I, Vector3D.PLUS_J);
96 return StaticTransform.compose(
97 date,
98 StaticTransform.of(date, translation),
99 StaticTransform.of(date, rotation));
100 }
101
102
103 @Override
104 public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
105 final FieldPVCoordinates<T> pv21 = secondaryBody.getPVCoordinates(date, frame);
106 final FieldVector3D<T> translation = getL2(pv21.getPosition()).negate();
107 final Field<T> field = pv21.getPosition().getX().getField();
108 final FieldRotation<T> rotation = new FieldRotation<>(pv21.getPosition(), pv21.getVelocity(),
109 FieldVector3D.getPlusI(field),
110 FieldVector3D.getPlusJ(field));
111 return new FieldTransform<>(date,
112 new FieldTransform<>(date, translation),
113 new FieldTransform<>(date, rotation));
114 }
115
116
117 @Override
118 public <T extends CalculusFieldElement<T>> FieldStaticTransform<T> getStaticTransform(final FieldAbsoluteDate<T> date) {
119 final FieldPVCoordinates<T> pv21 = secondaryBody.getPVCoordinates(date, frame);
120 final FieldVector3D<T> translation = getL2(pv21.getPosition()).negate();
121 final FieldRotation<T> rotation = new FieldRotation<>(pv21.getPosition(), pv21.getVelocity(),
122 FieldVector3D.getPlusI(date.getField()), FieldVector3D.getPlusJ(date.getField()));
123 return FieldStaticTransform.compose(
124 date,
125 FieldStaticTransform.of(date, translation),
126 FieldStaticTransform.of(date, rotation));
127 }
128
129
130
131
132
133 private Vector3D getL2(final Vector3D primaryToSecondary) {
134
135
136 final double massRatio = secondaryBody.getGM() / primaryBody.getGM();
137
138
139 final double bigR = primaryToSecondary.getNorm();
140 final double baseR = bigR * (FastMath.cbrt(massRatio / 3) + 1);
141
142
143 final UnivariateFunction l2Equation = r -> {
144 final double rminusbigR = r - bigR;
145 final double lhs1 = 1.0 / (r * r);
146 final double lhs2 = massRatio / (rminusbigR * rminusbigR);
147 final double rhs1 = 1.0 / (bigR * bigR);
148 final double rhs2 = (1 + massRatio) * rminusbigR * rhs1 / bigR;
149 return (lhs1 + lhs2) - (rhs1 + rhs2);
150 };
151 final double[] searchInterval = UnivariateSolverUtils.bracket(l2Equation,
152 baseR, 0, 2 * bigR,
153 0.01 * bigR, 1, MAX_EVALUATIONS);
154 final BracketingNthOrderBrentSolver solver =
155 new BracketingNthOrderBrentSolver(RELATIVE_ACCURACY,
156 ABSOLUTE_ACCURACY,
157 FUNCTION_ACCURACY,
158 MAX_ORDER);
159 final double r = solver.solve(MAX_EVALUATIONS, l2Equation,
160 searchInterval[0], searchInterval[1],
161 AllowedSolution.ANY_SIDE);
162
163
164 return new Vector3D(r / bigR, primaryToSecondary);
165
166 }
167
168
169
170
171
172
173 private <T extends CalculusFieldElement<T>> FieldVector3D<T>
174 getL2(final FieldVector3D<T> primaryToSecondary) {
175
176
177 final double massRatio = secondaryBody.getGM() / primaryBody.getGM();
178
179
180 final T bigR = primaryToSecondary.getNorm();
181 final T baseR = bigR.multiply(FastMath.cbrt(massRatio / 3) + 1);
182
183
184 final CalculusFieldUnivariateFunction<T> l2Equation = r -> {
185 final T rminusbigR = r.subtract(bigR);
186 final T lhs1 = r.multiply(r).reciprocal();
187 final T lhs2 = rminusbigR.multiply(rminusbigR).reciprocal().multiply(massRatio);
188 final T rhs1 = bigR.multiply(bigR).reciprocal();
189 final T rhs2 = rminusbigR.multiply(rhs1).multiply(1 + massRatio).divide(bigR);
190 return lhs1.add(lhs2).subtract(rhs1.add(rhs2));
191 };
192 final T zero = primaryToSecondary.getX().getField().getZero();
193 final T[] searchInterval = UnivariateSolverUtils.bracket(l2Equation,
194 baseR, zero, bigR.multiply(2),
195 bigR.multiply(0.01), zero,
196 MAX_EVALUATIONS);
197
198
199 final T relativeAccuracy = zero.newInstance(RELATIVE_ACCURACY);
200 final T absoluteAccuracy = zero.newInstance(ABSOLUTE_ACCURACY);
201 final T functionAccuracy = zero.newInstance(FUNCTION_ACCURACY);
202
203 final FieldBracketingNthOrderBrentSolver<T> solver =
204 new FieldBracketingNthOrderBrentSolver<>(relativeAccuracy,
205 absoluteAccuracy,
206 functionAccuracy,
207 MAX_ORDER);
208 final T r = solver.solve(MAX_EVALUATIONS, l2Equation,
209 searchInterval[0], searchInterval[1],
210 AllowedSolution.ANY_SIDE);
211
212
213 return new FieldVector3D<>(r.divide(bigR), primaryToSecondary);
214
215 }
216
217 }