ootk 6.0.6 → 6.0.7

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,8 +23,6 @@ var ValidationError = class extends OotkError {
23
23
  this.value = value;
24
24
  this.name = "ValidationError";
25
25
  }
26
- field;
27
- value;
28
26
  };
29
27
  var ParseError = class extends OotkError {
30
28
  /**
@@ -39,8 +37,6 @@ var ParseError = class extends OotkError {
39
37
  this.line = line;
40
38
  this.name = "ParseError";
41
39
  }
42
- format;
43
- line;
44
40
  };
45
41
  var PropagationError = class extends OotkError {
46
42
  /**
@@ -53,7 +49,6 @@ var PropagationError = class extends OotkError {
53
49
  this.epoch = epoch;
54
50
  this.name = "PropagationError";
55
51
  }
56
- epoch;
57
52
  };
58
53
  var OrbitDeterminationError = class extends OotkError {
59
54
  /**
@@ -66,7 +61,6 @@ var OrbitDeterminationError = class extends OotkError {
66
61
  this.algorithm = algorithm;
67
62
  this.name = "OrbitDeterminationError";
68
63
  }
69
- algorithm;
70
64
  };
71
65
 
72
66
  // src/enums/AngularDiameterMethod.ts
@@ -284,7 +278,6 @@ var Epoch = class {
284
278
  throw new ValidationError("Epoch posix time must be a valid number", "posix", posix);
285
279
  }
286
280
  }
287
- posix;
288
281
  toString() {
289
282
  return this.toDateTime().toISOString();
290
283
  }
@@ -308,7 +301,7 @@ var Epoch = class {
308
301
  const currentDateObj = this.toDateTime();
309
302
  const epochYear = currentDateObj.getUTCFullYear().toString().slice(2, 4);
310
303
  const epochDay = this.getDayOfYear_(currentDateObj);
311
- const timeOfDay = (currentDateObj.getUTCHours() * 60 + currentDateObj.getUTCMinutes()) / 1440;
304
+ const timeOfDay = (currentDateObj.getUTCHours() * 3600 + currentDateObj.getUTCMinutes() * 60 + currentDateObj.getUTCSeconds() + currentDateObj.getUTCMilliseconds() / 1e3) / 86400;
312
305
  const epochDayStr = (epochDay + timeOfDay).toFixed(8).padStart(12, "0");
313
306
  return {
314
307
  epochYr: epochYear,
@@ -1828,8 +1821,6 @@ var EpochGPS = class _EpochGPS {
1828
1821
  throw new ValidationError("GPS seconds must be between 0 and 604799", "seconds", seconds);
1829
1822
  }
1830
1823
  }
1831
- week;
1832
- seconds;
1833
1824
  /** Cached GPS reference epoch (1980-01-06T00:00:00.000Z) */
1834
1825
  static reference_ = null;
1835
1826
  /**
@@ -2255,6 +2246,32 @@ function createSampleCovarianceFromTle(tleLine1, tleLine2, frame = "ric" /* RIC
2255
2246
  const sample = new CovarianceSample(j2000State, covariance2, tle);
2256
2247
  return frame === "ric" /* RIC */ ? sample.desampleRIC() : sample.desampleJ2000();
2257
2248
  }
2249
+ var DEFAULT_SCREENING_SIGMA_CAPS = [1200, 1e3, 5e3];
2250
+ function cappedScreeningCovarianceFromTle(tleLine1, tleLine2, confidenceLevel, caps = DEFAULT_SCREENING_SIGMA_CAPS) {
2251
+ let elements;
2252
+ try {
2253
+ elements = createSampleCovarianceFromTle(tleLine1, tleLine2).matrix.elements;
2254
+ } catch {
2255
+ return buildFallbackScreeningCovariance_(caps);
2256
+ }
2257
+ const radialVar = elements[0][0];
2258
+ const intrackVar = elements[1][1];
2259
+ const crosstrackVar = elements[2][2];
2260
+ elements[0][0] = Math.min(Math.sqrt(radialVar) * confidenceLevel, caps[0]);
2261
+ elements[1][1] = Math.min(Math.sqrt(crosstrackVar) * confidenceLevel, caps[1]);
2262
+ elements[2][2] = Math.min(Math.sqrt(intrackVar) * confidenceLevel, caps[2]);
2263
+ if (!elements[0][0] || !elements[1][1] || !elements[2][2]) {
2264
+ return buildFallbackScreeningCovariance_(caps);
2265
+ }
2266
+ return new StateCovariance(new Matrix(elements), "eci" /* ECI */);
2267
+ }
2268
+ function buildFallbackScreeningCovariance_(caps) {
2269
+ const fallback = Array.from({ length: 6 }, () => new Array(6).fill(0));
2270
+ fallback[0][0] = caps[0];
2271
+ fallback[1][1] = caps[1];
2272
+ fallback[2][2] = caps[2];
2273
+ return new StateCovariance(new Matrix(fallback), "eci" /* ECI */);
2274
+ }
2258
2275
 
2259
2276
  // src/utils/jacobian.ts
