1 /* Copyright 2002-2025 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.omm; 19 20 import org.orekit.files.ccsds.section.CommentsContainer; 21 22 /** Container for TLE data. 23 * <p> 24 * Beware that the Orekit getters and setters all rely on SI units. The parsers 25 * and writers take care of converting these SI units into CCSDS mandatory units. 26 * The {@link org.orekit.utils.units.Unit Unit} class provides useful 27 * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and 28 * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers 29 * already use CCSDS units instead of the API SI units. The general-purpose 30 * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the 31 * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class 32 * (with an 's') also provide some predefined units. These predefined units and the 33 * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and 34 * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed 35 * what the parsers and writers use for the conversions. 36 * </p> 37 * @author sports 38 * @since 6.1 39 */ 40 public class OmmTle extends CommentsContainer { 41 42 /** Constant for EPHEMERIS_TYPE SGP. 43 * @since 12.0 44 */ 45 public static final int EPHEMERIS_TYPE_SGP = 0; 46 47 /** Constant for EPHEMERIS_TYPE SGP4. 48 * @since 12.0 49 */ 50 public static final int EPHEMERIS_TYPE_SGP4 = 2; 51 52 /** Constant for EPHEMERIS_TYPE PPT3. 53 * @since 12.0 54 */ 55 public static final int EPHEMERIS_TYPE_PPT3 = 3; 56 57 /** Constant for EPHEMERIS_TYPE SGP4-XP. 58 * @since 12.0 59 */ 60 public static final int EPHEMERIS_TYPE_SGP4_XP = 4; 61 62 /** Constant for EPHEMERIS_TYPE Special Perturbations. 63 * @since 12.0 64 */ 65 public static final int EPHEMERIS_TYPE_SPECIAL_PERTURBATIONS = 6; 66 67 /** Ephemeris Type, only required if MEAN_ELEMENT_THEORY = SGP/SGP4. Some sources suggest the coding for 68 * the EPHEMERIS_TYPE keyword: 0 = SGP, 2 = SGP4, 3 = PPT3, 4 = SGP4-XP, 6 = Special Perturbations. Default value = 0. 69 */ 70 private int ephemerisType; 71 72 /** Classification Type, only required if MEAN_ELEMENT_THEORY = SGP/SGP4. Some sources suggest the 73 * following coding for the CLASSIFICATION_TYPE keyword: U = unclassified, S = secret. Default value = U. 74 */ 75 private char classificationType; 76 77 /** NORAD Catalog Number ("Satellite Number"), an integer of up to nine digits. */ 78 private int noradID; 79 80 /** Element set number for this satellite, only required if MEAN_ELEMENT_THEORY = SGP/SGP4. 81 * Normally incremented sequentially, but may be out of sync if it is generated from a backup source. 82 * Used to distinguish different TLEs, and therefore only meaningful if TLE based data is being exchanged. */ 83 private int elementSetNo; 84 85 /** Revolution Number, only required if MEAN_ELEMENT_THEORY = SGP/SGP4. */ 86 private int revAtEpoch; 87 88 /** SGP/SGP4 drag-like coefficient (in units 1/[Earth radii]), only required if MEAN_ELEMENT_THEORY = SGP/SGP4. */ 89 private double bStar; 90 91 /** SGP4-XP drag-like coefficient (in m²/kg), only required if MEAN_ELEMENT_THEORY = SGP4-XP. 92 * @since 12.0 93 */ 94 private double bTerm; 95 96 /** First Time Derivative of the Mean Motion, only required if MEAN_ELEMENT_THEORY = SGP. */ 97 private double meanMotionDot; 98 99 /** Second Time Derivative of Mean Motion, only required if MEAN_ELEMENT_THEORY = SGP. */ 100 private double meanMotionDotDot; 101 102 /** SGP4-XP solar radiation pressure-like coefficient Aγ/m (in m²/kg), only required if MEAN_ELEMENT_THEORY = SGP4-XP. 103 * @since 12.0 104 */ 105 private double agOm; 106 107 /** Create an empty data set. 108 */ 109 public OmmTle() { 110 ephemerisType = EPHEMERIS_TYPE_SGP; 111 classificationType = 'U'; 112 noradID = -1; 113 elementSetNo = -1; 114 revAtEpoch = -1; 115 bStar = Double.NaN; 116 bTerm = Double.NaN; 117 meanMotionDot = Double.NaN; 118 meanMotionDotDot = Double.NaN; 119 agOm = Double.NaN; 120 } 121 122 /** {@inheritDoc} */ 123 @Override 124 public void validate(final double version) { 125 super.validate(version); 126 127 checkNotNegative(noradID, OmmTleKey.NORAD_CAT_ID.name()); 128 checkNotNegative(elementSetNo, OmmTleKey.ELEMENT_SET_NO.name()); 129 checkNotNegative(revAtEpoch, OmmTleKey.REV_AT_EPOCH.name()); 130 131 if (ephemerisType == EPHEMERIS_TYPE_SGP4) { 132 checkNotNaN(bStar, OmmTleKey.BSTAR.name()); 133 } else if (ephemerisType == EPHEMERIS_TYPE_SGP4_XP) { 134 checkNotNaN(bTerm, OmmTleKey.BTERM.name()); 135 } 136 137 if (ephemerisType == EPHEMERIS_TYPE_SGP || ephemerisType == EPHEMERIS_TYPE_PPT3) { 138 checkNotNaN(meanMotionDot, OmmTleKey.MEAN_MOTION_DOT.name()); 139 } 140 141 if (ephemerisType == EPHEMERIS_TYPE_SGP || ephemerisType == EPHEMERIS_TYPE_PPT3) { 142 checkNotNaN(meanMotionDotDot, OmmTleKey.MEAN_MOTION_DDOT.name()); 143 } else if (ephemerisType == EPHEMERIS_TYPE_SGP4_XP) { 144 checkNotNaN(agOm, OmmTleKey.AGOM.name()); 145 } 146 147 } 148 149 /** Get the ephemeris type. 150 * @return the ephemerisType 151 */ 152 public int getEphemerisType() { 153 return ephemerisType; 154 } 155 156 /** Set the ephemeris type. 157 * @param ephemerisType the ephemeris type to be set 158 */ 159 public void setEphemerisType(final int ephemerisType) { 160 refuseFurtherComments(); 161 this.ephemerisType = ephemerisType; 162 } 163 164 /** Get the classification type. 165 * @return the classificationType 166 */ 167 public char getClassificationType() { 168 return classificationType; 169 } 170 171 /** Set the classification type. 172 * @param classificationType the classification type to be set 173 */ 174 public void setClassificationType(final char classificationType) { 175 refuseFurtherComments(); 176 this.classificationType = classificationType; 177 } 178 179 /** Get the NORAD Catalog Number ("Satellite Number"). 180 * @return the NORAD Catalog Number 181 */ 182 public int getNoradID() { 183 return noradID; 184 } 185 186 /** Set the NORAD Catalog Number ("Satellite Number"). 187 * @param noradID the element set number to be set 188 */ 189 public void setNoradID(final int noradID) { 190 refuseFurtherComments(); 191 this.noradID = noradID; 192 } 193 194 /** Get the element set number for this satellite. 195 * @return the element set number for this satellite 196 */ 197 public int getElementSetNumber() { 198 return elementSetNo; 199 } 200 201 /** Set the element set number for this satellite. 202 * @param elementSetNo the element set number to be set 203 */ 204 public void setElementSetNo(final int elementSetNo) { 205 refuseFurtherComments(); 206 this.elementSetNo = elementSetNo; 207 } 208 209 /** Get the revolution rumber. 210 * @return the revolution rumber 211 */ 212 public int getRevAtEpoch() { 213 return revAtEpoch; 214 } 215 216 /** Set the revolution rumber. 217 * @param revAtEpoch the Revolution Number to be set 218 */ 219 public void setRevAtEpoch(final int revAtEpoch) { 220 refuseFurtherComments(); 221 this.revAtEpoch = revAtEpoch; 222 } 223 224 /** Get the SGP/SGP4 drag-like coefficient. 225 * @return the SGP/SGP4 drag-like coefficient 226 */ 227 public double getBStar() { 228 return bStar; 229 } 230 231 /** Set the SGP/SGP4 drag-like coefficient. 232 * @param bstar the SGP/SGP4 drag-like coefficient to be set 233 */ 234 public void setBStar(final double bstar) { 235 refuseFurtherComments(); 236 this.bStar = bstar; 237 } 238 239 /** Get the SGP4-XP drag-like coefficient. 240 * @return the SGP4-XP drag-like coefficient 241 * @since 12.0 242 */ 243 public double getBTerm() { 244 return bTerm; 245 } 246 247 /** Set the SGP4-XP drag-like coefficient. 248 * @param bterm the SGP4-XP drag-like coefficient to be set 249 * @since 12.0 250 */ 251 public void setBTerm(final double bterm) { 252 refuseFurtherComments(); 253 this.bTerm = bterm; 254 } 255 256 /** Get the first time derivative of the mean motion. 257 * @return the first time derivative of the mean motion 258 */ 259 public double getMeanMotionDot() { 260 return meanMotionDot; 261 } 262 263 /** Set the first time derivative of the mean motion. 264 * @param meanMotionDot the first time derivative of the mean motion to be set 265 */ 266 public void setMeanMotionDot(final double meanMotionDot) { 267 refuseFurtherComments(); 268 this.meanMotionDot = meanMotionDot; 269 } 270 271 /** Get the second time derivative of the mean motion. 272 * @return the second time derivative of the mean motion 273 */ 274 public double getMeanMotionDotDot() { 275 return meanMotionDotDot; 276 } 277 278 /** Set the second time derivative of the mean motion. 279 * @param meanMotionDotDot the second time derivative of the mean motion to be set 280 */ 281 public void setMeanMotionDotDot(final double meanMotionDotDot) { 282 refuseFurtherComments(); 283 this.meanMotionDotDot = meanMotionDotDot; 284 } 285 286 /** Get the SGP4-XP solar radiation pressure-like coefficient Aγ/m. 287 * @return the SGP4-XP solar radiation pressure-like coefficient Aγ/m 288 * @since 12.0 289 */ 290 public double getAGoM() { 291 return agOm; 292 } 293 294 /** Set the SGP4-XP solar radiation pressure-like coefficient Aγ/m. 295 * @param agom the SGP4-XP solar radiation pressure-like coefficient Aγ/m to be set 296 * @since 12.0 297 */ 298 public void setAGoM(final double agom) { 299 refuseFurtherComments(); 300 this.agOm = agom; 301 } 302 303 }