1 /* Copyright 2002-2026 CS GROUP
2 * Licensed to CS GROUP (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.orekit.files.ccsds.ndm.odm;
19
20 import java.util.Optional;
21
22 import org.orekit.annotation.Nullable;
23 import org.orekit.files.ccsds.section.CommentsContainer;
24 import org.orekit.files.ccsds.section.Data;
25 import org.orekit.frames.Frame;
26 import org.orekit.orbits.KeplerianOrbit;
27 import org.orekit.orbits.PositionAngleType;
28 import org.orekit.time.AbsoluteDate;
29
30 /** Container for Keplerian elements.
31 * <p>
32 * Beware that the Orekit getters and setters all rely on SI units. The parsers
33 * and writers take care of converting these SI units into CCSDS mandatory units.
34 * The {@link org.orekit.utils.units.Unit Unit} class provides useful
35 * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
36 * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
37 * already use CCSDS units instead of the API SI units. The general-purpose
38 * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
39 * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
40 * (with an 's') also provide some predefined units. These predefined units and the
41 * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
42 * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
43 * what the parsers and writers use for the conversions.
44 * </p>
45 * @author sports
46 * @since 6.1
47 */
48 public class KeplerianElements extends CommentsContainer implements Data {
49
50 /** Epoch of state vector and optional Keplerian elements. */
51 private AbsoluteDate epoch;
52
53 /** Orbit semi-major axis (m).
54 * <p>
55 * Used in OPM instead of mean motion.
56 * </p>
57 */
58 @Nullable
59 private Double a;
60
61 /** Mean motion (the Keplerian Mean motion in rad/s).
62 * <p>
63 * Used in OMM instead of semi-major axis if MEAN_ELEMENT_THEORY = SGP/SGP4.
64 * </p>
65 */
66 @Nullable
67 private Double meanMotion;
68
69 /** Orbit eccentricity. */
70 private double e;
71
72 /** Orbit inclination (rad). */
73 private double i;
74
75 /** Orbit right ascension of ascending node (rad). */
76 private double raan;
77
78 /** Orbit argument of pericenter (rad). */
79 private double pa;
80
81 /** Orbit anomaly (rad). */
82 private double anomaly;
83
84 /** Orbit anomaly type (mean or true). */
85 private PositionAngleType anomalyType;
86
87 /** Gravitational coefficient. */
88 @Nullable
89 private Double mu;
90
91 /** Simple constructor.
92 */
93 public KeplerianElements() {
94 e = Double.NaN;
95 i = Double.NaN;
96 raan = Double.NaN;
97 pa = Double.NaN;
98 anomaly = Double.NaN;
99 }
100
101 /** {@inheritDoc}
102 * <p>
103 * We check neither semi-major axis nor mean motion here,
104 * they must be checked separately in OPM and OMM parsers
105 * </p>
106 */
107 @Override
108 public void validate(final double version) {
109 super.validate(version);
110 checkNotNull(epoch, StateVectorKey.EPOCH.name());
111 checkNotNaN(e, KeplerianElementsKey.ECCENTRICITY.name());
112 checkNotNaN(i, KeplerianElementsKey.INCLINATION.name());
113 checkNotNaN(raan, KeplerianElementsKey.RA_OF_ASC_NODE.name());
114 checkNotNaN(pa, KeplerianElementsKey.ARG_OF_PERICENTER.name());
115 checkNotNaN(anomaly, KeplerianElementsKey.MEAN_ANOMALY.name());
116 }
117
118 /** Get epoch of state vector, Keplerian elements and covariance matrix data.
119 * @return epoch the epoch
120 */
121 public AbsoluteDate getEpoch() {
122 return epoch;
123 }
124
125 /** Set epoch of state vector, Keplerian elements and covariance matrix data.
126 * @param epoch the epoch to be set
127 */
128 public void setEpoch(final AbsoluteDate epoch) {
129 refuseFurtherComments();
130 this.epoch = epoch;
131 }
132
133 /** Get the orbit semi-major axis.
134 * @return the orbit semi-major axis
135 */
136 public Optional<Double> getA() {
137 return Optional.ofNullable(a);
138 }
139
140 /** Set the orbit semi-major axis.
141 * @param a the semi-major axis to be set
142 */
143 public void setA(final double a) {
144 refuseFurtherComments();
145 this.a = a;
146 }
147
148 /** Get the orbit mean motion.
149 * @return the orbit mean motion
150 */
151 public Optional<Double> getMeanMotion() {
152 return Optional.ofNullable(meanMotion);
153 }
154
155 /** Set the orbit mean motion.
156 * @param motion the mean motion to be set
157 */
158 public void setMeanMotion(final double motion) {
159 this.meanMotion = motion;
160 }
161
162 /** Get the orbit eccentricity.
163 * @return the orbit eccentricity
164 */
165 public double getE() {
166 return e;
167 }
168
169 /** Set the orbit eccentricity.
170 * @param e the eccentricity to be set
171 */
172 public void setE(final double e) {
173 refuseFurtherComments();
174 this.e = e;
175 }
176
177 /** Get the orbit inclination.
178 * @return the orbit inclination
179 */
180 public double getI() {
181 return i;
182 }
183
184 /**Set the orbit inclination.
185 * @param i the inclination to be set
186 */
187 public void setI(final double i) {
188 refuseFurtherComments();
189 this.i = i;
190 }
191
192 /** Get the orbit right ascension of ascending node.
193 * @return the orbit right ascension of ascending node
194 */
195 public double getRaan() {
196 return raan;
197 }
198
199 /** Set the orbit right ascension of ascending node.
200 * @param raan the right ascension of ascending node to be set
201 */
202 public void setRaan(final double raan) {
203 refuseFurtherComments();
204 this.raan = raan;
205 }
206
207 /** Get the orbit argument of pericenter.
208 * @return the orbit argument of pericenter
209 */
210 public double getPa() {
211 return pa;
212 }
213
214 /** Set the orbit argument of pericenter.
215 * @param pa the argument of pericenter to be set
216 */
217 public void setPa(final double pa) {
218 refuseFurtherComments();
219 this.pa = pa;
220 }
221
222 /** Get the orbit anomaly.
223 * @return the orbit anomaly
224 */
225 public double getAnomaly() {
226 return anomaly;
227 }
228
229 /** Set the orbit anomaly.
230 * @param anomaly the anomaly to be set
231 */
232 public void setAnomaly(final double anomaly) {
233 refuseFurtherComments();
234 this.anomaly = anomaly;
235 }
236
237 /** Get the type of anomaly (true or mean).
238 * @return the type of anomaly
239 */
240 public PositionAngleType getAnomalyType() {
241 return anomalyType;
242 }
243
244 /** Set the type of anomaly.
245 * @param anomalyType the type of anomaly to be set
246 */
247 public void setAnomalyType(final PositionAngleType anomalyType) {
248 refuseFurtherComments();
249 this.anomalyType = anomalyType;
250 }
251
252 /**
253 * Set the gravitational coefficient.
254 * @param mu the coefficient to be set
255 */
256 public void setMu(final double mu) {
257 refuseFurtherComments();
258 this.mu = mu;
259 }
260
261 /**
262 * Get the gravitational coefficient.
263 * @return gravitational coefficient
264 */
265 public Optional<Double> getMu() {
266 return Optional.ofNullable(mu);
267 }
268
269 /** Generate a keplerian orbit.
270 * @param frame inertial frame for orbit
271 * @param defaultMu default gravitational coefficient to use if not specified in the file
272 * @return generated orbit
273 */
274 public KeplerianOrbit generateKeplerianOrbit(final Frame frame, final double defaultMu) {
275 return new KeplerianOrbit(a, e, i, pa, raan, anomaly, anomalyType, frame, epoch, getMu().orElse(defaultMu));
276 }
277
278 }