ootk 6.0.4 → 6.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.cjs CHANGED
@@ -23,6 +23,8 @@ var ValidationError = class extends OotkError {
23
23
  this.value = value;
24
24
  this.name = "ValidationError";
25
25
  }
26
+ field;
27
+ value;
26
28
  };
27
29
  var ParseError = class extends OotkError {
28
30
  /**
@@ -37,6 +39,8 @@ var ParseError = class extends OotkError {
37
39
  this.line = line;
38
40
  this.name = "ParseError";
39
41
  }
42
+ format;
43
+ line;
40
44
  };
41
45
  var PropagationError = class extends OotkError {
42
46
  /**
@@ -49,6 +53,7 @@ var PropagationError = class extends OotkError {
49
53
  this.epoch = epoch;
50
54
  this.name = "PropagationError";
51
55
  }
56
+ epoch;
52
57
  };
53
58
  var OrbitDeterminationError = class extends OotkError {
54
59
  /**
@@ -61,6 +66,7 @@ var OrbitDeterminationError = class extends OotkError {
61
66
  this.algorithm = algorithm;
62
67
  this.name = "OrbitDeterminationError";
63
68
  }
69
+ algorithm;
64
70
  };
65
71
 
66
72
  // src/enums/AngularDiameterMethod.ts
@@ -79,6 +85,7 @@ var AngularDistanceMethod = /* @__PURE__ */ ((AngularDistanceMethod2) => {
79
85
 
80
86
  // src/enums/CatalogSource.ts
81
87
  var CatalogSource = /* @__PURE__ */ ((CatalogSource2) => {
88
+ CatalogSource2["UNKNOWN"] = "unknown";
82
89
  CatalogSource2["USSF"] = "spacetrack";
83
90
  CatalogSource2["CELESTRAK"] = "celestrak";
84
91
  CatalogSource2["CELESTRAK_SUP"] = "celestrak-sup";
@@ -277,6 +284,7 @@ var Epoch = class {
277
284
  throw new ValidationError("Epoch posix time must be a valid number", "posix", posix);
278
285
  }
279
286
  }
287
+ posix;
280
288
  toString() {
281
289
  return this.toDateTime().toISOString();
282
290
  }
@@ -1820,6 +1828,8 @@ var EpochGPS = class _EpochGPS {
1820
1828
  throw new ValidationError("GPS seconds must be between 0 and 604799", "seconds", seconds);
1821
1829
  }
1822
1830
  }
1831
+ week;
1832
+ seconds;
1823
1833
  /** Cached GPS reference epoch (1980-01-06T00:00:00.000Z) */
1824
1834
  static reference_ = null;
1825
1835
  /**
@@ -2278,6 +2288,9 @@ var Vector3D = class _Vector3D {
2278
2288
  this.y = y;
2279
2289
  this.z = z;
2280
2290
  }
2291
+ x;
2292
+ y;
2293
+ z;
2281
2294
  /**
2282
2295
  * Create a new Vector3D object from the first three elements of a Vector
2283
2296
  * object.
@@ -2475,6 +2488,7 @@ var Vector = class _Vector {
2475
2488
  this.elements = elements;
2476
2489
  this.length = elements.length;
2477
2490
  }
2491
+ elements;
2478
2492
  /**
2479
2493
  * The length of the vector.
2480
2494
  */
@@ -8595,6 +8609,12 @@ var CubicSpline = class {
8595
8609
  this.p1 = p1;
8596
8610
  this.m1 = m1;
8597
8611
  }
8612
+ t0;
8613
+ p0;
8614
+ m0;
8615
+ t1;
8616
+ p1;
8617
+ m1;
8598
8618
  // / Interpolate position at the provided time [t] _(POSIX seconds)_.
8599
8619
  position_(t) {
8600
8620
  const t2 = t * t;
@@ -8670,6 +8690,7 @@ var CubicSplineInterpolator = class _CubicSplineInterpolator extends StateInterp
8670
8690
  super();
8671
8691
  this.splines_ = splines_;
8672
8692
  }
8693
+ splines_;
8673
8694
  static fromEphemeris(ephemeris) {
8674
8695
  const splines = [];
8675
8696
  for (let i = 0; i < ephemeris.length - 1; i++) {
@@ -8869,6 +8890,7 @@ var VerletBlendInterpolator = class _VerletBlendInterpolator extends StateInterp
8869
8890
  super();
8870
8891
  this.ephemeris = ephemeris;
8871
8892
  }
8893
+ ephemeris;
8872
8894
  get sizeBytes() {
8873
8895
  return 64 * 7 * this.ephemeris.length / 8;
8874
8896
  }
@@ -9028,6 +9050,7 @@ var OemParser = class _OemParser {
9028
9050
  let currentBlock = null;
9029
9051
  let currentMetadata = {};
9030
9052
  let metadataComments = [];
9053
+ let userDefined = {};
9031
9054
  let inMeta = false;
9032
9055
  let inData = false;
9033
9056
  let inCovariance = false;
@@ -9036,6 +9059,7 @@ var OemParser = class _OemParser {
9036
9059
  if (line === "META_START") {
9037
9060
  currentMetadata = {};
9038
9061
  metadataComments = [];
9062
+ userDefined = {};
9039
9063
  inMeta = true;
9040
9064
  continue;
9041
9065
  }
@@ -9043,6 +9067,9 @@ var OemParser = class _OemParser {
9043
9067
  if (metadataComments.length > 0) {
9044
9068
  currentMetadata.COMMENT = metadataComments;
9045
9069
  }
9070
+ if (Object.keys(userDefined).length > 0) {
9071
+ currentMetadata.USER_DEFINED = userDefined;
9072
+ }
9046
9073
  currentBlock = {
9047
9074
  metadata: currentMetadata,
9048
9075
  ephemeris: []
@@ -9081,7 +9108,9 @@ var OemParser = class _OemParser {
9081
9108
  const eqIndex = line.indexOf("=");
9082
9109
  const key = line.substring(0, eqIndex).trim();
9083
9110
  const value = line.substring(eqIndex + 1).trim();
9084
- if (key === "INTERPOLATION_DEGREE") {
9111
+ if (key.startsWith("USER_DEFINED_")) {
9112
+ userDefined[key.substring(13)] = value;
9113
+ } else if (key === "INTERPOLATION_DEGREE") {
9085
9114
  currentMetadata[key] = parseInt(value, 10);
9086
9115
  } else {
9087
9116
  currentMetadata[key] = value;
@@ -13529,6 +13558,11 @@ var Thrust = class {
13529
13558
  crosstrack * 1e-3
13530
13559
  );
13531
13560
  }
13561
+ center;
13562
+ radial;
13563
+ intrack;
13564
+ crosstrack;
13565
+ durationRate;
13532
13566
  deltaV;
13533
13567
  get magnitude() {
13534
13568
  return this.deltaV.magnitude() * 1e3;
@@ -13567,6 +13601,9 @@ var Hill = class _Hill {
13567
13601
  this.semimajorAxis_ = semimajorAxis;
13568
13602
  this.meanMotion_ = Earth.smaToMeanMotion(this.semimajorAxis_);
13569
13603
  }
13604
+ epoch;
13605
+ position;
13606
+ velocity;
13570
13607
  semimajorAxis_;
13571
13608
  meanMotion_;
13572
13609
  static fromState(origin, radialPosition, intrackPosition, nodeVelocity, nodeOffsetTime) {
@@ -14522,15 +14559,21 @@ ${this.line2}`;
14522
14559
  const line1 = _Tle.parseLine1(tleLine1);
14523
14560
  const line2 = _Tle.parseLine2(tleLine2);
14524
14561
  if (line1.satNum !== line2.satNum) {
14562
+ console.info("Line 1 satNum:", line1.satNum);
14563
+ console.info("Line 2 satNum:", line2.satNum);
14525
14564
  throw new ParseError("Satellite numbers do not match between TLE lines", "TLE");
14526
14565
  }
14527
14566
  if (line1.satNumRaw !== line2.satNumRaw) {
14567
+ console.info("Line 1 satNumRaw:", line1.satNumRaw);
14568
+ console.info("Line 2 satNumRaw:", line2.satNumRaw);
14528
14569
  throw new ParseError("Raw satellite numbers do not match between TLE lines", "TLE");
14529
14570
  }
14530
14571
  if (line1.lineNumber1 !== 1) {
14572
+ console.info("Line 1 line number:", line1.lineNumber1);
14531
14573
  throw new ParseError("First TLE line number must be 1", "TLE");
14532
14574
  }
14533
14575
  if (line2.lineNumber2 !== 2) {
14576
+ console.info("Line 2 line number:", line2.lineNumber2);
14534
14577
  throw new ParseError("Second TLE line number must be 2", "TLE");
14535
14578
  }
14536
14579
  return {
@@ -14576,9 +14619,44 @@ ${this.line2}`;
14576
14619
  return { ...line1, ...line2 };
14577
14620
  }
14578
14621
  /**
14579
- * Converts a 6 digit SCC number to a 5 digit SCC alpha 5 number
14580
- * @param sccNum The 6 digit SCC number
14581
- * @returns The 5 digit SCC alpha 5 number
14622
+ * Classifies a satellite catalog number by representation. See {@link SatNumKind}.
14623
+ * Pure function; no side effects.
14624
+ * @param sccNum The catalog number string.
14625
+ * @returns The {@link SatNumKind} describing the input.
14626
+ */
14627
+ static classifySatNum(sccNum) {
14628
+ if (typeof sccNum !== "string") {
14629
+ return "invalid";
14630
+ }
14631
+ const trimmed = sccNum.trim();
14632
+ if (trimmed.length === 0) {
14633
+ return "invalid";
14634
+ }
14635
+ const first = trimmed[0];
14636
+ if (trimmed.length === 5 && first in _Tle.alpha5_) {
14637
+ return /^\d{4}$/u.test(trimmed.slice(1)) ? "alpha5" : "invalid";
14638
+ }
14639
+ if (!/^\d+$/u.test(trimmed)) {
14640
+ return "invalid";
14641
+ }
14642
+ if (trimmed.length <= 5) {
14643
+ return "numeric5";
14644
+ }
14645
+ if (trimmed.length === 6) {
14646
+ return parseInt(trimmed, 10) <= 339999 ? "numeric6" : "extended";
14647
+ }
14648
+ return "extended";
14649
+ }
14650
+ /**
14651
+ * Converts a 6-digit numeric SCC number to its 5-character alpha-5 form.
14652
+ *
14653
+ * Inputs shorter than 6 chars or already in alpha-5 form pass through unchanged.
14654
+ *
14655
+ * @param sccNum The SCC number to convert.
14656
+ * @returns The 5-character alpha-5 representation.
14657
+ * @throws {ValidationError} If `sccNum` exceeds the alpha-5 range (numeric value > 339 999,
14658
+ * or length > 6). For such IDs the canonical value should be kept on
14659
+ * `Satellite.sccNum` and the TLE column populated with the last 5 digits.
14582
14660
  */
14583
14661
  static convert6DigitToA5(sccNum) {
14584
14662
  if (sccNum.length < 6) {
@@ -14587,9 +14665,27 @@ ${this.line2}`;
14587
14665
  if (typeof sccNum[0] !== "string") {
14588
14666
  throw new ParseError("Invalid SCC number format", "TLE");
14589
14667
  }
14668
+ if (sccNum.length > 6) {
14669
+ throw new ValidationError(
14670
+ "SCC number exceeds TLE alpha-5 capacity (max 339999); use Satellite.sccNum for the canonical ID",
14671
+ "sccNum",
14672
+ sccNum
14673
+ );
14674
+ }
14590
14675
  if (RegExp(/[A-Z]/iu, "u").test(sccNum[0])) {
14591
14676
  return sccNum;
14592
14677
  }
14678
+ const numericValue = parseInt(sccNum, 10);
14679
+ if (isNaN(numericValue)) {
14680
+ throw new ValidationError("SCC number must be numeric", "sccNum", sccNum);
14681
+ }
14682
+ if (numericValue > 339999) {
14683
+ throw new ValidationError(
14684
+ "SCC number exceeds TLE alpha-5 capacity (max 339999); use Satellite.sccNum for the canonical ID",
14685
+ "sccNum",
14686
+ sccNum
14687
+ );
14688
+ }
14593
14689
  const rest = sccNum.slice(2, 6);
14594
14690
  let first = parseInt(`${sccNum[0]}${sccNum[1]}`);
14595
14691
  const iPlus = first >= 18 ? 1 : 0;
@@ -14598,9 +14694,17 @@ ${this.line2}`;
14598
14694
  return `${String.fromCharCode(first + 55)}${rest}`;
14599
14695
  }
14600
14696
  /**
14601
- * Converts a 5-digit SCC number to a 6-digit SCC number.
14602
- * @param sccNum - The 5-digit SCC number to convert.
14603
- * @returns The converted 6-digit SCC number.
14697
+ * Converts a 5-character alpha-5 SCC number to its 6-digit numeric form.
14698
+ *
14699
+ * Inputs shorter than 5 chars pass through unchanged. Numeric inputs without
14700
+ * an alpha-5 leading letter pass through unchanged (5-digit numeric, in-range
14701
+ * 6-digit numeric, and extended 7+ digit numeric IDs are all identity).
14702
+ *
14703
+ * @param sccNum The SCC number to convert.
14704
+ * @returns The 6-digit numeric representation, or the input itself if it
14705
+ * is already a numeric form.
14706
+ * @throws {ValidationError} If `sccNum` is malformed: 6-digit numeric whose
14707
+ * value exceeds 339 999, or contains stray letters in a non-leading position.
14604
14708
  */
14605
14709
  static convertA5to6Digit(sccNum) {
14606
14710
  if (sccNum.length < 5) {
@@ -14611,10 +14715,33 @@ ${this.line2}`;
14611
14715
  throw new ParseError("Invalid SCC number format", "TLE");
14612
14716
  }
14613
14717
  if (values[0] in _Tle.alpha5_) {
14718
+ if (!/^\d+$/u.test(sccNum.slice(1))) {
14719
+ throw new ValidationError(
14720
+ "Alpha-5 SCC number must have 4 trailing digits",
14721
+ "sccNum",
14722
+ sccNum
14723
+ );
14724
+ }
14614
14725
  const firstLetter = values[0];
14615
14726
  values[0] = _Tle.alpha5_[firstLetter];
14727
+ return values.join("");
14728
+ }
14729
+ if (!/^\s*\d+\s*$/u.test(sccNum)) {
14730
+ throw new ValidationError(
14731
+ "SCC number must be alpha-5 or all-numeric",
14732
+ "sccNum",
14733
+ sccNum
14734
+ );
14616
14735
  }
14617
- return values.join("");
14736
+ const trimmed = sccNum.trim();
14737
+ if (trimmed.length === 6 && parseInt(trimmed, 10) > 339999) {
14738
+ throw new ValidationError(
14739
+ "6-digit SCC number exceeds TLE alpha-5 capacity (max 339999)",
14740
+ "sccNum",
14741
+ sccNum
14742
+ );
14743
+ }
14744
+ return sccNum;
14618
14745
  }
14619
14746
  };
14620
14747
 
@@ -14836,6 +14963,9 @@ var SolarRadiationPressure = class _SolarRadiationPressure extends Force {
14836
14963
  this.area = area;
14837
14964
  this.reflectCoeff = reflectCoeff;
14838
14965
  }
14966
+ mass;
14967
+ area;
14968
+ reflectCoeff;
14839
14969
  // / Solar pressure _(N/m²)_;
14840
14970
  static _kRef = 456e-8 * KM_PER_AU ** 2;
14841
14971
  acceleration(state) {
@@ -15218,6 +15348,8 @@ var ThirdBodyGravity = class _ThirdBodyGravity {
15218
15348
  this.moon = moon;
15219
15349
  this.sun = sun;
15220
15350
  }
15351
+ moon;
15352
+ sun;
15221
15353
  static moonGravity_(state) {
15222
15354
  const rMoon = Moon.eci(state.epoch.toDateTime());
15223
15355
  const aNum = rMoon.subtract(state.position);
@@ -15320,6 +15452,13 @@ var RAE = class _RAE {
15320
15452
  this.azRateRad = azRateRad;
15321
15453
  this.elRateRad = elRateRad;
15322
15454
  }
15455
+ epoch;
15456
+ rng;
15457
+ azRad;
15458
+ elRad;
15459
+ rngRate;
15460
+ azRateRad;
15461
+ elRateRad;
15323
15462
  // / Create a new [Razel] object, using degrees for the angular values.
15324
15463
  static fromDegrees(epoch, range, azimuth, elevation, rangeRate, azimuthRate, elevationRate) {
15325
15464
  const azimuthRateRad = azimuthRate ? azimuthRate * DEG2RAD : void 0;
@@ -15788,6 +15927,9 @@ var RungeKuttaAdaptive = class _RungeKuttaAdaptive extends Propagator {
15788
15927
  this._cacheState = this.initState_;
15789
15928
  this.tolerance_ = Math.max(_RungeKuttaAdaptive._minTolerance, Math.abs(tolerance_));
15790
15929
  }
15930
+ initState_;
15931
+ forceModel_;
15932
+ tolerance_;
15791
15933
  // / Initial state vector.
15792
15934
  _cacheState;
15793
15935
  _checkpoints = [];
@@ -16083,6 +16225,11 @@ var RungeKutta4Propagator = class extends Propagator {
16083
16225
  this.checkpoints_ = checkpoints_;
16084
16226
  this.stepSize_ = Math.abs(stepSize_);
16085
16227
  }
16228
+ initState_;
16229
+ forceModel_;
16230
+ stepSize_;
16231
+ cacheState_;
16232
+ checkpoints_;
16086
16233
  // / Set the integrator step size to the provided number of [seconds].
16087
16234
  setStepSize(seconds) {
16088
16235
  this.stepSize_ = Math.abs(seconds);
@@ -16411,6 +16558,7 @@ var Sgp4Propagator = class extends Propagator {
16411
16558
  this.tle_ = tle_;
16412
16559
  this.cacheState_ = tle_.state.toJ2000();
16413
16560
  }
16561
+ tle_;
16414
16562
  cacheState_;
16415
16563
  checkpoints_ = [];
16416
16564
  /**
@@ -16497,11 +16645,15 @@ var Satellite = class _Satellite extends SpaceObject {
16497
16645
  period;
16498
16646
  rightAscension;
16499
16647
  satrec;
16500
- /** The satellite catalog number as listed in the TLE. */
16648
+ /** The canonical satellite catalog number. May be a 5-digit numeric, alpha-5,
16649
+ * 6-digit numeric, or an extended (7+ digit) ID such as CelesTrak supplemental
16650
+ * 9-digit IDs. */
16501
16651
  sccNum;
16502
- /** The 5 digit alpha-numeric satellite catalog number. */
16652
+ /** The 5-character alpha-5 representation, or `null` when {@link sccNum} is
16653
+ * an extended ID that exceeds the alpha-5 capacity (max numeric value 339 999). */
16503
16654
  sccNum5;
16504
- /** The 6 digit numeric satellite catalog number. */
16655
+ /** The 6-digit numeric representation, or `null` when {@link sccNum} is
16656
+ * an extended ID that exceeds the alpha-5 capacity (max numeric value 339 999). */
16505
16657
  sccNum6;
16506
16658
  tle1;
16507
16659
  tle2;
@@ -16683,13 +16835,42 @@ var Satellite = class _Satellite extends SpaceObject {
16683
16835
  return new _Satellite({ omm, name: name ?? omm.OBJECT_NAME });
16684
16836
  }
16685
16837
  // ==================== TLE/OMM Parsing ====================
16838
+ /**
16839
+ * Converts an OMM international designator (e.g. `"2026-114A"`) to the
16840
+ * TLE intl-des column format (cols 10-17, e.g. `"26114A"`). Inputs that
16841
+ * don't match the OMM `YYYY-NNNL...` pattern pass through unchanged.
16842
+ */
16843
+ static ommObjectIdToTleIntlDes_(objectId) {
16844
+ if (!objectId) {
16845
+ return "";
16846
+ }
16847
+ const match = objectId.match(/^\d{4}-(?<rest>\d{3}[A-Z]{1,3})$/u);
16848
+ if (match?.groups?.rest) {
16849
+ return objectId.slice(2, 4) + match.groups.rest;
16850
+ }
16851
+ return objectId;
16852
+ }
16853
+ /**
16854
+ * Derives {@link sccNum5} and {@link sccNum6} from {@link sccNum}. When the
16855
+ * canonical ID is an extended (7+ digit) value that exceeds the TLE alpha-5
16856
+ * capacity (max 339 999), both forms are set to `null`.
16857
+ */
16858
+ assignAlpha5Forms_() {
16859
+ const kind = Tle.classifySatNum(this.sccNum);
16860
+ if (kind === "numeric5" || kind === "alpha5" || kind === "numeric6") {
16861
+ this.sccNum5 = Tle.convert6DigitToA5(this.sccNum);
16862
+ this.sccNum6 = Tle.convertA5to6Digit(this.sccNum5);
16863
+ } else {
16864
+ this.sccNum5 = null;
16865
+ this.sccNum6 = null;
16866
+ }
16867
+ }
16686
16868
  parseTleAndUpdateOrbit_(tle1, tle2, sccNum) {
16687
16869
  const tleData = Tle.parse(tle1, tle2);
16688
16870
  this.tle1 = tle1;
16689
16871
  this.tle2 = tle2;
16690
16872
  this.sccNum = sccNum ?? tleData.satNum.toString();
16691
- this.sccNum5 = Tle.convert6DigitToA5(this.sccNum);
16692
- this.sccNum6 = Tle.convertA5to6Digit(this.sccNum5);
16873
+ this.assignAlpha5Forms_();
16693
16874
  this.intlDes = tleData.intlDes;
16694
16875
  this.epochYear = tleData.epochYear;
16695
16876
  this.epochDay = tleData.epochDay;
@@ -16712,8 +16893,7 @@ var Satellite = class _Satellite extends SpaceObject {
16712
16893
  parseOmmAndUpdateOrbit_(omm) {
16713
16894
  const noradStr = String(omm.NORAD_CAT_ID);
16714
16895
  this.sccNum = noradStr.padStart(5, "0");
16715
- this.sccNum5 = Tle.convert6DigitToA5(noradStr);
16716
- this.sccNum6 = Tle.convertA5to6Digit(this.sccNum5);
16896
+ this.assignAlpha5Forms_();
16717
16897
  this.intlDes = omm.OBJECT_ID;
16718
16898
  const YYYY = omm.EPOCH.slice(0, 4);
16719
16899
  const MM = omm.EPOCH.slice(5, 7);
@@ -16773,8 +16953,10 @@ var Satellite = class _Satellite extends SpaceObject {
16773
16953
  ecen: this.eccentricity,
16774
16954
  epochyr: this.epochYear,
16775
16955
  epochday: this.epochDay,
16776
- intl: omm.OBJECT_ID,
16777
- scc: this.sccNum,
16956
+ intl: _Satellite.ommObjectIdToTleIntlDes_(omm.OBJECT_ID),
16957
+ // Extended (7+ digit) IDs don't fit TLE cols 3-7. Truncate to the last 5
16958
+ // digits for the TLE string; the canonical ID stays on this.sccNum.
16959
+ scc: Tle.classifySatNum(this.sccNum) === "extended" ? this.sccNum.slice(-5) : this.sccNum,
16778
16960
  bstar: this.bstar,
16779
16961
  meanMotionDot: this.meanMoDev1,
16780
16962
  meanMotionDdot: this.meanMoDev2,
@@ -19119,6 +19301,13 @@ var RadecGeocentric = class _RadecGeocentric {
19119
19301
  this.declinationRate = declinationRate;
19120
19302
  this.rangeRate = rangeRate;
19121
19303
  }
19304
+ epoch;
19305
+ rightAscension;
19306
+ declination;
19307
+ range;
19308
+ rightAscensionRate;
19309
+ declinationRate;
19310
+ rangeRate;
19122
19311
  /**
19123
19312
  * Creates a RadecGeocentric object from the given parameters in degrees.
19124
19313
  * @param epoch - The epoch in UTC.
@@ -19261,6 +19450,13 @@ var RadecTopocentric = class _RadecTopocentric {
19261
19450
  this.declinationRate = declinationRate;
19262
19451
  this.rangeRate = rangeRate;
19263
19452
  }
19453
+ epoch;
19454
+ rightAscension;
19455
+ declination;
19456
+ range;
19457
+ rightAscensionRate;
19458
+ declinationRate;
19459
+ rangeRate;
19264
19460
  /**
19265
19461
  * Create a new RadecTopocentric object, using degrees for the angular values.
19266
19462
  * @param epoch UTC epoch.
@@ -19818,6 +20014,8 @@ var RkCheckpoint = class {
19818
20014
  this.cacheState = cacheState;
19819
20015
  this.stepSize = stepSize;
19820
20016
  }
20017
+ cacheState;
20018
+ stepSize;
19821
20019
  };
19822
20020
 
19823
20021
  // src/propagator/RkResult.ts
@@ -19828,6 +20026,9 @@ var RkResult = class {
19828
20026
  this.error = error;
19829
20027
  this.newStep = newStep;
19830
20028
  }
20029
+ state;
20030
+ error;
20031
+ newStep;
19831
20032
  };
19832
20033
 
19833
20034
  // src/covariance/StateCovariance.ts
@@ -19848,6 +20049,8 @@ var StateCovariance = class _StateCovariance {
19848
20049
  this.matrix = matrix;
19849
20050
  this.frame = frame;
19850
20051
  }
20052
+ matrix;
20053
+ frame;
19851
20054
  // / Create a new [StateCovariance] object from 1-sigma values.
19852
20055
  static fromSigmas(sigmas, frame) {
19853
20056
  const n = sigmas.length;
@@ -19878,6 +20081,8 @@ var PropagatorPairs = class {
19878
20081
  this.posStep_ = posStep_;
19879
20082
  this.velStep_ = velStep_;
19880
20083
  }
20084
+ posStep_;
20085
+ velStep_;
19881
20086
  _high = Array(6).fill(null);
19882
20087
  _low = Array(6).fill(null);
19883
20088
  set(index, high, low) {
@@ -19911,6 +20116,9 @@ var BatchLeastSquaresResult = class {
19911
20116
  this.covariance = covariance2;
19912
20117
  this.rms = rms;
19913
20118
  }
20119
+ state;
20120
+ covariance;
20121
+ rms;
19914
20122
  };
19915
20123
 
19916
20124
  // src/orbit-determination/BatchLeastSquaresOD.ts
@@ -19941,6 +20149,12 @@ var BatchLeastSquaresOD = class _BatchLeastSquaresOD {
19941
20149
  this.propagator_ = new RungeKutta89Propagator(this.apriori_, this.forceModel_);
19942
20150
  this.nominal_ = this.propagator_.propagate(this.start_);
19943
20151
  }
20152
+ observations_;
20153
+ apriori_;
20154
+ forceModel_;
20155
+ posStep_;
20156
+ velStep_;
20157
+ fastDerivatives_;
19944
20158
  /** Propagator pair cache, for generating observation Jacobians. */
19945
20159
  propPairs_;
19946
20160
  /** Nominal state propagator. */
@@ -20041,6 +20255,7 @@ var GibbsIOD = class _GibbsIOD {
20041
20255
  constructor(mu = Earth.mu) {
20042
20256
  this.mu = mu;
20043
20257
  }
20258
+ mu;
20044
20259
  /** Abort solve if position plane exceeds this value. */
20045
20260
  static coplanarThreshold_ = 5 * DEG2RAD;
20046
20261
  /**
@@ -20099,6 +20314,7 @@ var HerrickGibbsIOD = class {
20099
20314
  constructor(mu = Earth.mu) {
20100
20315
  this.mu = mu;
20101
20316
  }
20317
+ mu;
20102
20318
  // / Attempt to create a state estimate from three inertial position vectors.
20103
20319
  solve(r1, t1, r2, t2, r3, t3) {
20104
20320
  const dt31 = t3.difference(t1);
@@ -20359,6 +20575,7 @@ var LambertIOD = class _LambertIOD {
20359
20575
  constructor(mu = Earth.mu) {
20360
20576
  this.mu = mu;
20361
20577
  }
20578
+ mu;
20362
20579
  /**
20363
20580
  * Try to guess the short path argument given an [interceptor] and
20364
20581
  * [target] state.
@@ -21046,6 +21263,11 @@ var LevenbergMarquardtResult = class {
21046
21263
  this.iterations = iterations;
21047
21264
  this.converged = converged;
21048
21265
  }
21266
+ state;
21267
+ covariance;
21268
+ rms;
21269
+ iterations;
21270
+ converged;
21049
21271
  };
21050
21272
 
21051
21273
  // src/orbit-determination/LevenbergMarquardtOD.ts
@@ -21076,6 +21298,12 @@ var LevenbergMarquardtOD = class _LevenbergMarquardtOD {
21076
21298
  const propagator = new RungeKutta89Propagator(this.apriori_, this.forceModel_);
21077
21299
  this.nominal_ = propagator.propagate(this.start_);
21078
21300
  }
21301
+ observations_;
21302
+ apriori_;
21303
+ forceModel_;
21304
+ posStep_;
21305
+ velStep_;
21306
+ fastDerivatives_;
21079
21307
  /** Propagator pair cache, for generating observation Jacobians. */
21080
21308
  propPairs_;
21081
21309
  /** State estimate during solve. */
@@ -21234,6 +21462,8 @@ var SimplexEntry = class _SimplexEntry {
21234
21462
  this.x_ = new Vector(points);
21235
21463
  this.score = this.f_(points);
21236
21464
  }
21465
+ f_;
21466
+ points;
21237
21467
  /**
21238
21468
  * The cost function score at this vertex.
21239
21469
  *
@@ -21766,6 +21996,8 @@ var ConjunctionAssessment = class {
21766
21996
  this.primaryProp = this.createPropagator(primary, false);
21767
21997
  this.secondaryProp = this.createPropagator(secondary, false);
21768
21998
  }
21999
+ primary;
22000
+ secondary;
21769
22001
  primaryProp;
21770
22002
  secondaryProp;
21771
22003
  primaryCovSample;
@@ -23211,6 +23443,9 @@ var ObservationRadar = class _ObservationRadar extends Observation {
23211
23443
  this.observation = observation;
23212
23444
  this.noise_ = noise_;
23213
23445
  }
23446
+ site_;
23447
+ observation;
23448
+ noise_;
23214
23449
  // / Default noise matrix.
23215
23450
  static defaultNoise = _ObservationRadar.noiseFromSigmas(0.32, 0.015 * DEG2RAD, 0.015 * DEG2RAD);
23216
23451
  get epoch() {
@@ -23700,6 +23935,9 @@ var ObservationOptical = class _ObservationOptical extends Observation {
23700
23935
  this.observation = observation;
23701
23936
  this.noise_ = noise_;
23702
23937
  }
23938
+ site_;
23939
+ observation;
23940
+ noise_;
23703
23941
  // / Inertial site location.
23704
23942
  get site() {
23705
23943
  return this.site_;
@@ -24182,12 +24420,12 @@ var HorizonsParser = class {
24182
24420
  for (let i = 0; i < lines.length; i++) {
24183
24421
  const line = lines[i].trim();
24184
24422
  if (line.startsWith("Target body name:")) {
24185
- targetName = this.extractValue_(line, "Target body name:");
24423
+ targetName = this.extractTargetName_(line, "Target body name:");
24186
24424
  metadata.targetName = targetName;
24187
24425
  } else if (line.startsWith("Center body name:")) {
24188
24426
  centerBody = this.extractValue_(line, "Center body name:");
24189
24427
  metadata.centerBody = centerBody;
24190
- } else if (line.startsWith("Center-site name:")) {
24428
+ } else if (line.startsWith("Center-site name:") && !centerBody) {
24191
24429
  centerBody = this.extractValue_(line, "Center-site name:");
24192
24430
  metadata.centerBody = centerBody;
24193
24431
  } else if (line.startsWith("Output type:")) {
@@ -24242,7 +24480,7 @@ var HorizonsParser = class {
24242
24480
  for (let i = 0; i < lines.length; i++) {
24243
24481
  const line = lines[i].trim();
24244
24482
  if (line.startsWith("Target body name:")) {
24245
- targetName = this.extractValue_(line, "Target body name:");
24483
+ targetName = this.extractTargetName_(line, "Target body name:");
24246
24484
  } else if (line.startsWith("Center-site name:")) {
24247
24485
  observerLocation = this.extractValue_(line, "Center-site name:");
24248
24486
  }
@@ -24273,7 +24511,23 @@ var HorizonsParser = class {
24273
24511
  */
24274
24512
  static extractValue_(line, key) {
24275
24513
  const value = line.substring(key.length).trim();
24276
- return value.split(/\s{2,}/)[0].trim();
24514
+ return value.split(/\s{2,}/u)[0].trim();
24515
+ }
24516
+ /**
24517
+ * Extracts the target body name, stripping parenthetical descriptors and IDs.
24518
+ *
24519
+ * Horizons format examples:
24520
+ * - "1 Ceres {source: astDys}" → "1 Ceres"
24521
+ * - "Artemis II (spacecraft) (-1024) {source: ...}" → "Artemis II"
24522
+ * - "Mars (499)" → "Mars"
24523
+ */
24524
+ static extractTargetName_(line, key) {
24525
+ const raw = this.extractValue_(line, key);
24526
+ const parenIdx = raw.search(/\s\(/u);
24527
+ if (parenIdx > 0) {
24528
+ return raw.substring(0, parenIdx).trim();
24529
+ }
24530
+ return raw;
24277
24531
  }
24278
24532
  /**
24279
24533
  * Parses a vector data line from Horizons output.
@@ -24343,7 +24597,9 @@ var HorizonsParser = class {
24343
24597
  return null;
24344
24598
  }
24345
24599
  const posLine = allLines[nextIndex].trim();
24346
- const posMatch = posLine.match(/X\s*=\s*([-\d.E+]+)\s+Y\s*=\s*([-\d.E+]+)\s+Z\s*=\s*([-\d.E+]+)/i);
24600
+ const posMatchLabeled = posLine.match(/X\s*=\s*([-\d.E+]+)\s+Y\s*=\s*([-\d.E+]+)\s+Z\s*=\s*([-\d.E+]+)/iu);
24601
+ const posMatchBare = !posMatchLabeled ? posLine.match(/^\s*([-\d.E+]+)\s+([-\d.E+]+)\s+([-\d.E+]+)\s*$/iu) : null;
24602
+ const posMatch = posMatchLabeled ?? posMatchBare;
24347
24603
  if (!posMatch) {
24348
24604
  return null;
24349
24605
  }
@@ -24355,7 +24611,9 @@ var HorizonsParser = class {
24355
24611
  let velocity;
24356
24612
  if (nextIndex < allLines.length) {
24357
24613
  const velLine = allLines[nextIndex].trim();
24358
- const velMatch = velLine.match(/VX\s*=\s*([-\d.E+]+)\s+VY\s*=\s*([-\d.E+]+)\s+VZ\s*=\s*([-\d.E+]+)/i);
24614
+ const velMatchLabeled = velLine.match(/VX\s*=\s*([-\d.E+]+)\s+VY\s*=\s*([-\d.E+]+)\s+VZ\s*=\s*([-\d.E+]+)/iu);
24615
+ const velMatchBare = !velMatchLabeled ? velLine.match(/^\s*([-\d.E+]+)\s+([-\d.E+]+)\s+([-\d.E+]+)\s*$/iu) : null;
24616
+ const velMatch = velMatchLabeled ?? velMatchBare;
24359
24617
  if (velMatch) {
24360
24618
  velocity = new Vector3D(
24361
24619
  parseFloat(velMatch[1]),
@@ -24365,6 +24623,17 @@ var HorizonsParser = class {
24365
24623
  nextIndex++;
24366
24624
  }
24367
24625
  }
24626
+ while (nextIndex < allLines.length) {
24627
+ const extraLine = allLines[nextIndex].trim();
24628
+ if (extraLine === "$$EOE" || extraLine.length === 0 || /^\d+\.\d+\s*=\s*A\.D\./u.test(extraLine)) {
24629
+ break;
24630
+ }
24631
+ if (/^\s*[-\d.E+]+(\s+[-\d.E+]+)*\s*$/u.test(extraLine)) {
24632
+ nextIndex++;
24633
+ } else {
24634
+ break;
24635
+ }
24636
+ }
24368
24637
  return {
24369
24638
  data: { epoch, position, velocity },
24370
24639
  nextIndex
@@ -25111,6 +25380,58 @@ var OdmExporter = class _OdmExporter {
25111
25380
  return lines.join("\n");
25112
25381
  }
25113
25382
  // ==========================================================================
25383
+ // OEM from State Vectors — direct J2000 array export
25384
+ // ==========================================================================
25385
+ /**
25386
+ * Export an array of J2000 state vectors as OEM KVN.
25387
+ *
25388
+ * Unlike {@link formatOem}, which propagates a TLE-based satellite, this
25389
+ * method serializes pre-computed state vectors directly. Useful for
25390
+ * converting parsed ephemeris data (e.g., NASA Horizons) to CCSDS OEM.
25391
+ *
25392
+ * @param stateVectors - Array of J2000 state vectors to export
25393
+ * @param metadata - Object identification metadata
25394
+ * @param options - Export configuration
25395
+ * @returns OEM KVN format string
25396
+ */
25397
+ static formatOemFromStateVectors(stateVectors, metadata, options = {}) {
25398
+ if (stateVectors.length === 0) {
25399
+ throw new Error("Cannot export OEM with no state vectors");
25400
+ }
25401
+ const refFrame = options.refFrame ?? "EME2000";
25402
+ const centerName = options.centerName ?? "EARTH";
25403
+ const startTime = stateVectors[0].epoch.toDateTime();
25404
+ const stopTime = stateVectors[stateVectors.length - 1].epoch.toDateTime();
25405
+ const lines = [];
25406
+ lines.push("CCSDS_OEM_VERS = 2.0");
25407
+ _OdmExporter.appendComments_(lines, options.comments);
25408
+ lines.push(`CREATION_DATE = ${_OdmExporter.formatDateTime_(/* @__PURE__ */ new Date())}`);
25409
+ lines.push(`ORIGINATOR = ${options.originator ?? "KeepTrack"}`);
25410
+ if (options.messageId) {
25411
+ lines.push(`MESSAGE_ID = ${options.messageId}`);
25412
+ }
25413
+ lines.push("");
25414
+ lines.push("META_START");
25415
+ lines.push(`OBJECT_NAME = ${metadata.objectName}`);
25416
+ lines.push(`OBJECT_ID = ${metadata.objectId}`);
25417
+ lines.push(`CENTER_NAME = ${centerName}`);
25418
+ lines.push(`REF_FRAME = ${refFrame}`);
25419
+ lines.push("TIME_SYSTEM = UTC");
25420
+ lines.push(`START_TIME = ${_OdmExporter.formatDateTime_(startTime)}`);
25421
+ lines.push(`STOP_TIME = ${_OdmExporter.formatDateTime_(stopTime)}`);
25422
+ lines.push(`INTERPOLATION = ${options.interpolation ?? "LAGRANGE"}`);
25423
+ lines.push(`INTERPOLATION_DEGREE = ${options.interpolationDegree ?? 7}`);
25424
+ lines.push("META_STOP");
25425
+ lines.push("");
25426
+ for (const sv of stateVectors) {
25427
+ const epoch = _OdmExporter.formatDateTime_(sv.epoch.toDateTime());
25428
+ lines.push(
25429
+ `${epoch} ${_OdmExporter.formatNumber_(sv.position.x)} ${_OdmExporter.formatNumber_(sv.position.y)} ${_OdmExporter.formatNumber_(sv.position.z)} ${_OdmExporter.formatNumber_(sv.velocity.x)} ${_OdmExporter.formatNumber_(sv.velocity.y)} ${_OdmExporter.formatNumber_(sv.velocity.z)}`
25430
+ );
25431
+ }
25432
+ return lines.join("\n");
25433
+ }
25434
+ // ==========================================================================
25114
25435
  // OMM — Orbit Mean-Elements Message
25115
25436
  // ==========================================================================
25116
25437
  /**
@@ -26910,6 +27231,11 @@ var ChebyshevCoefficients = class _ChebyshevCoefficients {
26910
27231
  this.cyd_ = _ChebyshevCoefficients._derivative(a, b, cy_);
26911
27232
  this.czd_ = _ChebyshevCoefficients._derivative(a, b, cz_);
26912
27233
  }
27234
+ a;
27235
+ b;
27236
+ cx_;
27237
+ cy_;
27238
+ cz_;
26913
27239
  cxd_;
26914
27240
  cyd_;
26915
27241
  czd_;
@@ -27431,6 +27757,11 @@ var TwoBurnOrbitTransfer = class _TwoBurnOrbitTransfer {
27431
27757
  this.vTransB = vTransB;
27432
27758
  this.tTrans = tTrans;
27433
27759
  }
27760
+ vInit;
27761
+ vFinal;
27762
+ vTransA;
27763
+ vTransB;
27764
+ tTrans;
27434
27765
  /**
27435
27766
  * Calculates the parameters for a Hohmann transfer orbit between two circular orbits.
27436
27767
  * @param rInit The initial radius of the orbit. (km)
@@ -27483,6 +27814,7 @@ var ChebyshevCompressor = class _ChebyshevCompressor {
27483
27814
  constructor(interpolator_) {
27484
27815
  this.interpolator_ = interpolator_;
27485
27816
  }
27817
+ interpolator_;
27486
27818
  /** Returns the cosine of π times x. */
27487
27819
  static cosPi_(x) {
27488
27820
  return Math.cos(Math.PI * x);
@@ -27723,6 +28055,8 @@ var SimpleLinearRegression = class _SimpleLinearRegression {
27723
28055
  this.ys = ys;
27724
28056
  this.update();
27725
28057
  }
28058
+ xs;
28059
+ ys;
27726
28060
  /** Line slope (m in y = mx + b). */
27727
28061
  slope_ = 0;
27728
28062
  /** Y-axis intercept (b in y = mx + b). */