1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.ndm.odm.ocm;
18
19 import java.util.List;
20 import java.util.stream.Collectors;
21 import java.util.stream.Stream;
22
23 import org.hipparchus.geometry.euclidean.threed.Vector3D;
24 import org.hipparchus.util.FastMath;
25 import org.hipparchus.util.MathUtils;
26 import org.hipparchus.util.SinCos;
27 import org.orekit.annotation.DefaultDataContext;
28 import org.orekit.bodies.GeodeticPoint;
29 import org.orekit.bodies.OneAxisEllipsoid;
30 import org.orekit.errors.OrekitException;
31 import org.orekit.errors.OrekitMessages;
32 import org.orekit.frames.Frame;
33 import org.orekit.frames.FramesFactory;
34 import org.orekit.orbits.EquinoctialOrbit;
35 import org.orekit.orbits.KeplerianOrbit;
36 import org.orekit.orbits.PositionAngleType;
37 import org.orekit.time.AbsoluteDate;
38 import org.orekit.utils.TimeStampedPVCoordinates;
39 import org.orekit.utils.units.Unit;
40
41
42
43
44
45
46 public enum OrbitElementsType {
47
48
49
50
51 ADBARV("Spherical 6-element set (α,δ,β,A,r,v)",
52 "°", "°", "°", "°", "km", "km/s"),
53
54
55 CARTP("Cartesian 3-element position (X, Y, Z)",
56 "km", "km", "km") {
57
58
59 @Override
60 public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements,
61 final OneAxisEllipsoid body, final double mu) {
62 return new TimeStampedPVCoordinates(date,
63 new Vector3D(elements[0], elements[1], elements[2]),
64 Vector3D.ZERO,
65 Vector3D.ZERO);
66 }
67
68
69 @Override
70 public double[] toRawElements(final TimeStampedPVCoordinates pv, final Frame frame,
71 final OneAxisEllipsoid body, final double mu) {
72 return new double[] {
73 pv.getPosition().getX(), pv.getPosition().getY(), pv.getPosition().getZ()
74 };
75 }
76
77 },
78
79
80 CARTPV("Cartesian 6-element position and velocity (X, Y, Z, XD, YD, ZD)",
81 "km", "km", "km", "km/s", "km/s", "km/s") {
82
83
84 @Override
85 public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements,
86 final OneAxisEllipsoid body, final double mu) {
87 return new TimeStampedPVCoordinates(date,
88 new Vector3D(elements[0], elements[1], elements[2]),
89 new Vector3D(elements[3], elements[4], elements[5]),
90 Vector3D.ZERO);
91 }
92
93
94 @Override
95 public double[] toRawElements(final TimeStampedPVCoordinates pv, final Frame frame,
96 final OneAxisEllipsoid body, final double mu) {
97 return new double[] {
98 pv.getPosition().getX(), pv.getPosition().getY(), pv.getPosition().getZ(),
99 pv.getVelocity().getX(), pv.getVelocity().getY(), pv.getVelocity().getZ()
100 };
101 }
102
103 },
104
105
106 CARTPVA("Cartesian 9-element position, velocity and acceleration (X, Y, Z, XD, YD, ZD, XDD, YDD, ZDD)",
107 "km", "km", "km", "km/s", "km/s", "km/s", "km/s²", "km/s²", "km/s²") {
108
109
110 @Override
111 public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements,
112 final OneAxisEllipsoid body, final double mu) {
113 return new TimeStampedPVCoordinates(date,
114 new Vector3D(elements[0], elements[1], elements[2]),
115 new Vector3D(elements[3], elements[4], elements[5]),
116 new Vector3D(elements[6], elements[7], elements[8]));
117 }
118
119
120 @Override
121 public double[] toRawElements(final TimeStampedPVCoordinates pv, final Frame frame,
122 final OneAxisEllipsoid body, final double mu) {
123 return new double[] {
124 pv.getPosition().getX(), pv.getPosition().getY(), pv.getPosition().getZ(),
125 pv.getVelocity().getX(), pv.getVelocity().getY(), pv.getVelocity().getZ(),
126 pv.getAcceleration().getX(), pv.getAcceleration().getY(), pv.getAcceleration().getZ()
127 };
128 }
129
130 },
131
132
133 DELAUNAY("Delaunay elements (L, G, H, l, g, h)",
134 "km²/s", "km²/s", "km²/s", "°", "°", "°"),
135
136
137 DELAUNAYMOD("Delaunay elements (Lm, Gm, Hm, lm, gm, hm)",
138 "√km", "√km", "√km", "°", "°", "°"),
139
140
141 EIGVAL3EIGVEC3("12 elements eigenvalue/eigenvectors (EigMaj, EigMed, EigMin, EigVecMaj, EigVecMed, EigVecMin)",
142 "km", "km", "km", "n/a", "n/a", "n/a", "n/a", "n/a", "n/a", "n/a", "n/a", "n/a"),
143
144
145 EQUINOCTIAL("Equinoctial elements (a, af, ag, L=M+ω+frΩ, χ, ψ, fr)",
146 "km", "n/a", "n/a", "°", "n/a", "n/a", "n/a") {
147
148
149 @Override
150 @DefaultDataContext
151 public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements,
152 final OneAxisEllipsoid body, final double mu) {
153 if (elements[6] < 0) {
154
155 throw new OrekitException(OrekitMessages.CCSDS_UNSUPPORTED_RETROGRADE_EQUINOCTIAL,
156 EQUINOCTIAL.name());
157 }
158 return new EquinoctialOrbit(elements[0], elements[1], elements[2],
159 elements[5], elements[4],
160 elements[3], PositionAngleType.MEAN,
161 FramesFactory.getGCRF(), date, mu).
162 getPVCoordinates();
163 }
164
165
166 @Override
167 public double[] toRawElements(final TimeStampedPVCoordinates pv, final Frame frame,
168 final OneAxisEllipsoid body, final double mu) {
169 final EquinoctialOrbit orbit = new EquinoctialOrbit(pv, frame, mu);
170 return new double[] {
171 orbit.getA(), orbit.getEquinoctialEx(), orbit.getEquinoctialEy(),
172 orbit.getLM(), orbit.getHy(), orbit.getHx(), +1
173 };
174 }
175
176 },
177
178
179 EQUINOCTIALMOD("Modified equinoctial elements (p=a(1−e²), af, ag, L'=υ+ω+frΩ, χ, ψ, fr)",
180 "km", "n/a", "n/a", "°", "n/a", "n/a", "n/a") {
181
182
183 @Override
184 @DefaultDataContext
185 public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements,
186 final OneAxisEllipsoid body, final double mu) {
187 if (elements[6] < 0) {
188
189 throw new OrekitException(OrekitMessages.CCSDS_UNSUPPORTED_RETROGRADE_EQUINOCTIAL,
190 EQUINOCTIALMOD.name());
191 }
192 final double oMe2 = 1.0 - (elements[1] * elements[1] + elements[2] * elements[2]);
193 return new EquinoctialOrbit(elements[0] / oMe2, elements[1], elements[2],
194 elements[5], elements[4],
195 elements[3], PositionAngleType.TRUE,
196 FramesFactory.getGCRF(), date, mu).
197 getPVCoordinates();
198 }
199
200
201 @Override
202 public double[] toRawElements(final TimeStampedPVCoordinates pv, final Frame frame,
203 final OneAxisEllipsoid body, final double mu) {
204 final EquinoctialOrbit orbit = new EquinoctialOrbit(pv, frame, mu);
205 final double ex = orbit.getEquinoctialEx();
206 final double ey = orbit.getEquinoctialEy();
207 return new double[] {
208 orbit.getA() * (1 - (ex * ex + ey * ey)), ex, ey,
209 orbit.getLv(), orbit.getHy(), orbit.getHx(), +1
210 };
211 }
212
213 },
214
215
216 GEODETIC("Geodetic elements (λ, ΦGD, β, A, h, vre)",
217 "°", "°", "°", "°", "km", "km/s") {
218
219
220 @Override
221 @DefaultDataContext
222 public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements,
223 final OneAxisEllipsoid body, final double mu) {
224 final GeodeticPoint gp = new GeodeticPoint(elements[1], elements[0], elements[4]);
225 final Vector3D position = body.transform(gp);
226 final SinCos scBeta = FastMath.sinCos(elements[2]);
227 final SinCos scAzi = FastMath.sinCos(elements[3]);
228 final Vector3D velocity = new Vector3D(elements[5] * scBeta.cos() * scAzi.sin(), gp.getEast(),
229 elements[5] * scBeta.cos() * scAzi.cos(), gp.getNorth(),
230 elements[5] * scBeta.sin(), gp.getZenith());
231 return new TimeStampedPVCoordinates(date, position, velocity);
232 }
233
234
235 @Override
236 public double[] toRawElements(final TimeStampedPVCoordinates pv, final Frame frame,
237 final OneAxisEllipsoid body, final double mu) {
238 final GeodeticPoint gp = body.transform(pv.getPosition(), frame, pv.getDate());
239 return new double[] {
240 gp.getLongitude(), gp.getLatitude(),
241 MathUtils.SEMI_PI - Vector3D.angle(pv.getVelocity(), gp.getZenith()),
242 FastMath.atan2(Vector3D.dotProduct(pv.getVelocity(), gp.getEast()),
243 Vector3D.dotProduct(pv.getVelocity(), gp.getNorth())),
244 gp.getAltitude(),
245 pv.getVelocity().getNorm()
246 };
247 }
248
249 },
250
251
252 KEPLERIAN("Keplerian 6-elemnt classical set (a, e, i, Ω, ω, ν)",
253 "km", "n/a", "°", "°", "°", "°") {
254
255
256 @Override
257 @DefaultDataContext
258 public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements,
259 final OneAxisEllipsoid body, final double mu) {
260 return new KeplerianOrbit(elements[0], elements[1], elements[2],
261 elements[4], elements[3],
262 elements[5], PositionAngleType.TRUE,
263 Frame.getRoot(), date, mu).
264 getPVCoordinates();
265 }
266
267
268 @Override
269 public double[] toRawElements(final TimeStampedPVCoordinates pv, final Frame frame,
270 final OneAxisEllipsoid body, final double mu) {
271 final KeplerianOrbit orbit = new KeplerianOrbit(pv, frame, mu);
272 return new double[] {
273 orbit.getA(), orbit.getE(), orbit.getI(),
274 orbit.getRightAscensionOfAscendingNode(),
275 orbit.getPeriapsisArgument(), orbit.getTrueAnomaly()
276 };
277 }
278
279 },
280
281
282 KEPLERIANMEAN("Keplerian 6-elemnt classical set (a, e, i, Ω, ω, M)",
283 "km", "n/a", "°", "°", "°", "°") {
284
285
286 @Override
287 @DefaultDataContext
288 public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements,
289 final OneAxisEllipsoid body, final double mu) {
290 return new KeplerianOrbit(elements[0], elements[1], elements[2],
291 elements[4], elements[3],
292 elements[5], PositionAngleType.MEAN,
293 FramesFactory.getGCRF(), date, mu).
294 getPVCoordinates();
295 }
296
297
298 @Override
299 public double[] toRawElements(final TimeStampedPVCoordinates pv, final Frame frame,
300 final OneAxisEllipsoid body, final double mu) {
301 final KeplerianOrbit orbit = new KeplerianOrbit(pv, frame, mu);
302 return new double[] {
303 orbit.getA(), orbit.getE(), orbit.getI(),
304 orbit.getRightAscensionOfAscendingNode(),
305 orbit.getPeriapsisArgument(), orbit.getMeanAnomaly()
306 };
307 }
308
309 },
310
311
312 LDBARV("Modified spherical 6-element set (λ, δ, β, A, r, v)",
313 "°", "°", "°", "°", "km", "km/s"),
314
315
316 ONSTATION("Geosynchronous on-station tailored set (a, ex, ey, ix, iy, λ)",
317 "km", "n/a", "n/a", "n/a", "n/a", "°"),
318
319
320 POINCARE("Canonical counterpart of equinoctial 6-element set (λM=M+ω+Ω, gp, hp, Lp, Gp, Hp)",
321 "°", "km/√s", "km/√s", "km²/s", "km/√s", "km/√s");
322
323
324
325
326 private final String description;
327
328
329 private final List<Unit> units;
330
331
332
333
334
335 OrbitElementsType(final String description, final String... unitsSpecifications) {
336 this.description = description;
337 this.units = Stream.of(unitsSpecifications).
338 map(Unit::parse).
339 collect(Collectors.toList());
340 }
341
342
343
344
345 public List<Unit> getUnits() {
346 return units;
347 }
348
349
350
351
352
353
354
355
356
357 public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements,
358 final OneAxisEllipsoid body, final double mu) {
359 throw new OrekitException(OrekitMessages.CCSDS_UNSUPPORTED_ELEMENT_SET_TYPE, name(), toString());
360 }
361
362
363
364
365
366
367
368
369
370
371 public double[] toRawElements(final TimeStampedPVCoordinates pv, final Frame frame,
372 final OneAxisEllipsoid body, final double mu) {
373 throw new OrekitException(OrekitMessages.CCSDS_UNSUPPORTED_ELEMENT_SET_TYPE, name(), toString());
374 }
375
376
377 @Override
378 public String toString() {
379 return description;
380 }
381
382 }