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.linear.RealMatrix;
25 import org.hipparchus.linear.RealVector;
26 import org.hipparchus.util.FastMath;
27 import org.orekit.estimation.measurements.AngularAzEl;
28 import org.orekit.estimation.measurements.AngularRaDec;
29 import org.orekit.frames.Frame;
30 import org.orekit.orbits.CartesianOrbit;
31 import org.orekit.orbits.Orbit;
32 import org.orekit.time.AbsoluteDate;
33 import org.orekit.utils.PVCoordinates;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class IodGauss {
52
53
54 private final double mu;
55
56
57
58
59
60
61 public IodGauss(final double mu) {
62 this.mu = mu;
63 }
64
65
66
67
68
69
70
71
72
73
74
75 public Orbit estimate(final Frame outputFrame, final AngularAzEl azEl1,
76 final AngularAzEl azEl2, final AngularAzEl azEl3) {
77 return estimate(outputFrame,
78 azEl1.getGroundStationPosition(outputFrame), azEl1.getDate(), azEl1.getObservedLineOfSight(outputFrame),
79 azEl2.getGroundStationPosition(outputFrame), azEl2.getDate(), azEl2.getObservedLineOfSight(outputFrame),
80 azEl3.getGroundStationPosition(outputFrame), azEl3.getDate(), azEl3.getObservedLineOfSight(outputFrame));
81 }
82
83
84
85
86
87
88
89
90
91
92
93 public Orbit estimate(final Frame outputFrame, final AngularRaDec raDec1,
94 final AngularRaDec raDec2, final AngularRaDec raDec3) {
95 return estimate(outputFrame,
96 raDec1.getGroundStationPosition(outputFrame), raDec1.getDate(), raDec1.getObservedLineOfSight(outputFrame),
97 raDec2.getGroundStationPosition(outputFrame), raDec2.getDate(), raDec2.getObservedLineOfSight(outputFrame),
98 raDec3.getGroundStationPosition(outputFrame), raDec3.getDate(), raDec3.getObservedLineOfSight(outputFrame));
99 }
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 public Orbit estimate(final Frame outputFrame,
118 final Vector3D obsP1, final AbsoluteDate obsDate1, final Vector3D los1,
119 final Vector3D obsP2, final AbsoluteDate obsDate2, final Vector3D los2,
120 final Vector3D obsP3, final AbsoluteDate obsDate3, final Vector3D los3) {
121
122
123 final double tau1 = obsDate1.getDate().durationFrom(obsDate2.getDate());
124 final double tau3 = obsDate3.getDate().durationFrom(obsDate2.getDate());
125
126 final double diffTau3Tau1 = tau3 - tau1;
127
128
129 final double a1 = tau3 / diffTau3Tau1;
130 final double a3 = -tau1 / diffTau3Tau1;
131 final double a1u = tau3 * ((diffTau3Tau1 * diffTau3Tau1) - tau3 * tau3) / (6. * diffTau3Tau1);
132 final double a3u = -tau1 * ((diffTau3Tau1 * diffTau3Tau1) - tau1 * tau1) / (6. * diffTau3Tau1);
133
134
135 final RealMatrix losMatrix = new Array2DRowRealMatrix(3, 3);
136 losMatrix.setColumn(0, los1.toArray());
137 losMatrix.setColumn(1, los2.toArray());
138 losMatrix.setColumn(2, los3.toArray());
139
140 final RealMatrix invertedLosMatrix = new LUDecomposition(losMatrix).getSolver().getInverse();
141
142
143 final RealMatrix rSite = new Array2DRowRealMatrix(3, 3);
144 rSite.setColumn(0, obsP1.toArray());
145 rSite.setColumn(1, obsP2.toArray());
146 rSite.setColumn(2, obsP3.toArray());
147
148
149 final RealMatrix m = invertedLosMatrix.multiply(rSite);
150
151 final double d1 = m.getEntry(1, 0) * a1 - m.getEntry(1, 1) + m.getEntry(1, 2) * a3;
152 final double d2 = m.getEntry(1, 0) * a1u + m.getEntry(1, 2) * a3u;
153 final double C = los2.dotProduct(obsP2);
154
155
156 final double r2Norm = obsP2.getNorm();
157
158
159 final double[] coeff = new double[] { -mu * mu * d2 * d2, 0., 0., -2. * mu * (C * d2 + d1 * d2), 0.,
160 0., -(d1 * d1 + 2. * C * d1 + r2Norm * r2Norm), 0., 1.0 };
161 final LaguerreSolver solver = new LaguerreSolver(1E-10,
162 1E-10, 1E-10);
163 final Complex[] roots = solver.solveAllComplex(coeff, 5. * r2Norm);
164
165
166 double r2Mag = 0.0;
167 for (final Complex root : roots) {
168 if (root.getReal() > r2Mag &&
169 FastMath.abs(root.getImaginary()) < solver.getAbsoluteAccuracy()) {
170 r2Mag = root.getReal();
171 }
172 }
173 if (r2Mag == 0.0) {
174 return null;
175 }
176
177
178 final double u = mu / (r2Mag * r2Mag * r2Mag);
179
180 final double c1 = -(-a1 - a1u * u);
181 final double c2 = -1;
182 final double c3 = -(-a3 - a3u * u);
183
184 final RealMatrix cCoeffMatrix = new Array2DRowRealMatrix(3, 1);
185 cCoeffMatrix.setEntry(0, 0, -c1);
186 cCoeffMatrix.setEntry(1, 0, -c2);
187 cCoeffMatrix.setEntry(2, 0, -c3);
188
189 final RealMatrix B = m.multiply(cCoeffMatrix.scalarMultiply(1));
190
191 final RealMatrix A = new Array2DRowRealMatrix(3, 3);
192 A.setEntry(0, 0, c1);
193 A.setEntry(1, 1, c2);
194 A.setEntry(2, 2, c3);
195
196
197 final RealMatrix slantRanges = new LUDecomposition(A).getSolver().solve(B);
198
199
200 final RealMatrix posMatrix = new Array2DRowRealMatrix(3, 3);
201 for (int i = 0; i <= 2; i++) {
202 final RealVector position = losMatrix.getColumnVector(i).
203 mapMultiply(slantRanges.getEntry(i, 0)).add(rSite.getColumnVector(i));
204 posMatrix.setRowVector(i, position);
205 }
206
207
208
209 final double pos2Norm = posMatrix.getRowVector(1).getNorm();
210 final double pos2NormCubed = pos2Norm * pos2Norm * pos2Norm;
211
212
213 final double f1 = 1. - (0.5 * mu * tau1 * tau1 / pos2NormCubed);
214 final double f3 = 1. - (0.5 * mu * tau3 * tau3 / pos2NormCubed);
215 final double g1 = tau1 - ((1. / 6.) * mu * tau1 * tau1 * tau1 / pos2NormCubed);
216 final double g3 = tau3 - ((1. / 6.) * mu * tau3 * tau3 * tau3 / pos2NormCubed);
217
218 final double v2EquationCoeff = 1. / (f1 * g3 - f3 * g1);
219
220 final RealVector v2 = (posMatrix.getRowVector(0).mapMultiply(-f3).add(
221 posMatrix.getRowVector(2).mapMultiply(f1))).mapMultiply(v2EquationCoeff);
222
223
224 final RealVector p2 = posMatrix.getRowVector(1);
225
226
227 final Vector3D p2Vector3D = new Vector3D(p2.toArray());
228 final Vector3D v2Vector3D = new Vector3D(v2.toArray());
229 return new CartesianOrbit(new PVCoordinates(p2Vector3D, v2Vector3D), outputFrame, obsDate2, mu);
230 }
231
232 }