1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package fr.cs.examples.propagation;
19
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.IOException;
23 import java.io.PrintStream;
24 import java.net.URISyntaxException;
25 import java.text.DecimalFormat;
26 import java.text.DecimalFormatSymbols;
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.Locale;
30
31 import org.apache.commons.math3.geometry.euclidean.threed.Line;
32 import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
33 import org.apache.commons.math3.util.FastMath;
34 import org.orekit.attitudes.LofOffset;
35 import org.orekit.bodies.BodyShape;
36 import org.orekit.bodies.GeodeticPoint;
37 import org.orekit.bodies.OneAxisEllipsoid;
38 import org.orekit.errors.OrekitException;
39 import org.orekit.errors.PropagationException;
40 import org.orekit.frames.FramesFactory;
41 import org.orekit.frames.LOFType;
42 import org.orekit.frames.Transform;
43 import org.orekit.orbits.CircularOrbit;
44 import org.orekit.orbits.Orbit;
45 import org.orekit.orbits.PositionAngle;
46 import org.orekit.propagation.Propagator;
47 import org.orekit.propagation.SpacecraftState;
48 import org.orekit.propagation.analytical.EcksteinHechlerPropagator;
49 import org.orekit.propagation.analytical.tle.TLE;
50 import org.orekit.propagation.analytical.tle.TLEPropagator;
51 import org.orekit.propagation.sampling.OrekitFixedStepHandler;
52 import org.orekit.time.AbsoluteDate;
53 import org.orekit.time.TimeScale;
54 import org.orekit.time.TimeScalesFactory;
55 import org.orekit.utils.Constants;
56 import org.orekit.utils.IERSConventions;
57 import org.orekit.utils.PVCoordinates;
58
59 import fr.cs.examples.Autoconfiguration;
60 import fr.cs.examples.KeyValueFileParser;
61
62
63
64
65 public class TrackCorridor {
66
67
68
69
70 public static void main(String[] args) {
71 try {
72
73
74 Autoconfiguration.configureOrekit();
75
76
77 File input = new File(TrackCorridor.class.getResource("/track-corridor.in").toURI().getPath());
78 File output = new File(input.getParentFile(), "track-corridor.csv");
79
80 new TrackCorridor().run(input, output, ",");
81
82 System.out.println("corridor saved as file " + output);
83
84 } catch (URISyntaxException use) {
85 System.err.println(use.getLocalizedMessage());
86 System.exit(1);
87 } catch (IOException ioe) {
88 System.err.println(ioe.getLocalizedMessage());
89 System.exit(1);
90 } catch (IllegalArgumentException iae) {
91 System.err.println(iae.getLocalizedMessage());
92 System.exit(1);
93 } catch (OrekitException oe) {
94 System.err.println(oe.getLocalizedMessage());
95 System.exit(1);
96 }
97 }
98
99
100 private static enum ParameterKey {
101
102 TLE_LINE1,
103 TLE_LINE2,
104 ORBIT_CIRCULAR_DATE,
105 ORBIT_CIRCULAR_A,
106 ORBIT_CIRCULAR_EX,
107 ORBIT_CIRCULAR_EY,
108 ORBIT_CIRCULAR_I,
109 ORBIT_CIRCULAR_RAAN,
110 ORBIT_CIRCULAR_ALPHA,
111 START_DATE,
112 DURATION,
113 STEP,
114 ANGULAR_OFFSET;
115
116 }
117
118 private void run(final File input, final File output, final String separator)
119 throws IOException, IllegalArgumentException, OrekitException {
120
121
122 KeyValueFileParser<ParameterKey> parser =
123 new KeyValueFileParser<ParameterKey>(ParameterKey.class);
124 parser.parseInput(new FileInputStream(input));
125 TimeScale utc = TimeScalesFactory.getUTC();
126
127 Propagator propagator;
128 if (parser.containsKey(ParameterKey.TLE_LINE1)) {
129 propagator = createPropagator(parser.getString(ParameterKey.TLE_LINE1),
130 parser.getString(ParameterKey.TLE_LINE2));
131 } else {
132 propagator = createPropagator(parser.getDate(ParameterKey.ORBIT_CIRCULAR_DATE, utc),
133 parser.getDouble(ParameterKey.ORBIT_CIRCULAR_A),
134 parser.getDouble(ParameterKey.ORBIT_CIRCULAR_EX),
135 parser.getDouble(ParameterKey.ORBIT_CIRCULAR_EY),
136 parser.getAngle(ParameterKey.ORBIT_CIRCULAR_I),
137 parser.getAngle(ParameterKey.ORBIT_CIRCULAR_RAAN),
138 parser.getAngle(ParameterKey.ORBIT_CIRCULAR_ALPHA));
139 }
140
141
142 AbsoluteDate start = parser.getDate(ParameterKey.START_DATE, utc);
143 double duration = parser.getDouble(ParameterKey.DURATION);
144 double step = parser.getDouble(ParameterKey.STEP);
145 double angle = parser.getAngle(ParameterKey.ANGULAR_OFFSET);
146
147
148 CorridorHandler handler = new CorridorHandler(angle);
149 propagator.setMasterMode(step, handler);
150
151
152 propagator.propagate(start, start.shiftedBy(duration));
153
154
155 List<CorridorPoint> corridor = handler.getCorridor();
156
157
158
159
160
161
162 DecimalFormat format = new DecimalFormat("#00.00000", new DecimalFormatSymbols(Locale.US));
163 PrintStream stream = new PrintStream(output);
164 for (CorridorPoint p : corridor) {
165 stream.println(p.getDate() + separator +
166 format.format(FastMath.toDegrees(p.getLeft().getLatitude())) + separator +
167 format.format(FastMath.toDegrees(p.getLeft().getLongitude())) + separator +
168 format.format(FastMath.toDegrees(p.getCenter().getLatitude())) + separator +
169 format.format(FastMath.toDegrees(p.getCenter().getLongitude())) + separator +
170 format.format(FastMath.toDegrees(p.getRight().getLatitude())) + separator +
171 format.format(FastMath.toDegrees(p.getRight().getLongitude())));
172 }
173 stream.close();
174
175 }
176
177
178
179
180
181
182
183
184
185
186
187
188 private Propagator createPropagator(final AbsoluteDate date,
189 final double a, final double ex, final double ey,
190 final double i, final double raan,
191 final double alpha)
192 throws OrekitException {
193
194
195 Orbit initialOrbit = new CircularOrbit(a, ex, ey, i, raan, alpha, PositionAngle.MEAN,
196 FramesFactory.getEME2000(), date,
197 Constants.EIGEN5C_EARTH_MU);
198
199
200 Propagator propagator =
201 new EcksteinHechlerPropagator(initialOrbit,
202 new LofOffset(initialOrbit.getFrame(), LOFType.TNW),
203 Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS,
204 Constants.EIGEN5C_EARTH_MU, Constants.EIGEN5C_EARTH_C20,
205 Constants.EIGEN5C_EARTH_C30, Constants.EIGEN5C_EARTH_C40,
206 Constants.EIGEN5C_EARTH_C50, Constants.EIGEN5C_EARTH_C60);
207
208 return propagator;
209
210 }
211
212
213
214
215
216
217
218 private Propagator createPropagator(final String line1, final String line2)
219 throws OrekitException {
220
221
222 TLE tle = new TLE(line1, line2);
223
224
225 Propagator propagator = TLEPropagator.selectExtrapolator(tle);
226
227 return propagator;
228
229 }
230
231
232 private static class CorridorHandler implements OrekitFixedStepHandler {
233
234
235 private final BodyShape earth;
236
237
238 private final double deltaR;
239
240
241 private final double deltaC;
242
243
244 private final List<CorridorPoint> corridor;
245
246
247
248
249
250 public CorridorHandler(final double angle) throws OrekitException {
251
252
253 earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
254 Constants.WGS84_EARTH_FLATTENING,
255 FramesFactory.getITRF(IERSConventions.IERS_2010, false));
256
257
258 deltaR = Constants.WGS84_EARTH_EQUATORIAL_RADIUS * FastMath.cos(angle);
259 deltaC = Constants.WGS84_EARTH_EQUATORIAL_RADIUS * FastMath.sin(angle);
260
261
262 corridor = new ArrayList<TrackCorridor.CorridorPoint>();
263
264 }
265
266
267 public void init(final SpacecraftState s0, final AbsoluteDate t) {
268 }
269
270
271 public void handleStep(SpacecraftState currentState, boolean isLast)
272 throws PropagationException {
273 try {
274
275
276 AbsoluteDate date = currentState.getDate();
277 PVCoordinates pvInert = currentState.getPVCoordinates();
278 Transform t = currentState.getFrame().getTransformTo(earth.getBodyFrame(), date);
279 Vector3D p = t.transformPosition(pvInert.getPosition());
280 Vector3D v = t.transformVector(pvInert.getVelocity());
281 GeodeticPoint center = earth.transform(p, earth.getBodyFrame(), date);
282
283
284 Vector3D nadir = p.normalize().negate();
285 Vector3D crossTrack = p.crossProduct(v).normalize();
286 Line leftLine = new Line(p, new Vector3D(1.0, p, deltaR, nadir, deltaC, crossTrack), 1.0e-10);
287 GeodeticPoint left = earth.getIntersectionPoint(leftLine, p, earth.getBodyFrame(), date);
288 Line rightLine = new Line(p, new Vector3D(1.0, p, deltaR, nadir, -deltaC, crossTrack), 1.0e-10);
289 GeodeticPoint right = earth.getIntersectionPoint(rightLine, p, earth.getBodyFrame(), date);
290
291
292 corridor.add(new CorridorPoint(date, left, center, right));
293
294 } catch (OrekitException oe) {
295 throw new PropagationException(oe);
296 }
297 }
298
299
300
301
302 public List<CorridorPoint> getCorridor() {
303 return corridor;
304 }
305
306 }
307
308
309 private static class CorridorPoint {
310
311
312 private final AbsoluteDate date;
313
314
315 private final GeodeticPoint left;
316
317
318 private final GeodeticPoint center;
319
320
321 private final GeodeticPoint right;
322
323
324
325
326
327
328
329 public CorridorPoint(AbsoluteDate date, GeodeticPoint left,
330 GeodeticPoint center, GeodeticPoint right) {
331 this.date = date;
332 this.left = left;
333 this.center = center;
334 this.right = right;
335 }
336
337
338 public AbsoluteDate getDate() {
339 return date;
340 }
341
342
343 public GeodeticPoint getLeft() {
344 return left;
345 }
346
347
348 public GeodeticPoint getCenter() {
349 return center;
350 }
351
352
353 public GeodeticPoint getRight() {
354 return right;
355 }
356
357 }
358
359 }