1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.iod;
18
19 import org.hipparchus.analysis.solvers.LaguerreSolver;
20 import org.hipparchus.complex.Complex;
21 import org.hipparchus.geometry.euclidean.threed.Vector3D;
22 import org.hipparchus.linear.Array2DRowRealMatrix;
23 import org.hipparchus.linear.LUDecomposition;
24 import org.hipparchus.util.FastMath;
25 import org.orekit.estimation.measurements.AngularAzEl;
26 import org.orekit.estimation.measurements.AngularRaDec;
27 import org.orekit.frames.Frame;
28 import org.orekit.orbits.CartesianOrbit;
29 import org.orekit.orbits.Orbit;
30 import org.orekit.time.AbsoluteDate;
31 import org.orekit.utils.PVCoordinates;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 public class IodLaplace {
49
50
51 private final double mu;
52
53
54
55
56
57 public IodLaplace(final double mu) {
58 this.mu = mu;
59 }
60
61
62
63
64
65
66
67
68
69
70
71 public Orbit estimate(final Frame outputFrame,
72 final AngularAzEl azEl1, final AngularAzEl azEl2,
73 final AngularAzEl azEl3) {
74 return estimate(outputFrame, azEl2.getGroundStationCoordinates(outputFrame),
75 azEl1.getDate(), azEl1.getObservedLineOfSight(outputFrame),
76 azEl2.getDate(), azEl2.getObservedLineOfSight(outputFrame),
77 azEl3.getDate(), azEl3.getObservedLineOfSight(outputFrame));
78 }
79
80
81
82
83
84
85
86
87
88
89
90 public Orbit estimate(final Frame outputFrame,
91 final AngularRaDec raDec1, final AngularRaDec raDec2,
92 final AngularRaDec raDec3) {
93 return estimate(outputFrame, raDec2.getGroundStationCoordinates(outputFrame),
94 raDec1.getDate(), raDec1.getObservedLineOfSight(outputFrame),
95 raDec2.getDate(), raDec2.getObservedLineOfSight(outputFrame),
96 raDec3.getDate(), raDec3.getObservedLineOfSight(outputFrame));
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 public Orbit estimate(final Frame outputFrame, final PVCoordinates obsPva,
113 final AbsoluteDate obsDate1, final Vector3D los1,
114 final AbsoluteDate obsDate2, final Vector3D los2,
115 final AbsoluteDate obsDate3, final Vector3D los3) {
116
117
118 final double t2 = obsDate2.durationFrom(obsDate1);
119 final double t3 = obsDate3.durationFrom(obsDate1);
120
121
122 final Vector3D Ldot = los1.scalarMultiply((t2 - t3) / (t2 * t3)).
123 add(los2.scalarMultiply((2.0 * t2 - t3) / (t2 * (t2 - t3)))).
124 add(los3.scalarMultiply(t2 / (t3 * (t3 - t2))));
125 final Vector3D Ldotdot = los1.scalarMultiply(2.0 / (t2 * t3)).
126 add(los2.scalarMultiply(2.0 / (t2 * (t2 - t3)))).
127 add(los3.scalarMultiply(2.0 / (t3 * (t3 - t2))));
128
129
130 final double D = 2.0 * getDeterminant(los2, Ldot, Ldotdot);
131 if (FastMath.abs(D) < 1.0E-14) {
132 return null;
133 }
134
135 final double Dsq = D * D;
136 final double R = obsPva.getPosition().getNorm();
137 final double RdotL = obsPva.getPosition().dotProduct(los2);
138
139 final double D1 = getDeterminant(los2, Ldot, obsPva.getAcceleration());
140 final double D2 = getDeterminant(los2, Ldot, obsPva.getPosition());
141
142
143 final double[] coeff = new double[] {-4.0 * mu * mu * D2 * D2 / Dsq,
144 0.0,
145 0.0,
146 4.0 * mu * D2 * (RdotL / D - 2.0 * D1 / Dsq),
147 0.0,
148 0.0,
149 4.0 * D1 * RdotL / D - 4.0 * D1 * D1 / Dsq - R * R, 0.0,
150 1.0};
151
152
153
154 final LaguerreSolver solver = new LaguerreSolver(1E-10, 1E-10, 1E-10);
155 final Complex[] roots = solver.solveAllComplex(coeff, 5.0 * R);
156
157
158 double rMag = 0.0;
159 for (Complex root : roots) {
160 if (root.getReal() > rMag &&
161 FastMath.abs(root.getImaginary()) < solver.getAbsoluteAccuracy()) {
162 rMag = root.getReal();
163 }
164 }
165 if (rMag == 0.0) {
166 return null;
167 }
168
169
170
171 final double rCubed = rMag * rMag * rMag;
172 final double rho = -2.0 * D1 / D - 2.0 * mu * D2 / (D * rCubed);
173 final Vector3D posVec = los2.scalarMultiply(rho).add(obsPva.getPosition());
174
175
176 final double D3 = getDeterminant(los2, obsPva.getAcceleration(), Ldotdot);
177 final double D4 = getDeterminant(los2, obsPva.getPosition(), Ldotdot);
178 final double rhoDot = -D3 / D - mu * D4 / (D * rCubed);
179 final Vector3D velVec = los2.scalarMultiply(rhoDot).
180 add(Ldot.scalarMultiply(rho)).
181 add(obsPva.getVelocity());
182
183
184 return new CartesianOrbit(new PVCoordinates(posVec, velVec), outputFrame, obsDate2, mu);
185 }
186
187
188
189
190
191
192
193
194
195 private double getDeterminant(final Vector3D col0, final Vector3D col1, final Vector3D col2) {
196 final Array2DRowRealMatrix mat = new Array2DRowRealMatrix(3, 3);
197 mat.setColumn(0, col0.toArray());
198 mat.setColumn(1, col1.toArray());
199 mat.setColumn(2, col2.toArray());
200 return new LUDecomposition(mat).getDeterminant();
201 }
202
203 }