2260
2277
  var jacobian = (f, m, x0, step = 1e-5) => {
@@ -2281,6 +2298,17 @@ function linearDistance(pos1, pos2) {
2281
2298
  return Math.sqrt((pos1.x - pos2.x) ** 2 + (pos1.y - pos2.y) ** 2 + (pos1.z - pos2.z) ** 2);
2282
2299
  }
2283
2300
 
2301
+ // src/utils/photometry.ts
2302
+ var RCS_VMAG_ESTIMATE_MIN = -5;
2303
+ var RCS_VMAG_ESTIMATE_MAX = 15;
2304
+ function estimateVmagFromRcs(rcs) {
2305
+ if (typeof rcs !== "number" || !Number.isFinite(rcs) || rcs <= 0) {
2306
+ return null;
2307
+ }
2308
+ const vmag = -1.3 - 2.5 * Math.log10(rcs);
2309
+ return Math.min(Math.max(vmag, RCS_VMAG_ESTIMATE_MIN), RCS_VMAG_ESTIMATE_MAX);
2310
+ }
2311
+
2284
2312
  // src/operations/Vector3D.ts
2285
2313
  var Vector3D = class _Vector3D {
2286
2314
  constructor(x, y, z) {
@@ -2288,9 +2316,6 @@ var Vector3D = class _Vector3D {
2288
2316
  this.y = y;
2289
2317
  this.z = z;
2290
2318
  }
2291
- x;
2292
- y;
2293
- z;
2294
2319
  /**
2295
2320
  * Create a new Vector3D object from the first three elements of a Vector
2296
2321
  * object.
@@ -2488,7 +2513,6 @@ var Vector = class _Vector {
2488
2513
  this.elements = elements;
2489
2514
  this.length = elements.length;
2490
2515
  }
2491
- elements;
2492
2516
  /**
2493
2517
  * The length of the vector.
2494
2518
  */
@@ -3269,7 +3293,7 @@ var Random = class {
3269
3293
  }
3270
3294
  };
3271
3295
 
3272
- // ../../../node_modules/astronomy-engine/esm/astronomy.js
3296
+ // node_modules/astronomy-engine/esm/astronomy.js
3273
3297
  var C_AUDAY = 173.1446326846693;
3274
3298
  var KM_PER_AU2 = 14959787069098932e-8;
3275
3299
  var DEG2RAD2 = 0.017453292519943295;
@@ -8609,12 +8633,6 @@ var CubicSpline = class {
8609
8633
  this.p1 = p1;
8610
8634
  this.m1 = m1;
8611
8635
  }
8612
- t0;
8613
- p0;
8614
- m0;
8615
- t1;
8616
- p1;
8617
- m1;
8618
8636
  // / Interpolate position at the provided time [t] _(POSIX seconds)_.
8619
8637
  position_(t) {
8620
8638
  const t2 = t * t;
@@ -8690,7 +8708,6 @@ var CubicSplineInterpolator = class _CubicSplineInterpolator extends StateInterp
8690
8708
  super();
8691
8709
  this.splines_ = splines_;
8692
8710
  }
8693
- splines_;
8694
8711
  static fromEphemeris(ephemeris) {
8695
8712
  const splines = [];
8696
8713
  for (let i = 0; i < ephemeris.length - 1; i++) {
@@ -8890,7 +8907,6 @@ var VerletBlendInterpolator = class _VerletBlendInterpolator extends StateInterp
8890
8907
  super();
8891
8908
  this.ephemeris = ephemeris;
8892
8909
  }
8893
- ephemeris;
8894
8910
  get sizeBytes() {
8895
8911
  return 64 * 7 * this.ephemeris.length / 8;
8896
8912
  }
@@ -9878,7 +9894,10 @@ var FormatTle = class _FormatTle {
9878
9894
  */
9879
9895
  static createTle(tleParams) {
9880
9896
  const { inc, meanmo, rasc, argPe, meana, ecen, epochyr, epochday, intl } = tleParams;
9881
- const scc = Tle.convert6DigitToA5(tleParams.scc);
9897
+ let scc = Tle.convert6DigitToA5(tleParams.scc);
9898
+ if (/^\d{1,4}$/u.test(scc)) {
9899
+ scc = scc.padStart(5, "0");
9900
+ }
9882
9901
  const epochYrStr = String(epochyr).padStart(2, "0");
9883
9902
  const epochdayStr = Number(epochday).toFixed(8).padStart(12, "0");
9884
9903
  const incStr = _FormatTle.inclination(inc);
@@ -10391,7 +10410,7 @@ var Sgp4 = class _Sgp4 {
10391
10410
  error: 0 /* NO_ERROR */
10392
10411
  };
10393
10412
  const xpdotp = 1440 / (2 * PI);
10394
- satrec.satnum = tleLine1.substring(2, 7);
10413
+ satrec.satnum = tleLine1.charAt(7) === "V" ? "0" : tleLine1.substring(2, 7);
10395
10414
  satrec.epochyr = parseInt(tleLine1.substring(18, 20));
10396
10415
  satrec.epochdays = parseFloat(tleLine1.substring(20, 32));
10397
10416
  satrec.ndot = parseFloat(tleLine1.substring(33, 43));
@@ -13558,11 +13577,6 @@ var Thrust = class {
13558
13577
  crosstrack * 1e-3
13559
13578
  );
13560
13579
  }
13561
- center;
13562
- radial;
13563
- intrack;
13564
- crosstrack;
13565
- durationRate;
13566
13580
  deltaV;
13567
13581
  get magnitude() {
13568
13582
  return this.deltaV.magnitude() * 1e3;
@@ -13601,9 +13615,6 @@ var Hill = class _Hill {
13601
13615
  this.semimajorAxis_ = semimajorAxis;
13602
13616
  this.meanMotion_ = Earth.smaToMeanMotion(this.semimajorAxis_);
13603
13617
  }
13604
- epoch;
13605
- position;
13606
- velocity;
13607
13618
  semimajorAxis_;
13608
13619
  meanMotion_;
13609
13620
  static fromState(origin, radialPosition, intrackPosition, nodeVelocity, nodeOffsetTime) {
@@ -13917,7 +13928,7 @@ var Tle = class _Tle {
13917
13928
  this.line1 = line1;
13918
13929
  this.line2 = line2;
13919
13930
  this.epoch = _Tle.parseEpoch_(line1.substring(18, 32));
13920
- this.satnum = parseInt(_Tle.convertA5to6Digit(line1.substring(2, 7)));
13931
+ this.satnum = _Tle.satNum(this.line1);
13921
13932
  this.satrec_ = Sgp4.createSatrec(line1, line2, gravConst, opsMode);
13922
13933
  }
13923
13934
  toString() {
@@ -14006,7 +14017,7 @@ ${this.line2}`;
14006
14017
  epochYearFull = 1900 + epochYearShort;
14007
14018
  }
14008
14019
  const epochJday = epochDayOfYear + epochYearFull * 365;
14009
- const currentJday = getDayOfYear() + currentYearFull * 365;
14020
+ const currentJday = getDayOfYear(nowInput) + currentYearFull * 365;
14010
14021
  const currentTime = (nowInput.getUTCHours() * 3600 + nowInput.getUTCMinutes() * 60 + nowInput.getUTCSeconds()) / 86400;
14011
14022
  const daysOld = currentJday + currentTime - epochJday;
14012
14023
  switch (outputUnits) {
@@ -14154,7 +14165,7 @@ ${this.line2}`;
14154
14165
  const BSTAR_PART_3 = _Tle.bstar_.start + 6;
14155
14166
  const BSTAR_PART_4 = _Tle.bstar_.stop - 1;
14156
14167
  const bstarSymbol = tleLine1.substring(_Tle.bstar_.start, BSTAR_PART_2);
14157
- let bstar1 = parseFloat(`0.${tleLine1.substring(BSTAR_PART_2, BSTAR_PART_3)}`);
14168
+ const mantissaFraction = tleLine1.substring(BSTAR_PART_2, BSTAR_PART_3);
14158
14169
  const exponentSymbol = tleLine1.substring(BSTAR_PART_3, BSTAR_PART_4);
14159
14170
  let exponent = parseInt(tleLine1.substring(BSTAR_PART_4, _Tle.bstar_.stop));
14160
14171
  if (exponentSymbol === "-") {
@@ -14162,12 +14173,16 @@ ${this.line2}`;
14162
14173
  } else if (exponentSymbol !== "+" && exponentSymbol !== " " && exponentSymbol !== "0") {
14163
14174
  throw new ParseError(`Invalid BSTAR exponent symbol: ${exponentSymbol}`, "TLE");
14164
14175
  }
14165
- bstar1 *= 10 ** exponent;
14176
+ let sign2 = 1;
14177
+ let integerPart = "0";
14166
14178
  if (bstarSymbol === "-") {
14167
- bstar1 *= -1;
14168
- } else if (bstarSymbol === "+" || bstarSymbol === " " || bstarSymbol === "0") ; else {
14179
+ sign2 = -1;
14180
+ } else if (bstarSymbol === "+" || bstarSymbol === " " || bstarSymbol === "0") ; else if (/^\d$/u.test(bstarSymbol)) {
14181
+ integerPart = bstarSymbol;
14182
+ } else {
14169
14183
  throw new ParseError(`Invalid BSTAR symbol: ${bstarSymbol}`, "TLE");
14170
14184
  }
14185
+ const bstar1 = sign2 * parseFloat(`${integerPart}.${mantissaFraction}`) * 10 ** exponent;
14171
14186
  return toPrecision(bstar1, 14);
14172
14187
  }
14173
14188
  /**
@@ -14222,22 +14237,25 @@ ${this.line2}`;
14222
14237
  }
14223
14238
  /**
14224
14239
  * Private value - used by United States Space Force to reference the orbit model used to generate the Tle. Will
14225
- * always be seen as zero externally (e.g. by "us", unless you are "them" - in which case, hello!).
14240
+ * almost always be seen as zero externally (e.g. by "us", unless you are "them" - in which case, hello!).
14241
+ *
14242
+ * A value of 1 is tolerated in addition to 0: the field is informational and does not change how SGP4/SDP4
14243
+ * propagate the element set, and a handful of archival TLEs carry a 1 (originally an SGP marker).
14226
14244
  *
14227
- * Starting in 2024, this may contain a 4 if the Tle was generated using the new SGP4-XP model. Until the source code
14228
- * is released, there is no way to support that format in JavaScript or TypeScript.
14245
+ * A value of 4 indicates the SGP4-XP model. Until that source code is released there is no way to support that
14246
+ * format in JavaScript or TypeScript, so it is rejected explicitly. Any other value is treated as malformed.
14229
14247
  * @example 0
14230
14248
  * @param tleLine1 The first line of the Tle to parse.
14231
- * @returns The ephemeris type.
14249
+ * @returns The ephemeris type (0 or 1).
14232
14250
  */
14233
14251
  static ephemerisType(tleLine1) {
14234
14252
  const ephemerisType = parseInt(tleLine1.substring(_Tle.ephemerisType_.start, _Tle.ephemerisType_.stop));
14235
- if (ephemerisType !== 0 && ephemerisType !== 4) {
14236
- throw new ParseError(`Invalid ephemeris type: ${ephemerisType}`, "TLE");
14237
- }
14238
14253
  if (ephemerisType === 4) {
14239
14254
  throw new ParseError("SGP4-XP ephemeris type is not supported", "TLE");
14240
14255
  }
14256
+ if (ephemerisType !== 0 && ephemerisType !== 1) {
14257
+ throw new ParseError(`Invalid ephemeris type: ${ephemerisType}`, "TLE");
14258
+ }
14241
14259
  return ephemerisType;
14242
14260
  }
14243
14261
  /**
@@ -14468,6 +14486,9 @@ ${this.line2}`;
14468
14486
  */
14469
14487
  static satNum(tleLine) {
14470
14488
  const satNumStr = tleLine.substring(_Tle.satNum_.start, _Tle.satNum_.stop);
14489
+ if (satNumStr.trim().length === 0) {
14490
+ return NaN;
14491
+ }
14471
14492
  const sixDigitSatNum = _Tle.convertA5to6Digit(satNumStr);
14472
14493
  return parseInt(sixDigitSatNum);
14473
14494
  }
@@ -14558,12 +14579,13 @@ ${this.line2}`;
14558
14579
  static parse(tleLine1, tleLine2) {
14559
14580
  const line1 = _Tle.parseLine1(tleLine1);
14560
14581
  const line2 = _Tle.parseLine2(tleLine2);
14561
- if (line1.satNum !== line2.satNum) {
14582
+ const isVimpel = line1.classification === "V";
14583
+ if (!isVimpel && line1.satNum !== line2.satNum) {
14562
14584
  console.info("Line 1 satNum:", line1.satNum);
14563
14585
  console.info("Line 2 satNum:", line2.satNum);
14564
14586
  throw new ParseError("Satellite numbers do not match between TLE lines", "TLE");
14565
14587
  }
14566
- if (line1.satNumRaw !== line2.satNumRaw) {
14588
+ if (!isVimpel && line1.satNumRaw !== line2.satNumRaw) {
14567
14589
  console.info("Line 1 satNumRaw:", line1.satNumRaw);
14568
14590
  console.info("Line 2 satNumRaw:", line2.satNumRaw);
14569
14591
  throw new ParseError("Raw satellite numbers do not match between TLE lines", "TLE");
@@ -14604,10 +14626,11 @@ ${this.line2}`;
14604
14626
  static parseAll(tleLine1, tleLine2) {
14605
14627
  const line1 = _Tle.parseLine1(tleLine1);
14606
14628
  const line2 = _Tle.parseLine2(tleLine2);
14607
- if (line1.satNum !== line2.satNum) {
14629
+ const isVimpel = line1.classification === "V";
14630
+ if (!isVimpel && line1.satNum !== line2.satNum) {
14608
14631
  throw new ParseError("Satellite numbers do not match between TLE lines", "TLE");
14609
14632
  }
14610
- if (line1.satNumRaw !== line2.satNumRaw) {
14633
+ if (!isVimpel && line1.satNumRaw !== line2.satNumRaw) {
14611
14634
  throw new ParseError("Raw satellite numbers do not match between TLE lines", "TLE");
14612
14635
  }
14613
14636
  if (line1.lineNumber1 !== 1) {
@@ -14963,9 +14986,6 @@ var SolarRadiationPressure = class _SolarRadiationPressure extends Force {
14963
14986
  this.area = area;
14964
14987
  this.reflectCoeff = reflectCoeff;
14965
14988
  }
14966
- mass;
14967
- area;
14968
- reflectCoeff;
14969
14989
  // / Solar pressure _(N/m²)_;
14970
14990
  static _kRef = 456e-8 * KM_PER_AU ** 2;
14971
14991
  acceleration(state) {
@@ -15348,8 +15368,6 @@ var ThirdBodyGravity = class _ThirdBodyGravity {
15348
15368
  this.moon = moon;
15349
15369
  this.sun = sun;
15350
15370
  }
15351
- moon;
15352
- sun;
15353
15371
  static moonGravity_(state) {
15354
15372
  const rMoon = Moon.eci(state.epoch.toDateTime());
15355
15373
  const aNum = rMoon.subtract(state.position);
@@ -15452,13 +15470,6 @@ var RAE = class _RAE {
15452
15470
  this.azRateRad = azRateRad;
15453
15471
  this.elRateRad = elRateRad;
15454
15472
  }
15455
- epoch;
15456
- rng;
15457
- azRad;
15458
- elRad;
15459
- rngRate;
15460
- azRateRad;
15461
- elRateRad;
15462
15473
  // / Create a new [Razel] object, using degrees for the angular values.
15463
15474
  static fromDegrees(epoch, range, azimuth, elevation, rangeRate, azimuthRate, elevationRate) {
15464
15475
  const azimuthRateRad = azimuthRate ? azimuthRate * DEG2RAD : void 0;
@@ -15927,9 +15938,6 @@ var RungeKuttaAdaptive = class _RungeKuttaAdaptive extends Propagator {
15927
15938
  this._cacheState = this.initState_;
15928
15939
  this.tolerance_ = Math.max(_RungeKuttaAdaptive._minTolerance, Math.abs(tolerance_));
15929
15940
  }
15930
- initState_;
15931
- forceModel_;
15932
- tolerance_;
15933
15941
  // / Initial state vector.
15934
15942
  _cacheState;
15935
15943
  _checkpoints = [];
@@ -16225,11 +16233,6 @@ var RungeKutta4Propagator = class extends Propagator {
16225
16233
  this.checkpoints_ = checkpoints_;
16226
16234
  this.stepSize_ = Math.abs(stepSize_);
16227
16235
  }
16228
- initState_;
16229
- forceModel_;
16230
- stepSize_;
16231
- cacheState_;
16232
- checkpoints_;
16233
16236
  // / Set the integrator step size to the provided number of [seconds].
16234
16237
  setStepSize(seconds) {
16235
16238
  this.stepSize_ = Math.abs(seconds);
@@ -16558,7 +16561,6 @@ var Sgp4Propagator = class extends Propagator {
16558
16561
  this.tle_ = tle_;
16559
16562
  this.cacheState_ = tle_.state.toJ2000();
16560
16563
  }
16561
- tle_;
16562
16564
  cacheState_;
16563
16565
  checkpoints_ = [];
16564
16566
  /**
@@ -16851,15 +16853,30 @@ var Satellite = class _Satellite extends SpaceObject {
16851
16853
  return objectId;
16852
16854
  }
16853
16855
  /**
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`.
16856
+ * Normalizes {@link sccNum} to the display-canonical numeric form and derives
16857
+ * {@link sccNum5} and {@link sccNum6}. The class invariant is that
16858
+ * `Satellite.sccNum` is always numeric — never an alpha-5 string. Alpha-5
16859
+ * inputs ("T0001") are converted to their 6-digit numeric equivalent
16860
+ * ("270001"); the alpha-5 form is preserved on {@link sccNum5}.
16861
+ *
16862
+ * Extended (7+ digit) IDs that exceed the alpha-5 capacity (max 339 999)
16863
+ * leave sccNum5/sccNum6 set to `null`.
16864
+ *
16865
+ * Invalid input (empty string, malformed token) is passed through unchanged
16866
+ * so callers can store placeholder sccNums on notional / debris stubs.
16857
16867
  */
16858
16868
  assignAlpha5Forms_() {
16869
+ try {
16870
+ this.sccNum = Tle.convertA5to6Digit(this.sccNum);
16871
+ } catch {
16872
+ }
16873
+ if (/^0+\d/u.test(this.sccNum)) {
16874
+ this.sccNum = this.sccNum.replace(/^0+/u, "");
16875
+ }
16859
16876
  const kind = Tle.classifySatNum(this.sccNum);
16860
- if (kind === "numeric5" || kind === "alpha5" || kind === "numeric6") {
16877
+ if (kind === "numeric5" || kind === "numeric6") {
16861
16878
  this.sccNum5 = Tle.convert6DigitToA5(this.sccNum);
16862
- this.sccNum6 = Tle.convertA5to6Digit(this.sccNum5);
16879
+ this.sccNum6 = this.sccNum;
16863
16880
  } else {
16864
16881
  this.sccNum5 = null;
16865
16882
  this.sccNum6 = null;
@@ -19301,13 +19318,6 @@ var RadecGeocentric = class _RadecGeocentric {
19301
19318
  this.declinationRate = declinationRate;
19302
19319
  this.rangeRate = rangeRate;
19303
19320
  }
19304
- epoch;
19305
- rightAscension;
19306
- declination;
19307
- range;
19308
- rightAscensionRate;
19309
- declinationRate;
19310
- rangeRate;
19311
19321
  /**
19312
19322
  * Creates a RadecGeocentric object from the given parameters in degrees.
19313
19323
  * @param epoch - The epoch in UTC.
@@ -19450,13 +19460,6 @@ var RadecTopocentric = class _RadecTopocentric {
19450
19460
  this.declinationRate = declinationRate;
19451
19461
  this.rangeRate = rangeRate;
19452
19462
  }
19453
- epoch;
19454
- rightAscension;
19455
- declination;
19456
- range;
19457
- rightAscensionRate;
19458
- declinationRate;
19459
- rangeRate;
19460
19463
  /**
19461
19464
  * Create a new RadecTopocentric object, using degrees for the angular values.
19462
19465
  * @param epoch UTC epoch.
@@ -20014,8 +20017,6 @@ var RkCheckpoint = class {
20014
20017
  this.cacheState = cacheState;
20015
20018
  this.stepSize = stepSize;
20016
20019
  }
20017
- cacheState;
20018
- stepSize;
20019
20020
  };
20020
20021
 
20021
20022
  // src/propagator/RkResult.ts
@@ -20026,9 +20027,6 @@ var RkResult = class {
20026
20027
  this.error = error;
20027
20028
  this.newStep = newStep;
20028
20029
  }
20029
- state;
20030
- error;
20031
- newStep;
20032
20030
  };
20033
20031
 
20034
20032
  // src/covariance/StateCovariance.ts
@@ -20049,8 +20047,6 @@ var StateCovariance = class _StateCovariance {
20049
20047
  this.matrix = matrix;
20050
20048
  this.frame = frame;
20051
20049
  }
20052
- matrix;
20053
- frame;
20054
20050
  // / Create a new [StateCovariance] object from 1-sigma values.
20055
20051
  static fromSigmas(sigmas, frame) {
20056
20052
  const n = sigmas.length;
@@ -20081,8 +20077,6 @@ var PropagatorPairs = class {
20081
20077
  this.posStep_ = posStep_;
20082
20078
  this.velStep_ = velStep_;
20083
20079
  }
20084
- posStep_;
20085
- velStep_;
20086
20080
  _high = Array(6).fill(null);
20087
20081
  _low = Array(6).fill(null);
20088
20082
  set(index, high, low) {
@@ -20116,9 +20110,6 @@ var BatchLeastSquaresResult = class {
20116
20110
  this.covariance = covariance2;
20117
20111
  this.rms = rms;
20118
20112
  }
20119
- state;
20120
- covariance;
20121
- rms;
20122
20113
  };
20123
20114
 
20124
20115
  // src/orbit-determination/BatchLeastSquaresOD.ts
@@ -20149,12 +20140,6 @@ var BatchLeastSquaresOD = class _BatchLeastSquaresOD {
20149
20140
  this.propagator_ = new RungeKutta89Propagator(this.apriori_, this.forceModel_);
20150
20141
  this.nominal_ = this.propagator_.propagate(this.start_);
20151
20142
  }
20152
- observations_;
20153
- apriori_;
20154
- forceModel_;
20155
- posStep_;
20156
- velStep_;
20157
- fastDerivatives_;
20158
20143
  /** Propagator pair cache, for generating observation Jacobians. */
20159
20144
  propPairs_;
20160
20145
  /** Nominal state propagator. */
@@ -20255,7 +20240,6 @@ var GibbsIOD = class _GibbsIOD {
20255
20240
  constructor(mu = Earth.mu) {
20256
20241
  this.mu = mu;
20257
20242
  }
20258
- mu;
20259
20243
  /** Abort solve if position plane exceeds this value. */
20260
20244
  static coplanarThreshold_ = 5 * DEG2RAD;
20261
20245
  /**
@@ -20314,7 +20298,6 @@ var HerrickGibbsIOD = class {
20314
20298
  constructor(mu = Earth.mu) {
20315
20299
  this.mu = mu;
20316
20300
  }
20317
- mu;
20318
20301
  // / Attempt to create a state estimate from three inertial position vectors.
20319
20302
  solve(r1, t1, r2, t2, r3, t3) {
20320
20303
  const dt31 = t3.difference(t1);
@@ -20575,7 +20558,6 @@ var LambertIOD = class _LambertIOD {
20575
20558
  constructor(mu = Earth.mu) {
20576
20559
  this.mu = mu;
20577
20560
  }
20578
- mu;
20579
20561
  /**
20580
20562
  * Try to guess the short path argument given an [interceptor] and
20581
20563
  * [target] state.
@@ -21263,11 +21245,6 @@ var LevenbergMarquardtResult = class {
21263
21245
  this.iterations = iterations;
21264
21246
  this.converged = converged;
21265
21247
  }
21266
- state;
21267
- covariance;
21268
- rms;
21269
- iterations;
21270
- converged;
21271
21248
  };
21272
21249
 
21273
21250
  // src/orbit-determination/LevenbergMarquardtOD.ts
@@ -21298,12 +21275,6 @@ var LevenbergMarquardtOD = class _LevenbergMarquardtOD {
21298
21275
  const propagator = new RungeKutta89Propagator(this.apriori_, this.forceModel_);
21299
21276
  this.nominal_ = propagator.propagate(this.start_);
21300
21277
  }
21301
- observations_;
21302
- apriori_;
21303
- forceModel_;
21304
- posStep_;
21305
- velStep_;
21306
- fastDerivatives_;
21307
21278
  /** Propagator pair cache, for generating observation Jacobians. */
21308
21279
  propPairs_;
21309
21280
  /** State estimate during solve. */
@@ -21462,8 +21433,6 @@ var SimplexEntry = class _SimplexEntry {
21462
21433
  this.x_ = new Vector(points);
21463
21434
  this.score = this.f_(points);
21464
21435
  }
21465
- f_;
21466
- points;
21467
21436
  /**
21468
21437
  * The cost function score at this vertex.
21469
21438
  *
@@ -21796,6 +21765,82 @@ var ModifiedGoodingIOD = class {
21796
21765
  }
21797
21766
  };
21798
21767
 
21768
+ // src/orbit-determination/Rv2Tle.ts
21769
+ var angleDiff_ = (a, b) => {
21770
+ let diff = (a - b) % TAU;
21771
+ if (diff > Math.PI) {
21772
+ diff -= TAU;
21773
+ } else if (diff < -Math.PI) {
21774
+ diff += TAU;
21775
+ }
21776
+ return diff;
21777
+ };
21778
+ var wrapTau_ = (angle) => {
21779
+ let wrapped = angle % TAU;
21780
+ if (wrapped < 0) {
21781
+ wrapped += TAU;
21782
+ }
21783
+ return wrapped;
21784
+ };
21785
+ var toElements_ = (epoch, position, velocity) => new J20002(
21786
+ epoch,
21787
+ new Vector3D(position.x, position.y, position.z),
21788
+ new Vector3D(velocity.x, velocity.y, velocity.z)
21789
+ ).toClassicalElements();
21790
+ var rv2tle = (epoch, position, velocity, options = {}) => {
21791
+ const maxIterations = options.maxIterations ?? 15;
21792
+ const toleranceKm = options.toleranceKm ?? 1e-4;
21793
+ const epochUtc = EpochUTC.fromDateTime(epoch);
21794
+ const target = toElements_(epochUtc, position, velocity);
21795
+ let mean2 = new ClassicalElements({
21796
+ epoch: epochUtc,
21797
+ semimajorAxis: target.semimajorAxis,
21798
+ eccentricity: target.eccentricity,
21799
+ inclination: target.inclination,
21800
+ rightAscension: target.rightAscension,
21801
+ argPerigee: target.argPerigee,
21802
+ trueAnomaly: target.trueAnomaly
21803
+ });
21804
+ let best = null;
21805
+ for (let iteration = 1; iteration <= maxIterations; iteration++) {
21806
+ let tle;
21807
+ let sv;
21808
+ try {
21809
+ tle = Tle.fromClassicalElements(mean2);
21810
+ const tsinceMin = (epoch.getTime() - tle.epoch.toDateTime().getTime()) / 6e4;
21811
+ sv = Sgp4.propagate(Sgp4.createSatrec(tle.line1, tle.line2), tsinceMin);
21812
+ } catch {
21813
+ return best;
21814
+ }
21815
+ if (!sv.position || typeof sv.position === "boolean" || !sv.velocity || typeof sv.velocity === "boolean") {
21816
+ return best;
21817
+ }
21818
+ const achievedPos = sv.position;
21819
+ const achievedVel = sv.velocity;
21820
+ const dx = achievedPos.x - position.x;
21821
+ const dy = achievedPos.y - position.y;
21822
+ const dz = achievedPos.z - position.z;
21823
+ const positionErrorKm = Math.sqrt(dx * dx + dy * dy + dz * dz);
21824
+ if (!best || positionErrorKm < best.positionErrorKm) {
21825
+ best = { tle1: tle.line1, tle2: tle.line2, positionErrorKm, iterations: iteration };
21826
+ }
21827
+ if (positionErrorKm < toleranceKm) {
21828
+ break;
21829
+ }
21830
+ const achieved = toElements_(epochUtc, achievedPos, achievedVel);
21831
+ mean2 = new ClassicalElements({
21832
+ epoch: epochUtc,
21833
+ semimajorAxis: mean2.semimajorAxis + (target.semimajorAxis - achieved.semimajorAxis),
21834
+ eccentricity: Math.min(Math.max(mean2.eccentricity + (target.eccentricity - achieved.eccentricity), 0), 0.999),
21835
+ inclination: Math.min(Math.max(mean2.inclination + angleDiff_(target.inclination, achieved.inclination), 0), Math.PI),
21836
+ rightAscension: wrapTau_(mean2.rightAscension + angleDiff_(target.rightAscension, achieved.rightAscension)),
21837
+ argPerigee: wrapTau_(mean2.argPerigee + angleDiff_(target.argPerigee, achieved.argPerigee)),
21838
+ trueAnomaly: wrapTau_(mean2.trueAnomaly + angleDiff_(target.trueAnomaly, achieved.trueAnomaly))
21839
+ });
21840
+ }
21841
+ return best;
21842
+ };
21843
+
21799
21844
  // src/covariance/CovarianceSample.ts
21800
21845
  var CovarianceSample = class {
21801
21846
  origin_;
@@ -21988,6 +22033,19 @@ var CovarianceSample = class {
21988
22033
  }
21989
22034
  };
21990
22035
 
22036
+ // src/covariance/displayRadii.ts
22037
+ function scaleAndClampRicSigmas(sigmas, confidence, caps) {
22038
+ const { radial, inTrack, crossTrack } = sigmas;
22039
+ if (![radial, inTrack, crossTrack].every((v) => Number.isFinite(v) && v >= 0)) {
22040
+ return null;
22041
+ }
22042
+ return {
22043
+ radial: Math.min(radial * confidence, caps.radial),
22044
+ inTrack: Math.min(inTrack * confidence, caps.inTrack),
22045
+ crossTrack: Math.min(crossTrack * confidence, caps.crossTrack)
22046
+ };
22047
+ }
22048
+
21991
22049
  // src/conjunction/ConjunctionAssessment.ts
21992
22050
  var ConjunctionAssessment = class {
21993
22051
  constructor(primary, secondary) {
@@ -21996,8 +22054,6 @@ var ConjunctionAssessment = class {
21996
22054
  this.primaryProp = this.createPropagator(primary, false);
21997
22055
  this.secondaryProp = this.createPropagator(secondary, false);
21998
22056
  }
21999
- primary;
22000
- secondary;
22001
22057
  primaryProp;
22002
22058
  secondaryProp;
22003
22059
  primaryCovSample;
@@ -23443,9 +23499,6 @@ var ObservationRadar = class _ObservationRadar extends Observation {
23443
23499
  this.observation = observation;
23444
23500
  this.noise_ = noise_;
23445
23501
  }
23446
- site_;
23447
- observation;
23448
- noise_;
23449
23502
  // / Default noise matrix.
23450
23503
  static defaultNoise = _ObservationRadar.noiseFromSigmas(0.32, 0.015 * DEG2RAD, 0.015 * DEG2RAD);
23451
23504
  get epoch() {
@@ -23935,9 +23988,6 @@ var ObservationOptical = class _ObservationOptical extends Observation {
23935
23988
  this.observation = observation;
23936
23989
  this.noise_ = noise_;
23937
23990
  }
23938
- site_;
23939
- observation;
23940
- noise_;
23941
23991
  // / Inertial site location.
23942
23992
  get site() {
23943
23993
  return this.site_;
@@ -27231,11 +27281,6 @@ var ChebyshevCoefficients = class _ChebyshevCoefficients {
27231
27281
  this.cyd_ = _ChebyshevCoefficients._derivative(a, b, cy_);
27232
27282
  this.czd_ = _ChebyshevCoefficients._derivative(a, b, cz_);
27233
27283
  }
27234
- a;
27235
- b;
27236
- cx_;
27237
- cy_;
27238
- cz_;
27239
27284
  cxd_;
27240
27285
  cyd_;
27241
27286
  czd_;
@@ -27757,11 +27802,6 @@ var TwoBurnOrbitTransfer = class _TwoBurnOrbitTransfer {
27757
27802
  this.vTransB = vTransB;
27758
27803
  this.tTrans = tTrans;
27759
27804
  }
27760
- vInit;
27761
- vFinal;
27762
- vTransA;
27763
- vTransB;
27764
- tTrans;
27765
27805
  /**
27766
27806
  * Calculates the parameters for a Hohmann transfer orbit between two circular orbits.
27767
27807
  * @param rInit The initial radius of the orbit. (km)
@@ -27814,7 +27854,6 @@ var ChebyshevCompressor = class _ChebyshevCompressor {
27814
27854
  constructor(interpolator_) {
27815
27855
  this.interpolator_ = interpolator_;
27816
27856
  }
27817
- interpolator_;
27818
27857
  /** Returns the cosine of π times x. */
27819
27858
  static cosPi_(x) {
27820
27859
  return Math.cos(Math.PI * x);
@@ -28055,8 +28094,6 @@ var SimpleLinearRegression = class _SimpleLinearRegression {
28055
28094
  this.ys = ys;
28056
28095
  this.update();
28057
28096
  }
28058
- xs;
28059
- ys;
28060
28097
  /** Line slope (m in y = mx + b). */
28061
28098
  slope_ = 0;
28062
28099
  /** Y-axis intercept (b in y = mx + b). */
@@ -29811,8 +29848,20 @@ var OrbitFinder = class _OrbitFinder {
29811
29848
  this.debug_(`Found perigee at altitude ${perigeeParams.altitude} km`);
29812
29849
  return perigeeParams;
29813
29850
  }
29851
+ /**
29852
+ * Returns the 5-char satnum to embed in the synthesized TLEs.
29853
+ *
29854
+ * Why not {@link Satellite.sccNum}? For extended (7+ digit) IDs sccNum is
29855
+ * the full 9-digit canonical value, which would push the TLE past 69 chars
29856
+ * and break Sgp4.createSatrec. The input tle1 always has a valid 5-char
29857
+ * satnum at columns 2-6, and SGP4 itself doesn't care what value lives
29858
+ * there as long as line 1 and line 2 agree — so use that.
29859
+ */
29860
+ tleSatNum_() {
29861
+ return this.sat_.tle1.substring(2, 7);
29862
+ }
29814
29863
  generateTle1_() {
29815
- return `1 ${this.sat_.sccNum}U ${this.sat_.tle1.substring(9, 17)} ${this.sat_.tle1.substring(18, 32)}${this.sat_.tle1.substring(32, 71)}`;
29864
+ return `1 ${this.tleSatNum_()}U ${this.sat_.tle1.substring(9, 17)} ${this.sat_.tle1.substring(18, 32)}${this.sat_.tle1.substring(32, 71)}`;
29816
29865
  }
29817
29866
  generateTle2_(newParams) {
29818
29867
  const mergedParams = {
@@ -29827,7 +29876,7 @@ var OrbitFinder = class _OrbitFinder {
29827
29876
  const argPer = mergedParams.argOfPerigee.toFixed(4).padStart(8, "0");
29828
29877
  const meanA = mergedParams.meanAnomaly.toFixed(4).padStart(8, "0");
29829
29878
  const meanMo = this.sat_.tle2.substring(52, 63);
29830
- return `2 ${this.sat_.sccNum} ${inc} ${raan} ${ecc} ${argPer} ${meanA} ${meanMo} 10`;
29879
+ return `2 ${this.tleSatNum_()} ${inc} ${raan} ${ecc} ${argPer} ${meanA} ${meanMo} 10`;
29831
29880
  }
29832
29881
  };
29833
29882
 
@@ -30187,6 +30236,33 @@ var RepeatGroundTrack = class _RepeatGroundTrack {
30187
30236
  * You should have received a copy of the GNU Affero General Public License along with
30188
30237
  * Orbital Object ToolKit. If not, see <http://www.gnu.org/licenses/>.
30189
30238
  */
30239
+ /**
30240
+ * @author Theodore Kruczek.
30241
+ * @description Orbital Object ToolKit (ootk) is a collection of tools for working
30242
+ * with satellites and other orbital objects.
30243
+ *
30244
+ * @license MIT License
30245
+ *
30246
+ * @Copyright (c) 2025 Theodore Kruczek
30247
+ *
30248
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
30249
+ * of this software and associated documentation files (the "Software"), to deal
30250
+ * in the Software without restriction, including without limitation the rights
30251
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
30252
+ * copies of the Software, and to permit persons to whom the Software is
30253
+ * furnished to do so, subject to the following conditions:
30254
+ *
30255
+ * The above copyright notice and this permission notice shall be included in all
30256
+ * copies or substantial portions of the Software.
30257
+ *
30258
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30259
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30260
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30261
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30262
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30263
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30264
+ * SOFTWARE.
30265
+ */
30190
30266
  /**
30191
30267
  * @author Theodore Kruczek
30192
30268
  * @description Orbital Object ToolKit (ootk) is a collection of tools for working
@@ -30416,6 +30492,8 @@ exports.Quaternion = Quaternion;
30416
30492
  exports.RAD2DEG = RAD2DEG;
30417
30493
  exports.RADIUS_OF_EARTH = RADIUS_OF_EARTH;
30418
30494
  exports.RAE = RAE;
30495
+ exports.RCS_VMAG_ESTIMATE_MAX = RCS_VMAG_ESTIMATE_MAX;
30496
+ exports.RCS_VMAG_ESTIMATE_MIN = RCS_VMAG_ESTIMATE_MIN;
30419
30497
  exports.RIC = RIC;
30420
30498
  exports.RadarSensor = RadarSensor;
30421
30499
  exports.RadecGeocentric = RadecGeocentric;
@@ -30493,6 +30571,7 @@ exports.calcIncFromAz = calcIncFromAz;
30493
30571
  exports.calcInertAz = calcInertAz;
30494
30572
  exports.calculateFspl = calculateFspl;
30495
30573
  exports.calculatePropagationDelay = calculatePropagationDelay;
30574
+ exports.cappedScreeningCovarianceFromTle = cappedScreeningCovarianceFromTle;
30496
30575
  exports.clamp = clamp;
30497
30576
  exports.concat = concat;
30498
30577
  exports.copySign = copySign;
@@ -30517,6 +30596,7 @@ exports.eci2lla = eci2lla;
30517
30596
  exports.eci2rae = eci2rae;
30518
30597
  exports.enu2rf = enu2rf;
30519
30598
  exports.estimateRcs = estimateRcs;
30599
+ exports.estimateVmagFromRcs = estimateVmagFromRcs;
30520
30600
  exports.evalPoly = evalPoly;
30521
30601
  exports.factorial = factorial;
30522
30602
  exports.gamma = gamma;
@@ -30557,6 +30637,8 @@ exports.rae2raeOffBoresight = rae2raeOffBoresight;
30557
30637
  exports.rae2ruv = rae2ruv;
30558
30638
  exports.rae2sez = rae2sez;
30559
30639
  exports.relativeVelocity = relativeVelocity;
30640
+ exports.rv2tle = rv2tle;
30641
+ exports.scaleAndClampRicSigmas = scaleAndClampRicSigmas;
30560
30642
  exports.sec2day = sec2day;
30561
30643
  exports.sec2deg = sec2deg;
30562
30644
  exports.sec2min = sec2min;