ootk 6.0.1 → 6.0.3
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 +204 -31
- package/dist/main.d.cts +71 -22
- package/dist/main.d.ts +71 -22
- package/dist/main.js +204 -31
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -9849,7 +9849,7 @@ var FormatTle = class _FormatTle {
|
|
|
9849
9849
|
const { inc, meanmo, rasc, argPe, meana, ecen, epochyr, epochday, intl } = tleParams;
|
|
9850
9850
|
const scc = Tle.convert6DigitToA5(tleParams.scc);
|
|
9851
9851
|
const epochYrStr = String(epochyr).padStart(2, "0");
|
|
9852
|
-
const epochdayStr =
|
|
9852
|
+
const epochdayStr = Number(epochday).toFixed(8).padStart(12, "0");
|
|
9853
9853
|
const incStr = _FormatTle.inclination(inc);
|
|
9854
9854
|
const meanmoStr = _FormatTle.meanMotion(meanmo);
|
|
9855
9855
|
const rascStr = _FormatTle.rightAscension(rasc);
|
|
@@ -9857,13 +9857,23 @@ var FormatTle = class _FormatTle {
|
|
|
9857
9857
|
const meanaStr = _FormatTle.meanAnomaly(meana);
|
|
9858
9858
|
const ecenStr = _FormatTle.eccentricity(ecen);
|
|
9859
9859
|
const intlStr = intl.padEnd(8, " ");
|
|
9860
|
-
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9860
|
+
const classification = tleParams.classification ?? "U";
|
|
9861
|
+
const elementSetNo = (tleParams.elementSetNo ?? 999).toString().padStart(4, " ");
|
|
9862
|
+
const ephemerisType = (tleParams.ephemerisType ?? 0).toString();
|
|
9863
|
+
const revAtEpoch = (tleParams.revAtEpoch ?? 0).toString().padStart(5, " ");
|
|
9864
|
+
let TLE1Ending;
|
|
9865
|
+
if (tleParams.sat) {
|
|
9866
|
+
TLE1Ending = tleParams.sat.tle1.substring(32, 71);
|
|
9867
|
+
} else {
|
|
9868
|
+
const mmDot = _FormatTle.formatMeanMotionDot(tleParams.meanMotionDot ?? 0);
|
|
9869
|
+
const mmDdot = _FormatTle.formatTleExponential(tleParams.meanMotionDdot ?? 0);
|
|
9870
|
+
const bstarStr = _FormatTle.formatTleExponential(tleParams.bstar ?? 0);
|
|
9871
|
+
TLE1Ending = ` ${mmDot} ${mmDdot} ${bstarStr} ${ephemerisType} ${elementSetNo}0`;
|
|
9872
|
+
}
|
|
9873
|
+
const tle1Pre = `1 ${scc}${classification} ${intlStr} ${epochYrStr}${epochdayStr}${TLE1Ending}`;
|
|
9874
|
+
const tle1 = _FormatTle.setCharAt(tle1Pre, 68, _FormatTle.tleChecksum(tle1Pre).toString());
|
|
9875
|
+
const tle2Pre = `2 ${scc} ${incStr} ${rascStr} ${ecenStr} ${argPeStr} ${meanaStr} ${meanmoStr}${revAtEpoch}0`;
|
|
9876
|
+
const tle2 = _FormatTle.setCharAt(tle2Pre, 68, _FormatTle.tleChecksum(tle2Pre).toString());
|
|
9867
9877
|
return { tle1, tle2 };
|
|
9868
9878
|
}
|
|
9869
9879
|
/**
|
|
@@ -9877,7 +9887,7 @@ var FormatTle = class _FormatTle {
|
|
|
9877
9887
|
argPe = argPe.toString();
|
|
9878
9888
|
}
|
|
9879
9889
|
const argPeNum = parseFloat(argPe).toFixed(4);
|
|
9880
|
-
const argPe0 = argPeNum.padStart(8, "
|
|
9890
|
+
const argPe0 = argPeNum.padStart(8, " ");
|
|
9881
9891
|
if (argPe0.length !== 8) {
|
|
9882
9892
|
throw new ValidationError("Argument of perigee must be 8 characters", "argPe", argPe0);
|
|
9883
9893
|
}
|
|
@@ -9891,7 +9901,10 @@ var FormatTle = class _FormatTle {
|
|
|
9891
9901
|
*/
|
|
9892
9902
|
static eccentricity(ecen) {
|
|
9893
9903
|
if (typeof ecen === "number") {
|
|
9894
|
-
|
|
9904
|
+
const ecenStr = ecen.toString();
|
|
9905
|
+
const dotIdx = ecenStr.indexOf(".");
|
|
9906
|
+
const afterDot = dotIdx >= 0 ? ecenStr.substring(dotIdx + 1) : "";
|
|
9907
|
+
ecen = `0.${afterDot.substring(0, 7).padEnd(7, "0")}`;
|
|
9895
9908
|
}
|
|
9896
9909
|
let ecen0 = ecen.padEnd(9, "0");
|
|
9897
9910
|
if (ecen0[1] === ".") {
|
|
@@ -9915,7 +9928,7 @@ var FormatTle = class _FormatTle {
|
|
|
9915
9928
|
inc = inc.toString();
|
|
9916
9929
|
}
|
|
9917
9930
|
const incNum = parseFloat(inc).toFixed(4);
|
|
9918
|
-
const inc0 = incNum.padStart(8, "
|
|
9931
|
+
const inc0 = incNum.padStart(8, " ");
|
|
9919
9932
|
if (inc0.length !== 8) {
|
|
9920
9933
|
throw new ValidationError("Inclination must be 8 characters", "inclination", inc0);
|
|
9921
9934
|
}
|
|
@@ -9932,7 +9945,7 @@ var FormatTle = class _FormatTle {
|
|
|
9932
9945
|
meana = meana.toString();
|
|
9933
9946
|
}
|
|
9934
9947
|
const meanaNum = parseFloat(meana).toFixed(4);
|
|
9935
|
-
const meana0 = meanaNum.padStart(8, "
|
|
9948
|
+
const meana0 = meanaNum.padStart(8, " ");
|
|
9936
9949
|
if (meana0.length !== 8) {
|
|
9937
9950
|
throw new ValidationError("Mean anomaly must be 8 characters", "meanAnomaly", meana0);
|
|
9938
9951
|
}
|
|
@@ -9973,7 +9986,7 @@ var FormatTle = class _FormatTle {
|
|
|
9973
9986
|
rasc = rasc.toString();
|
|
9974
9987
|
}
|
|
9975
9988
|
const rascNum = parseFloat(rasc).toFixed(4);
|
|
9976
|
-
const rasc0 = rascNum.padStart(8, "
|
|
9989
|
+
const rasc0 = rascNum.padStart(8, " ");
|
|
9977
9990
|
if (rasc0.length !== 8) {
|
|
9978
9991
|
throw new ValidationError("Right ascension must be 8 characters", "rightAscension", rasc0);
|
|
9979
9992
|
}
|
|
@@ -9992,6 +10005,61 @@ var FormatTle = class _FormatTle {
|
|
|
9992
10005
|
}
|
|
9993
10006
|
return `${str.substring(0, index)}${chr}${str.substring(index + 1)}`;
|
|
9994
10007
|
}
|
|
10008
|
+
/**
|
|
10009
|
+
* Format mean motion dot (first derivative / 2) for TLE line 1.
|
|
10010
|
+
* Format: sign + ".NNNNNNNN" = 10 chars total.
|
|
10011
|
+
* @param value - Mean motion dot value (rev/day^2)
|
|
10012
|
+
* @returns Formatted 10-character string
|
|
10013
|
+
*/
|
|
10014
|
+
static formatMeanMotionDot(value) {
|
|
10015
|
+
const sign2 = value >= 0 ? " " : "-";
|
|
10016
|
+
return sign2 + Math.abs(value).toFixed(8).substring(1);
|
|
10017
|
+
}
|
|
10018
|
+
/**
|
|
10019
|
+
* Format a value in TLE exponential notation for BSTAR or mean motion ddot.
|
|
10020
|
+
* Format: "sNNNNN±N" (8 chars) where mantissa has implied leading decimal point.
|
|
10021
|
+
* Example: 0.00017507 → " 17507-3" (i.e., .17507 × 10^-3)
|
|
10022
|
+
* @param value - The value to format
|
|
10023
|
+
* @returns Formatted 8-character string
|
|
10024
|
+
*/
|
|
10025
|
+
static formatTleExponential(value) {
|
|
10026
|
+
if (value === 0) {
|
|
10027
|
+
return " 00000+0";
|
|
10028
|
+
}
|
|
10029
|
+
const sign2 = value >= 0 ? " " : "-";
|
|
10030
|
+
const absVal = Math.abs(value);
|
|
10031
|
+
let exponent = Math.floor(Math.log10(absVal)) + 1;
|
|
10032
|
+
let mantissa = absVal / Math.pow(10, exponent);
|
|
10033
|
+
if (mantissa >= 1) {
|
|
10034
|
+
mantissa /= 10;
|
|
10035
|
+
exponent++;
|
|
10036
|
+
}
|
|
10037
|
+
if (mantissa < 0.1 && mantissa > 0) {
|
|
10038
|
+
mantissa *= 10;
|
|
10039
|
+
exponent--;
|
|
10040
|
+
}
|
|
10041
|
+
const mantissaStr = Math.round(mantissa * 1e5).toString().padStart(5, "0");
|
|
10042
|
+
const expSign = exponent >= 0 ? "+" : "-";
|
|
10043
|
+
const expStr = Math.abs(exponent).toString();
|
|
10044
|
+
return sign2 + mantissaStr + expSign + expStr;
|
|
10045
|
+
}
|
|
10046
|
+
/**
|
|
10047
|
+
* Compute TLE line checksum (modulo 10 sum of digits, '-' counts as 1).
|
|
10048
|
+
* @param line - TLE line (first 68 characters are summed)
|
|
10049
|
+
* @returns Checksum digit (0-9)
|
|
10050
|
+
*/
|
|
10051
|
+
static tleChecksum(line) {
|
|
10052
|
+
let sum = 0;
|
|
10053
|
+
for (let i = 0; i < 68 && i < line.length; i++) {
|
|
10054
|
+
const c = line[i];
|
|
10055
|
+
if (c >= "0" && c <= "9") {
|
|
10056
|
+
sum += parseInt(c);
|
|
10057
|
+
} else if (c === "-") {
|
|
10058
|
+
sum += 1;
|
|
10059
|
+
}
|
|
10060
|
+
}
|
|
10061
|
+
return sum % 10;
|
|
10062
|
+
}
|
|
9995
10063
|
};
|
|
9996
10064
|
|
|
9997
10065
|
// src/coordinate/RelativeState.ts
|
|
@@ -13187,13 +13255,28 @@ var ClassicalElements = class _ClassicalElements {
|
|
|
13187
13255
|
const h = pos.cross(vel);
|
|
13188
13256
|
const i = Math.acos(clamp(h.z / h.magnitude(), -1, 1));
|
|
13189
13257
|
const n = Vector3D.zAxis.cross(h);
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13258
|
+
const nMag = n.magnitude();
|
|
13259
|
+
let o;
|
|
13260
|
+
let w;
|
|
13261
|
+
if (nMag < 1e-12) {
|
|
13262
|
+
o = 0;
|
|
13263
|
+
if (e > 1e-12) {
|
|
13264
|
+
w = Math.atan2(eVec.y, eVec.x);
|
|
13265
|
+
if (w < 0) {
|
|
13266
|
+
w = w + TAU;
|
|
13267
|
+
}
|
|
13268
|
+
} else {
|
|
13269
|
+
w = 0;
|
|
13270
|
+
}
|
|
13271
|
+
} else {
|
|
13272
|
+
o = Math.acos(clamp(n.x / nMag, -1, 1));
|
|
13273
|
+
if (n.y < 0) {
|
|
13274
|
+
o = TAU - o;
|
|
13275
|
+
}
|
|
13276
|
+
w = n.angle(eVec);
|
|
13277
|
+
if (eVec.z < 0) {
|
|
13278
|
+
w = TAU - w;
|
|
13279
|
+
}
|
|
13197
13280
|
}
|
|
13198
13281
|
let v = eVec.angle(pos);
|
|
13199
13282
|
if (pos.dot(vel) < 0) {
|
|
@@ -16625,8 +16708,9 @@ var Satellite = class _Satellite extends SpaceObject {
|
|
|
16625
16708
|
this.satrec = Sgp4.createSatrec(tle1, tle2);
|
|
16626
16709
|
}
|
|
16627
16710
|
parseOmmAndUpdateOrbit_(omm) {
|
|
16628
|
-
|
|
16629
|
-
this.
|
|
16711
|
+
const noradStr = String(omm.NORAD_CAT_ID);
|
|
16712
|
+
this.sccNum = noradStr.padStart(5, "0");
|
|
16713
|
+
this.sccNum5 = Tle.convert6DigitToA5(noradStr);
|
|
16630
16714
|
this.sccNum6 = Tle.convertA5to6Digit(this.sccNum5);
|
|
16631
16715
|
this.intlDes = omm.OBJECT_ID;
|
|
16632
16716
|
const YYYY = omm.EPOCH.slice(0, 4);
|
|
@@ -16639,6 +16723,19 @@ var Satellite = class _Satellite extends SpaceObject {
|
|
|
16639
16723
|
const dayOfYear = (epochDateObj - Date.UTC(Number(YYYY), 0, 0)) / 864e5;
|
|
16640
16724
|
const ommParsed = {
|
|
16641
16725
|
...omm,
|
|
16726
|
+
NORAD_CAT_ID: noradStr,
|
|
16727
|
+
MEAN_MOTION: String(omm.MEAN_MOTION),
|
|
16728
|
+
ECCENTRICITY: String(omm.ECCENTRICITY),
|
|
16729
|
+
INCLINATION: String(omm.INCLINATION),
|
|
16730
|
+
RA_OF_ASC_NODE: String(omm.RA_OF_ASC_NODE),
|
|
16731
|
+
ARG_OF_PERICENTER: String(omm.ARG_OF_PERICENTER),
|
|
16732
|
+
MEAN_ANOMALY: String(omm.MEAN_ANOMALY),
|
|
16733
|
+
EPHEMERIS_TYPE: String(omm.EPHEMERIS_TYPE),
|
|
16734
|
+
ELEMENT_SET_NO: String(omm.ELEMENT_SET_NO),
|
|
16735
|
+
REV_AT_EPOCH: String(omm.REV_AT_EPOCH),
|
|
16736
|
+
BSTAR: String(omm.BSTAR),
|
|
16737
|
+
MEAN_MOTION_DOT: String(omm.MEAN_MOTION_DOT),
|
|
16738
|
+
MEAN_MOTION_DDOT: String(omm.MEAN_MOTION_DDOT),
|
|
16642
16739
|
epoch: {
|
|
16643
16740
|
year: Number(YYYY),
|
|
16644
16741
|
month: Number(MM),
|
|
@@ -16651,20 +16748,41 @@ var Satellite = class _Satellite extends SpaceObject {
|
|
|
16651
16748
|
};
|
|
16652
16749
|
this.epochYear = parseInt(YYYY.slice(2, 4));
|
|
16653
16750
|
this.epochDay = dayOfYear;
|
|
16654
|
-
this.meanMoDev1 =
|
|
16655
|
-
this.meanMoDev2 =
|
|
16656
|
-
this.bstar =
|
|
16657
|
-
this.inclination =
|
|
16658
|
-
this.rightAscension =
|
|
16659
|
-
this.eccentricity =
|
|
16660
|
-
this.argOfPerigee =
|
|
16661
|
-
this.meanAnomaly =
|
|
16662
|
-
this.meanMotion =
|
|
16751
|
+
this.meanMoDev1 = Number(omm.MEAN_MOTION_DOT);
|
|
16752
|
+
this.meanMoDev2 = Number(omm.MEAN_MOTION_DDOT);
|
|
16753
|
+
this.bstar = Number(omm.BSTAR);
|
|
16754
|
+
this.inclination = Number(omm.INCLINATION);
|
|
16755
|
+
this.rightAscension = Number(omm.RA_OF_ASC_NODE);
|
|
16756
|
+
this.eccentricity = Number(omm.ECCENTRICITY);
|
|
16757
|
+
this.argOfPerigee = Number(omm.ARG_OF_PERICENTER);
|
|
16758
|
+
this.meanAnomaly = Number(omm.MEAN_ANOMALY);
|
|
16759
|
+
this.meanMotion = Number(omm.MEAN_MOTION);
|
|
16663
16760
|
this.period = 1440 / this.meanMotion;
|
|
16664
16761
|
this.semiMajorAxis = (8681663653e-3 / this.meanMotion) ** (2 / 3);
|
|
16665
16762
|
this.semiMinorAxis = this.semiMajorAxis * Math.sqrt(1 - this.eccentricity ** 2);
|
|
16666
16763
|
this.apogee = this.semiMajorAxis * (1 + this.eccentricity) - 6371;
|
|
16667
16764
|
this.perigee = this.semiMajorAxis * (1 - this.eccentricity) - 6371;
|
|
16765
|
+
const { tle1, tle2 } = FormatTle.createTle({
|
|
16766
|
+
inc: this.inclination,
|
|
16767
|
+
meanmo: this.meanMotion,
|
|
16768
|
+
rasc: this.rightAscension,
|
|
16769
|
+
argPe: this.argOfPerigee,
|
|
16770
|
+
meana: this.meanAnomaly,
|
|
16771
|
+
ecen: this.eccentricity,
|
|
16772
|
+
epochyr: this.epochYear,
|
|
16773
|
+
epochday: this.epochDay,
|
|
16774
|
+
intl: omm.OBJECT_ID,
|
|
16775
|
+
scc: this.sccNum,
|
|
16776
|
+
bstar: this.bstar,
|
|
16777
|
+
meanMotionDot: this.meanMoDev1,
|
|
16778
|
+
meanMotionDdot: this.meanMoDev2,
|
|
16779
|
+
classification: String(omm.CLASSIFICATION_TYPE) || "U",
|
|
16780
|
+
revAtEpoch: Number(omm.REV_AT_EPOCH) || 0,
|
|
16781
|
+
elementSetNo: Number(omm.ELEMENT_SET_NO) || 999,
|
|
16782
|
+
ephemerisType: Number(omm.EPHEMERIS_TYPE) || 0
|
|
16783
|
+
});
|
|
16784
|
+
this.tle1 = tle1;
|
|
16785
|
+
this.tle2 = tle2;
|
|
16668
16786
|
this.satrec = Sgp4.createSatrecFromOmm(ommParsed);
|
|
16669
16787
|
}
|
|
16670
16788
|
// ==================== Type Checking ====================
|
|
@@ -25180,6 +25298,61 @@ var OmmParser = class _OmmParser {
|
|
|
25180
25298
|
const theory = omm.metadata.MEAN_ELEMENT_THEORY.toUpperCase();
|
|
25181
25299
|
return theory === "SGP" || theory === "SGP4" || theory === "SGP4-XP";
|
|
25182
25300
|
}
|
|
25301
|
+
/**
|
|
25302
|
+
* Parse a CelesTrak-style flat JSON OMM object into the structured ParsedOmm format.
|
|
25303
|
+
*
|
|
25304
|
+
* CelesTrak's JSON OMM format is a flat object with all fields at the top level,
|
|
25305
|
+
* omitting metadata fields like CENTER_NAME, REF_FRAME, TIME_SYSTEM, and
|
|
25306
|
+
* MEAN_ELEMENT_THEORY (which are always EARTH/TEME/UTC/SGP4 for GP data).
|
|
25307
|
+
*
|
|
25308
|
+
* @param omm - A flat OMM JSON object from CelesTrak
|
|
25309
|
+
* @returns Parsed OMM structure with inferred metadata
|
|
25310
|
+
*/
|
|
25311
|
+
static parseJson(omm) {
|
|
25312
|
+
const result = {
|
|
25313
|
+
header: {
|
|
25314
|
+
CCSDS_OMM_VERS: "3.0",
|
|
25315
|
+
CREATION_DATE: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25316
|
+
ORIGINATOR: "CelesTrak"
|
|
25317
|
+
},
|
|
25318
|
+
metadata: {
|
|
25319
|
+
OBJECT_NAME: omm.OBJECT_NAME,
|
|
25320
|
+
OBJECT_ID: omm.OBJECT_ID,
|
|
25321
|
+
CENTER_NAME: "EARTH",
|
|
25322
|
+
REF_FRAME: "TEME",
|
|
25323
|
+
TIME_SYSTEM: "UTC",
|
|
25324
|
+
MEAN_ELEMENT_THEORY: "SGP4"
|
|
25325
|
+
},
|
|
25326
|
+
meanElements: {
|
|
25327
|
+
EPOCH: omm.EPOCH,
|
|
25328
|
+
MEAN_MOTION: Number(omm.MEAN_MOTION),
|
|
25329
|
+
ECCENTRICITY: Number(omm.ECCENTRICITY),
|
|
25330
|
+
INCLINATION: Number(omm.INCLINATION),
|
|
25331
|
+
RA_OF_ASC_NODE: Number(omm.RA_OF_ASC_NODE),
|
|
25332
|
+
ARG_OF_PERICENTER: Number(omm.ARG_OF_PERICENTER),
|
|
25333
|
+
MEAN_ANOMALY: Number(omm.MEAN_ANOMALY)
|
|
25334
|
+
},
|
|
25335
|
+
tleParameters: {
|
|
25336
|
+
EPHEMERIS_TYPE: Number(omm.EPHEMERIS_TYPE),
|
|
25337
|
+
CLASSIFICATION_TYPE: String(omm.CLASSIFICATION_TYPE),
|
|
25338
|
+
NORAD_CAT_ID: Number(omm.NORAD_CAT_ID),
|
|
25339
|
+
ELEMENT_SET_NO: Number(omm.ELEMENT_SET_NO),
|
|
25340
|
+
REV_AT_EPOCH: Number(omm.REV_AT_EPOCH),
|
|
25341
|
+
BSTAR: Number(omm.BSTAR),
|
|
25342
|
+
MEAN_MOTION_DOT: Number(omm.MEAN_MOTION_DOT),
|
|
25343
|
+
MEAN_MOTION_DDOT: Number(omm.MEAN_MOTION_DDOT)
|
|
25344
|
+
}
|
|
25345
|
+
};
|
|
25346
|
+
return result;
|
|
25347
|
+
}
|
|
25348
|
+
/**
|
|
25349
|
+
* Parse an array of CelesTrak-style flat JSON OMM objects.
|
|
25350
|
+
* @param ommArray - Array of flat OMM JSON objects from CelesTrak
|
|
25351
|
+
* @returns Array of parsed OMM structures
|
|
25352
|
+
*/
|
|
25353
|
+
static parseJsonArray(ommArray) {
|
|
25354
|
+
return ommArray.map((omm) => _OmmParser.parseJson(omm));
|
|
25355
|
+
}
|
|
25183
25356
|
/**
|
|
25184
25357
|
* Parse all key-value pairs from OMM lines (excluding COMMENT lines).
|
|
25185
25358
|
*/
|
package/dist/main.d.cts
CHANGED
|
@@ -1816,6 +1816,27 @@ declare abstract class FormatTle {
|
|
|
1816
1816
|
* @returns The modified string with the character set at the specified index.
|
|
1817
1817
|
*/
|
|
1818
1818
|
static setCharAt(str: string, index: number, chr: string): string;
|
|
1819
|
+
/**
|
|
1820
|
+
* Format mean motion dot (first derivative / 2) for TLE line 1.
|
|
1821
|
+
* Format: sign + ".NNNNNNNN" = 10 chars total.
|
|
1822
|
+
* @param value - Mean motion dot value (rev/day^2)
|
|
1823
|
+
* @returns Formatted 10-character string
|
|
1824
|
+
*/
|
|
1825
|
+
static formatMeanMotionDot(value: number): string;
|
|
1826
|
+
/**
|
|
1827
|
+
* Format a value in TLE exponential notation for BSTAR or mean motion ddot.
|
|
1828
|
+
* Format: "sNNNNN±N" (8 chars) where mantissa has implied leading decimal point.
|
|
1829
|
+
* Example: 0.00017507 → " 17507-3" (i.e., .17507 × 10^-3)
|
|
1830
|
+
* @param value - The value to format
|
|
1831
|
+
* @returns Formatted 8-character string
|
|
1832
|
+
*/
|
|
1833
|
+
static formatTleExponential(value: number): string;
|
|
1834
|
+
/**
|
|
1835
|
+
* Compute TLE line checksum (modulo 10 sum of digits, '-' counts as 1).
|
|
1836
|
+
* @param line - TLE line (first 68 characters are summed)
|
|
1837
|
+
* @returns Checksum digit (0-9)
|
|
1838
|
+
*/
|
|
1839
|
+
static tleChecksum(line: string): number;
|
|
1819
1840
|
}
|
|
1820
1841
|
|
|
1821
1842
|
/**
|
|
@@ -2780,37 +2801,34 @@ declare class RIC extends RelativeState {
|
|
|
2780
2801
|
}
|
|
2781
2802
|
|
|
2782
2803
|
/**
|
|
2783
|
-
* Represents the data format for orbital elements as provided by the
|
|
2784
|
-
*
|
|
2785
|
-
*
|
|
2804
|
+
* Represents the data format for orbital elements as provided by the OMM system.
|
|
2805
|
+
* Numeric fields accept both string and number to support CelesTrak's JSON format
|
|
2806
|
+
* (which sends numbers as numbers) and other sources that send them as strings.
|
|
2786
2807
|
*/
|
|
2787
2808
|
interface OmmDataFormat {
|
|
2788
2809
|
OBJECT_NAME: string;
|
|
2789
2810
|
OBJECT_ID: string;
|
|
2790
2811
|
/** Date in YYYY-MM-DDTHH:MM:SS.SSSSSS UTC format */
|
|
2791
2812
|
EPOCH: string;
|
|
2792
|
-
MEAN_MOTION: string;
|
|
2793
|
-
ECCENTRICITY: string;
|
|
2794
|
-
INCLINATION: string;
|
|
2795
|
-
RA_OF_ASC_NODE: string;
|
|
2796
|
-
ARG_OF_PERICENTER: string;
|
|
2797
|
-
MEAN_ANOMALY: string;
|
|
2798
|
-
EPHEMERIS_TYPE: string;
|
|
2813
|
+
MEAN_MOTION: string | number;
|
|
2814
|
+
ECCENTRICITY: string | number;
|
|
2815
|
+
INCLINATION: string | number;
|
|
2816
|
+
RA_OF_ASC_NODE: string | number;
|
|
2817
|
+
ARG_OF_PERICENTER: string | number;
|
|
2818
|
+
MEAN_ANOMALY: string | number;
|
|
2819
|
+
EPHEMERIS_TYPE: string | number;
|
|
2799
2820
|
CLASSIFICATION_TYPE: string;
|
|
2800
|
-
NORAD_CAT_ID: string;
|
|
2801
|
-
ELEMENT_SET_NO: string;
|
|
2802
|
-
REV_AT_EPOCH: string;
|
|
2803
|
-
BSTAR: string;
|
|
2804
|
-
MEAN_MOTION_DOT: string;
|
|
2805
|
-
MEAN_MOTION_DDOT: string;
|
|
2821
|
+
NORAD_CAT_ID: string | number;
|
|
2822
|
+
ELEMENT_SET_NO: string | number;
|
|
2823
|
+
REV_AT_EPOCH: string | number;
|
|
2824
|
+
BSTAR: string | number;
|
|
2825
|
+
MEAN_MOTION_DOT: string | number;
|
|
2826
|
+
MEAN_MOTION_DDOT: string | number;
|
|
2806
2827
|
}
|
|
2807
2828
|
/**
|
|
2808
|
-
* Represents the parsed data format for orbital elements as provided by the
|
|
2809
|
-
*
|
|
2810
|
-
*
|
|
2811
|
-
* The `epoch` property is an object that contains the parsed date and time values.
|
|
2812
|
-
* The `doy` property is the day of the year.
|
|
2813
|
-
* The `epoch` property is an object that contains the parsed date and time values.
|
|
2829
|
+
* Represents the parsed data format for orbital elements as provided by the OMM system.
|
|
2830
|
+
* String fields are preserved from the original data; the `epoch` property contains
|
|
2831
|
+
* the parsed date/time values used for SGP4 initialization.
|
|
2814
2832
|
*/
|
|
2815
2833
|
interface OmmParsedDataFormat {
|
|
2816
2834
|
OBJECT_NAME: string;
|
|
@@ -5919,6 +5937,20 @@ type TleParams = {
|
|
|
5919
5937
|
intl: string;
|
|
5920
5938
|
/** alpha 5 satellite number */
|
|
5921
5939
|
scc: string;
|
|
5940
|
+
/** B* drag term (1/Earth radii). Used when `sat` is not provided. */
|
|
5941
|
+
bstar?: number;
|
|
5942
|
+
/** First derivative of mean motion / 2 (rev/day^2). Used when `sat` is not provided. */
|
|
5943
|
+
meanMotionDot?: number;
|
|
5944
|
+
/** Second derivative of mean motion / 6 (rev/day^3). Used when `sat` is not provided. */
|
|
5945
|
+
meanMotionDdot?: number;
|
|
5946
|
+
/** Classification type (default 'U'). Used when `sat` is not provided. */
|
|
5947
|
+
classification?: string;
|
|
5948
|
+
/** Revolution number at epoch. Used when `sat` is not provided. */
|
|
5949
|
+
revAtEpoch?: number;
|
|
5950
|
+
/** Element set number (default 999). Used when `sat` is not provided. */
|
|
5951
|
+
elementSetNo?: number;
|
|
5952
|
+
/** Ephemeris type (default 0). Used when `sat` is not provided. */
|
|
5953
|
+
ephemerisType?: number;
|
|
5922
5954
|
};
|
|
5923
5955
|
type PositionVelocity = {
|
|
5924
5956
|
position: Vector3D<Kilometers>;
|
|
@@ -14078,6 +14110,23 @@ declare class OmmParser {
|
|
|
14078
14110
|
* @returns true if the OMM uses SGP, SGP4, or SGP4-XP mean element theory
|
|
14079
14111
|
*/
|
|
14080
14112
|
static isTleCompatible(omm: ParsedOmm): boolean;
|
|
14113
|
+
/**
|
|
14114
|
+
* Parse a CelesTrak-style flat JSON OMM object into the structured ParsedOmm format.
|
|
14115
|
+
*
|
|
14116
|
+
* CelesTrak's JSON OMM format is a flat object with all fields at the top level,
|
|
14117
|
+
* omitting metadata fields like CENTER_NAME, REF_FRAME, TIME_SYSTEM, and
|
|
14118
|
+
* MEAN_ELEMENT_THEORY (which are always EARTH/TEME/UTC/SGP4 for GP data).
|
|
14119
|
+
*
|
|
14120
|
+
* @param omm - A flat OMM JSON object from CelesTrak
|
|
14121
|
+
* @returns Parsed OMM structure with inferred metadata
|
|
14122
|
+
*/
|
|
14123
|
+
static parseJson(omm: OmmDataFormat): ParsedOmm;
|
|
14124
|
+
/**
|
|
14125
|
+
* Parse an array of CelesTrak-style flat JSON OMM objects.
|
|
14126
|
+
* @param ommArray - Array of flat OMM JSON objects from CelesTrak
|
|
14127
|
+
* @returns Array of parsed OMM structures
|
|
14128
|
+
*/
|
|
14129
|
+
static parseJsonArray(ommArray: OmmDataFormat[]): ParsedOmm[];
|
|
14081
14130
|
/**
|
|
14082
14131
|
* Parse all key-value pairs from OMM lines (excluding COMMENT lines).
|
|
14083
14132
|
*/
|
package/dist/main.d.ts
CHANGED
|
@@ -1816,6 +1816,27 @@ declare abstract class FormatTle {
|
|
|
1816
1816
|
* @returns The modified string with the character set at the specified index.
|
|
1817
1817
|
*/
|
|
1818
1818
|
static setCharAt(str: string, index: number, chr: string): string;
|
|
1819
|
+
/**
|
|
1820
|
+
* Format mean motion dot (first derivative / 2) for TLE line 1.
|
|
1821
|
+
* Format: sign + ".NNNNNNNN" = 10 chars total.
|
|
1822
|
+
* @param value - Mean motion dot value (rev/day^2)
|
|
1823
|
+
* @returns Formatted 10-character string
|
|
1824
|
+
*/
|
|
1825
|
+
static formatMeanMotionDot(value: number): string;
|
|
1826
|
+
/**
|
|
1827
|
+
* Format a value in TLE exponential notation for BSTAR or mean motion ddot.
|
|
1828
|
+
* Format: "sNNNNN±N" (8 chars) where mantissa has implied leading decimal point.
|
|
1829
|
+
* Example: 0.00017507 → " 17507-3" (i.e., .17507 × 10^-3)
|
|
1830
|
+
* @param value - The value to format
|
|
1831
|
+
* @returns Formatted 8-character string
|
|
1832
|
+
*/
|
|
1833
|
+
static formatTleExponential(value: number): string;
|
|
1834
|
+
/**
|
|
1835
|
+
* Compute TLE line checksum (modulo 10 sum of digits, '-' counts as 1).
|
|
1836
|
+
* @param line - TLE line (first 68 characters are summed)
|
|
1837
|
+
* @returns Checksum digit (0-9)
|
|
1838
|
+
*/
|
|
1839
|
+
static tleChecksum(line: string): number;
|
|
1819
1840
|
}
|
|
1820
1841
|
|
|
1821
1842
|
/**
|
|
@@ -2780,37 +2801,34 @@ declare class RIC extends RelativeState {
|
|
|
2780
2801
|
}
|
|
2781
2802
|
|
|
2782
2803
|
/**
|
|
2783
|
-
* Represents the data format for orbital elements as provided by the
|
|
2784
|
-
*
|
|
2785
|
-
*
|
|
2804
|
+
* Represents the data format for orbital elements as provided by the OMM system.
|
|
2805
|
+
* Numeric fields accept both string and number to support CelesTrak's JSON format
|
|
2806
|
+
* (which sends numbers as numbers) and other sources that send them as strings.
|
|
2786
2807
|
*/
|
|
2787
2808
|
interface OmmDataFormat {
|
|
2788
2809
|
OBJECT_NAME: string;
|
|
2789
2810
|
OBJECT_ID: string;
|
|
2790
2811
|
/** Date in YYYY-MM-DDTHH:MM:SS.SSSSSS UTC format */
|
|
2791
2812
|
EPOCH: string;
|
|
2792
|
-
MEAN_MOTION: string;
|
|
2793
|
-
ECCENTRICITY: string;
|
|
2794
|
-
INCLINATION: string;
|
|
2795
|
-
RA_OF_ASC_NODE: string;
|
|
2796
|
-
ARG_OF_PERICENTER: string;
|
|
2797
|
-
MEAN_ANOMALY: string;
|
|
2798
|
-
EPHEMERIS_TYPE: string;
|
|
2813
|
+
MEAN_MOTION: string | number;
|
|
2814
|
+
ECCENTRICITY: string | number;
|
|
2815
|
+
INCLINATION: string | number;
|
|
2816
|
+
RA_OF_ASC_NODE: string | number;
|
|
2817
|
+
ARG_OF_PERICENTER: string | number;
|
|
2818
|
+
MEAN_ANOMALY: string | number;
|
|
2819
|
+
EPHEMERIS_TYPE: string | number;
|
|
2799
2820
|
CLASSIFICATION_TYPE: string;
|
|
2800
|
-
NORAD_CAT_ID: string;
|
|
2801
|
-
ELEMENT_SET_NO: string;
|
|
2802
|
-
REV_AT_EPOCH: string;
|
|
2803
|
-
BSTAR: string;
|
|
2804
|
-
MEAN_MOTION_DOT: string;
|
|
2805
|
-
MEAN_MOTION_DDOT: string;
|
|
2821
|
+
NORAD_CAT_ID: string | number;
|
|
2822
|
+
ELEMENT_SET_NO: string | number;
|
|
2823
|
+
REV_AT_EPOCH: string | number;
|
|
2824
|
+
BSTAR: string | number;
|
|
2825
|
+
MEAN_MOTION_DOT: string | number;
|
|
2826
|
+
MEAN_MOTION_DDOT: string | number;
|
|
2806
2827
|
}
|
|
2807
2828
|
/**
|
|
2808
|
-
* Represents the parsed data format for orbital elements as provided by the
|
|
2809
|
-
*
|
|
2810
|
-
*
|
|
2811
|
-
* The `epoch` property is an object that contains the parsed date and time values.
|
|
2812
|
-
* The `doy` property is the day of the year.
|
|
2813
|
-
* The `epoch` property is an object that contains the parsed date and time values.
|
|
2829
|
+
* Represents the parsed data format for orbital elements as provided by the OMM system.
|
|
2830
|
+
* String fields are preserved from the original data; the `epoch` property contains
|
|
2831
|
+
* the parsed date/time values used for SGP4 initialization.
|
|
2814
2832
|
*/
|
|
2815
2833
|
interface OmmParsedDataFormat {
|
|
2816
2834
|
OBJECT_NAME: string;
|
|
@@ -5919,6 +5937,20 @@ type TleParams = {
|
|
|
5919
5937
|
intl: string;
|
|
5920
5938
|
/** alpha 5 satellite number */
|
|
5921
5939
|
scc: string;
|
|
5940
|
+
/** B* drag term (1/Earth radii). Used when `sat` is not provided. */
|
|
5941
|
+
bstar?: number;
|
|
5942
|
+
/** First derivative of mean motion / 2 (rev/day^2). Used when `sat` is not provided. */
|
|
5943
|
+
meanMotionDot?: number;
|
|
5944
|
+
/** Second derivative of mean motion / 6 (rev/day^3). Used when `sat` is not provided. */
|
|
5945
|
+
meanMotionDdot?: number;
|
|
5946
|
+
/** Classification type (default 'U'). Used when `sat` is not provided. */
|
|
5947
|
+
classification?: string;
|
|
5948
|
+
/** Revolution number at epoch. Used when `sat` is not provided. */
|
|
5949
|
+
revAtEpoch?: number;
|
|
5950
|
+
/** Element set number (default 999). Used when `sat` is not provided. */
|
|
5951
|
+
elementSetNo?: number;
|
|
5952
|
+
/** Ephemeris type (default 0). Used when `sat` is not provided. */
|
|
5953
|
+
ephemerisType?: number;
|
|
5922
5954
|
};
|
|
5923
5955
|
type PositionVelocity = {
|
|
5924
5956
|
position: Vector3D<Kilometers>;
|
|
@@ -14078,6 +14110,23 @@ declare class OmmParser {
|
|
|
14078
14110
|
* @returns true if the OMM uses SGP, SGP4, or SGP4-XP mean element theory
|
|
14079
14111
|
*/
|
|
14080
14112
|
static isTleCompatible(omm: ParsedOmm): boolean;
|
|
14113
|
+
/**
|
|
14114
|
+
* Parse a CelesTrak-style flat JSON OMM object into the structured ParsedOmm format.
|
|
14115
|
+
*
|
|
14116
|
+
* CelesTrak's JSON OMM format is a flat object with all fields at the top level,
|
|
14117
|
+
* omitting metadata fields like CENTER_NAME, REF_FRAME, TIME_SYSTEM, and
|
|
14118
|
+
* MEAN_ELEMENT_THEORY (which are always EARTH/TEME/UTC/SGP4 for GP data).
|
|
14119
|
+
*
|
|
14120
|
+
* @param omm - A flat OMM JSON object from CelesTrak
|
|
14121
|
+
* @returns Parsed OMM structure with inferred metadata
|
|
14122
|
+
*/
|
|
14123
|
+
static parseJson(omm: OmmDataFormat): ParsedOmm;
|
|
14124
|
+
/**
|
|
14125
|
+
* Parse an array of CelesTrak-style flat JSON OMM objects.
|
|
14126
|
+
* @param ommArray - Array of flat OMM JSON objects from CelesTrak
|
|
14127
|
+
* @returns Array of parsed OMM structures
|
|
14128
|
+
*/
|
|
14129
|
+
static parseJsonArray(ommArray: OmmDataFormat[]): ParsedOmm[];
|
|
14081
14130
|
/**
|
|
14082
14131
|
* Parse all key-value pairs from OMM lines (excluding COMMENT lines).
|
|
14083
14132
|
*/
|
package/dist/main.js
CHANGED
|
@@ -9847,7 +9847,7 @@ var FormatTle = class _FormatTle {
|
|
|
9847
9847
|
const { inc, meanmo, rasc, argPe, meana, ecen, epochyr, epochday, intl } = tleParams;
|
|
9848
9848
|
const scc = Tle.convert6DigitToA5(tleParams.scc);
|
|
9849
9849
|
const epochYrStr = String(epochyr).padStart(2, "0");
|
|
9850
|
-
const epochdayStr =
|
|
9850
|
+
const epochdayStr = Number(epochday).toFixed(8).padStart(12, "0");
|
|
9851
9851
|
const incStr = _FormatTle.inclination(inc);
|
|
9852
9852
|
const meanmoStr = _FormatTle.meanMotion(meanmo);
|
|
9853
9853
|
const rascStr = _FormatTle.rightAscension(rasc);
|
|
@@ -9855,13 +9855,23 @@ var FormatTle = class _FormatTle {
|
|
|
9855
9855
|
const meanaStr = _FormatTle.meanAnomaly(meana);
|
|
9856
9856
|
const ecenStr = _FormatTle.eccentricity(ecen);
|
|
9857
9857
|
const intlStr = intl.padEnd(8, " ");
|
|
9858
|
-
|
|
9859
|
-
|
|
9860
|
-
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9864
|
-
|
|
9858
|
+
const classification = tleParams.classification ?? "U";
|
|
9859
|
+
const elementSetNo = (tleParams.elementSetNo ?? 999).toString().padStart(4, " ");
|
|
9860
|
+
const ephemerisType = (tleParams.ephemerisType ?? 0).toString();
|
|
9861
|
+
const revAtEpoch = (tleParams.revAtEpoch ?? 0).toString().padStart(5, " ");
|
|
9862
|
+
let TLE1Ending;
|
|
9863
|
+
if (tleParams.sat) {
|
|
9864
|
+
TLE1Ending = tleParams.sat.tle1.substring(32, 71);
|
|
9865
|
+
} else {
|
|
9866
|
+
const mmDot = _FormatTle.formatMeanMotionDot(tleParams.meanMotionDot ?? 0);
|
|
9867
|
+
const mmDdot = _FormatTle.formatTleExponential(tleParams.meanMotionDdot ?? 0);
|
|
9868
|
+
const bstarStr = _FormatTle.formatTleExponential(tleParams.bstar ?? 0);
|
|
9869
|
+
TLE1Ending = ` ${mmDot} ${mmDdot} ${bstarStr} ${ephemerisType} ${elementSetNo}0`;
|
|
9870
|
+
}
|
|
9871
|
+
const tle1Pre = `1 ${scc}${classification} ${intlStr} ${epochYrStr}${epochdayStr}${TLE1Ending}`;
|
|
9872
|
+
const tle1 = _FormatTle.setCharAt(tle1Pre, 68, _FormatTle.tleChecksum(tle1Pre).toString());
|
|
9873
|
+
const tle2Pre = `2 ${scc} ${incStr} ${rascStr} ${ecenStr} ${argPeStr} ${meanaStr} ${meanmoStr}${revAtEpoch}0`;
|
|
9874
|
+
const tle2 = _FormatTle.setCharAt(tle2Pre, 68, _FormatTle.tleChecksum(tle2Pre).toString());
|
|
9865
9875
|
return { tle1, tle2 };
|
|
9866
9876
|
}
|
|
9867
9877
|
/**
|
|
@@ -9875,7 +9885,7 @@ var FormatTle = class _FormatTle {
|
|
|
9875
9885
|
argPe = argPe.toString();
|
|
9876
9886
|
}
|
|
9877
9887
|
const argPeNum = parseFloat(argPe).toFixed(4);
|
|
9878
|
-
const argPe0 = argPeNum.padStart(8, "
|
|
9888
|
+
const argPe0 = argPeNum.padStart(8, " ");
|
|
9879
9889
|
if (argPe0.length !== 8) {
|
|
9880
9890
|
throw new ValidationError("Argument of perigee must be 8 characters", "argPe", argPe0);
|
|
9881
9891
|
}
|
|
@@ -9889,7 +9899,10 @@ var FormatTle = class _FormatTle {
|
|
|
9889
9899
|
*/
|
|
9890
9900
|
static eccentricity(ecen) {
|
|
9891
9901
|
if (typeof ecen === "number") {
|
|
9892
|
-
|
|
9902
|
+
const ecenStr = ecen.toString();
|
|
9903
|
+
const dotIdx = ecenStr.indexOf(".");
|
|
9904
|
+
const afterDot = dotIdx >= 0 ? ecenStr.substring(dotIdx + 1) : "";
|
|
9905
|
+
ecen = `0.${afterDot.substring(0, 7).padEnd(7, "0")}`;
|
|
9893
9906
|
}
|
|
9894
9907
|
let ecen0 = ecen.padEnd(9, "0");
|
|
9895
9908
|
if (ecen0[1] === ".") {
|
|
@@ -9913,7 +9926,7 @@ var FormatTle = class _FormatTle {
|
|
|
9913
9926
|
inc = inc.toString();
|
|
9914
9927
|
}
|
|
9915
9928
|
const incNum = parseFloat(inc).toFixed(4);
|
|
9916
|
-
const inc0 = incNum.padStart(8, "
|
|
9929
|
+
const inc0 = incNum.padStart(8, " ");
|
|
9917
9930
|
if (inc0.length !== 8) {
|
|
9918
9931
|
throw new ValidationError("Inclination must be 8 characters", "inclination", inc0);
|
|
9919
9932
|
}
|
|
@@ -9930,7 +9943,7 @@ var FormatTle = class _FormatTle {
|
|
|
9930
9943
|
meana = meana.toString();
|
|
9931
9944
|
}
|
|
9932
9945
|
const meanaNum = parseFloat(meana).toFixed(4);
|
|
9933
|
-
const meana0 = meanaNum.padStart(8, "
|
|
9946
|
+
const meana0 = meanaNum.padStart(8, " ");
|
|
9934
9947
|
if (meana0.length !== 8) {
|
|
9935
9948
|
throw new ValidationError("Mean anomaly must be 8 characters", "meanAnomaly", meana0);
|
|
9936
9949
|
}
|
|
@@ -9971,7 +9984,7 @@ var FormatTle = class _FormatTle {
|
|
|
9971
9984
|
rasc = rasc.toString();
|
|
9972
9985
|
}
|
|
9973
9986
|
const rascNum = parseFloat(rasc).toFixed(4);
|
|
9974
|
-
const rasc0 = rascNum.padStart(8, "
|
|
9987
|
+
const rasc0 = rascNum.padStart(8, " ");
|
|
9975
9988
|
if (rasc0.length !== 8) {
|
|
9976
9989
|
throw new ValidationError("Right ascension must be 8 characters", "rightAscension", rasc0);
|
|
9977
9990
|
}
|
|
@@ -9990,6 +10003,61 @@ var FormatTle = class _FormatTle {
|
|
|
9990
10003
|
}
|
|
9991
10004
|
return `${str.substring(0, index)}${chr}${str.substring(index + 1)}`;
|
|
9992
10005
|
}
|
|
10006
|
+
/**
|
|
10007
|
+
* Format mean motion dot (first derivative / 2) for TLE line 1.
|
|
10008
|
+
* Format: sign + ".NNNNNNNN" = 10 chars total.
|
|
10009
|
+
* @param value - Mean motion dot value (rev/day^2)
|
|
10010
|
+
* @returns Formatted 10-character string
|
|
10011
|
+
*/
|
|
10012
|
+
static formatMeanMotionDot(value) {
|
|
10013
|
+
const sign2 = value >= 0 ? " " : "-";
|
|
10014
|
+
return sign2 + Math.abs(value).toFixed(8).substring(1);
|
|
10015
|
+
}
|
|
10016
|
+
/**
|
|
10017
|
+
* Format a value in TLE exponential notation for BSTAR or mean motion ddot.
|
|
10018
|
+
* Format: "sNNNNN±N" (8 chars) where mantissa has implied leading decimal point.
|
|
10019
|
+
* Example: 0.00017507 → " 17507-3" (i.e., .17507 × 10^-3)
|
|
10020
|
+
* @param value - The value to format
|
|
10021
|
+
* @returns Formatted 8-character string
|
|
10022
|
+
*/
|
|
10023
|
+
static formatTleExponential(value) {
|
|
10024
|
+
if (value === 0) {
|
|
10025
|
+
return " 00000+0";
|
|
10026
|
+
}
|
|
10027
|
+
const sign2 = value >= 0 ? " " : "-";
|
|
10028
|
+
const absVal = Math.abs(value);
|
|
10029
|
+
let exponent = Math.floor(Math.log10(absVal)) + 1;
|
|
10030
|
+
let mantissa = absVal / Math.pow(10, exponent);
|
|
10031
|
+
if (mantissa >= 1) {
|
|
10032
|
+
mantissa /= 10;
|
|
10033
|
+
exponent++;
|
|
10034
|
+
}
|
|
10035
|
+
if (mantissa < 0.1 && mantissa > 0) {
|
|
10036
|
+
mantissa *= 10;
|
|
10037
|
+
exponent--;
|
|
10038
|
+
}
|
|
10039
|
+
const mantissaStr = Math.round(mantissa * 1e5).toString().padStart(5, "0");
|
|
10040
|
+
const expSign = exponent >= 0 ? "+" : "-";
|
|
10041
|
+
const expStr = Math.abs(exponent).toString();
|
|
10042
|
+
return sign2 + mantissaStr + expSign + expStr;
|
|
10043
|
+
}
|
|
10044
|
+
/**
|
|
10045
|
+
* Compute TLE line checksum (modulo 10 sum of digits, '-' counts as 1).
|
|
10046
|
+
* @param line - TLE line (first 68 characters are summed)
|
|
10047
|
+
* @returns Checksum digit (0-9)
|
|
10048
|
+
*/
|
|
10049
|
+
static tleChecksum(line) {
|
|
10050
|
+
let sum = 0;
|
|
10051
|
+
for (let i = 0; i < 68 && i < line.length; i++) {
|
|
10052
|
+
const c = line[i];
|
|
10053
|
+
if (c >= "0" && c <= "9") {
|
|
10054
|
+
sum += parseInt(c);
|
|
10055
|
+
} else if (c === "-") {
|
|
10056
|
+
sum += 1;
|
|
10057
|
+
}
|
|
10058
|
+
}
|
|
10059
|
+
return sum % 10;
|
|
10060
|
+
}
|
|
9993
10061
|
};
|
|
9994
10062
|
|
|
9995
10063
|
// src/coordinate/RelativeState.ts
|
|
@@ -13185,13 +13253,28 @@ var ClassicalElements = class _ClassicalElements {
|
|
|
13185
13253
|
const h = pos.cross(vel);
|
|
13186
13254
|
const i = Math.acos(clamp(h.z / h.magnitude(), -1, 1));
|
|
13187
13255
|
const n = Vector3D.zAxis.cross(h);
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13256
|
+
const nMag = n.magnitude();
|
|
13257
|
+
let o;
|
|
13258
|
+
let w;
|
|
13259
|
+
if (nMag < 1e-12) {
|
|
13260
|
+
o = 0;
|
|
13261
|
+
if (e > 1e-12) {
|
|
13262
|
+
w = Math.atan2(eVec.y, eVec.x);
|
|
13263
|
+
if (w < 0) {
|
|
13264
|
+
w = w + TAU;
|
|
13265
|
+
}
|
|
13266
|
+
} else {
|
|
13267
|
+
w = 0;
|
|
13268
|
+
}
|
|
13269
|
+
} else {
|
|
13270
|
+
o = Math.acos(clamp(n.x / nMag, -1, 1));
|
|
13271
|
+
if (n.y < 0) {
|
|
13272
|
+
o = TAU - o;
|
|
13273
|
+
}
|
|
13274
|
+
w = n.angle(eVec);
|
|
13275
|
+
if (eVec.z < 0) {
|
|
13276
|
+
w = TAU - w;
|
|
13277
|
+
}
|
|
13195
13278
|
}
|
|
13196
13279
|
let v = eVec.angle(pos);
|
|
13197
13280
|
if (pos.dot(vel) < 0) {
|
|
@@ -16623,8 +16706,9 @@ var Satellite = class _Satellite extends SpaceObject {
|
|
|
16623
16706
|
this.satrec = Sgp4.createSatrec(tle1, tle2);
|
|
16624
16707
|
}
|
|
16625
16708
|
parseOmmAndUpdateOrbit_(omm) {
|
|
16626
|
-
|
|
16627
|
-
this.
|
|
16709
|
+
const noradStr = String(omm.NORAD_CAT_ID);
|
|
16710
|
+
this.sccNum = noradStr.padStart(5, "0");
|
|
16711
|
+
this.sccNum5 = Tle.convert6DigitToA5(noradStr);
|
|
16628
16712
|
this.sccNum6 = Tle.convertA5to6Digit(this.sccNum5);
|
|
16629
16713
|
this.intlDes = omm.OBJECT_ID;
|
|
16630
16714
|
const YYYY = omm.EPOCH.slice(0, 4);
|
|
@@ -16637,6 +16721,19 @@ var Satellite = class _Satellite extends SpaceObject {
|
|
|
16637
16721
|
const dayOfYear = (epochDateObj - Date.UTC(Number(YYYY), 0, 0)) / 864e5;
|
|
16638
16722
|
const ommParsed = {
|
|
16639
16723
|
...omm,
|
|
16724
|
+
NORAD_CAT_ID: noradStr,
|
|
16725
|
+
MEAN_MOTION: String(omm.MEAN_MOTION),
|
|
16726
|
+
ECCENTRICITY: String(omm.ECCENTRICITY),
|
|
16727
|
+
INCLINATION: String(omm.INCLINATION),
|
|
16728
|
+
RA_OF_ASC_NODE: String(omm.RA_OF_ASC_NODE),
|
|
16729
|
+
ARG_OF_PERICENTER: String(omm.ARG_OF_PERICENTER),
|
|
16730
|
+
MEAN_ANOMALY: String(omm.MEAN_ANOMALY),
|
|
16731
|
+
EPHEMERIS_TYPE: String(omm.EPHEMERIS_TYPE),
|
|
16732
|
+
ELEMENT_SET_NO: String(omm.ELEMENT_SET_NO),
|
|
16733
|
+
REV_AT_EPOCH: String(omm.REV_AT_EPOCH),
|
|
16734
|
+
BSTAR: String(omm.BSTAR),
|
|
16735
|
+
MEAN_MOTION_DOT: String(omm.MEAN_MOTION_DOT),
|
|
16736
|
+
MEAN_MOTION_DDOT: String(omm.MEAN_MOTION_DDOT),
|
|
16640
16737
|
epoch: {
|
|
16641
16738
|
year: Number(YYYY),
|
|
16642
16739
|
month: Number(MM),
|
|
@@ -16649,20 +16746,41 @@ var Satellite = class _Satellite extends SpaceObject {
|
|
|
16649
16746
|
};
|
|
16650
16747
|
this.epochYear = parseInt(YYYY.slice(2, 4));
|
|
16651
16748
|
this.epochDay = dayOfYear;
|
|
16652
|
-
this.meanMoDev1 =
|
|
16653
|
-
this.meanMoDev2 =
|
|
16654
|
-
this.bstar =
|
|
16655
|
-
this.inclination =
|
|
16656
|
-
this.rightAscension =
|
|
16657
|
-
this.eccentricity =
|
|
16658
|
-
this.argOfPerigee =
|
|
16659
|
-
this.meanAnomaly =
|
|
16660
|
-
this.meanMotion =
|
|
16749
|
+
this.meanMoDev1 = Number(omm.MEAN_MOTION_DOT);
|
|
16750
|
+
this.meanMoDev2 = Number(omm.MEAN_MOTION_DDOT);
|
|
16751
|
+
this.bstar = Number(omm.BSTAR);
|
|
16752
|
+
this.inclination = Number(omm.INCLINATION);
|
|
16753
|
+
this.rightAscension = Number(omm.RA_OF_ASC_NODE);
|
|
16754
|
+
this.eccentricity = Number(omm.ECCENTRICITY);
|
|
16755
|
+
this.argOfPerigee = Number(omm.ARG_OF_PERICENTER);
|
|
16756
|
+
this.meanAnomaly = Number(omm.MEAN_ANOMALY);
|
|
16757
|
+
this.meanMotion = Number(omm.MEAN_MOTION);
|
|
16661
16758
|
this.period = 1440 / this.meanMotion;
|
|
16662
16759
|
this.semiMajorAxis = (8681663653e-3 / this.meanMotion) ** (2 / 3);
|
|
16663
16760
|
this.semiMinorAxis = this.semiMajorAxis * Math.sqrt(1 - this.eccentricity ** 2);
|
|
16664
16761
|
this.apogee = this.semiMajorAxis * (1 + this.eccentricity) - 6371;
|
|
16665
16762
|
this.perigee = this.semiMajorAxis * (1 - this.eccentricity) - 6371;
|
|
16763
|
+
const { tle1, tle2 } = FormatTle.createTle({
|
|
16764
|
+
inc: this.inclination,
|
|
16765
|
+
meanmo: this.meanMotion,
|
|
16766
|
+
rasc: this.rightAscension,
|
|
16767
|
+
argPe: this.argOfPerigee,
|
|
16768
|
+
meana: this.meanAnomaly,
|
|
16769
|
+
ecen: this.eccentricity,
|
|
16770
|
+
epochyr: this.epochYear,
|
|
16771
|
+
epochday: this.epochDay,
|
|
16772
|
+
intl: omm.OBJECT_ID,
|
|
16773
|
+
scc: this.sccNum,
|
|
16774
|
+
bstar: this.bstar,
|
|
16775
|
+
meanMotionDot: this.meanMoDev1,
|
|
16776
|
+
meanMotionDdot: this.meanMoDev2,
|
|
16777
|
+
classification: String(omm.CLASSIFICATION_TYPE) || "U",
|
|
16778
|
+
revAtEpoch: Number(omm.REV_AT_EPOCH) || 0,
|
|
16779
|
+
elementSetNo: Number(omm.ELEMENT_SET_NO) || 999,
|
|
16780
|
+
ephemerisType: Number(omm.EPHEMERIS_TYPE) || 0
|
|
16781
|
+
});
|
|
16782
|
+
this.tle1 = tle1;
|
|
16783
|
+
this.tle2 = tle2;
|
|
16666
16784
|
this.satrec = Sgp4.createSatrecFromOmm(ommParsed);
|
|
16667
16785
|
}
|
|
16668
16786
|
// ==================== Type Checking ====================
|
|
@@ -25178,6 +25296,61 @@ var OmmParser = class _OmmParser {
|
|
|
25178
25296
|
const theory = omm.metadata.MEAN_ELEMENT_THEORY.toUpperCase();
|
|
25179
25297
|
return theory === "SGP" || theory === "SGP4" || theory === "SGP4-XP";
|
|
25180
25298
|
}
|
|
25299
|
+
/**
|
|
25300
|
+
* Parse a CelesTrak-style flat JSON OMM object into the structured ParsedOmm format.
|
|
25301
|
+
*
|
|
25302
|
+
* CelesTrak's JSON OMM format is a flat object with all fields at the top level,
|
|
25303
|
+
* omitting metadata fields like CENTER_NAME, REF_FRAME, TIME_SYSTEM, and
|
|
25304
|
+
* MEAN_ELEMENT_THEORY (which are always EARTH/TEME/UTC/SGP4 for GP data).
|
|
25305
|
+
*
|
|
25306
|
+
* @param omm - A flat OMM JSON object from CelesTrak
|
|
25307
|
+
* @returns Parsed OMM structure with inferred metadata
|
|
25308
|
+
*/
|
|
25309
|
+
static parseJson(omm) {
|
|
25310
|
+
const result = {
|
|
25311
|
+
header: {
|
|
25312
|
+
CCSDS_OMM_VERS: "3.0",
|
|
25313
|
+
CREATION_DATE: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25314
|
+
ORIGINATOR: "CelesTrak"
|
|
25315
|
+
},
|
|
25316
|
+
metadata: {
|
|
25317
|
+
OBJECT_NAME: omm.OBJECT_NAME,
|
|
25318
|
+
OBJECT_ID: omm.OBJECT_ID,
|
|
25319
|
+
CENTER_NAME: "EARTH",
|
|
25320
|
+
REF_FRAME: "TEME",
|
|
25321
|
+
TIME_SYSTEM: "UTC",
|
|
25322
|
+
MEAN_ELEMENT_THEORY: "SGP4"
|
|
25323
|
+
},
|
|
25324
|
+
meanElements: {
|
|
25325
|
+
EPOCH: omm.EPOCH,
|
|
25326
|
+
MEAN_MOTION: Number(omm.MEAN_MOTION),
|
|
25327
|
+
ECCENTRICITY: Number(omm.ECCENTRICITY),
|
|
25328
|
+
INCLINATION: Number(omm.INCLINATION),
|
|
25329
|
+
RA_OF_ASC_NODE: Number(omm.RA_OF_ASC_NODE),
|
|
25330
|
+
ARG_OF_PERICENTER: Number(omm.ARG_OF_PERICENTER),
|
|
25331
|
+
MEAN_ANOMALY: Number(omm.MEAN_ANOMALY)
|
|
25332
|
+
},
|
|
25333
|
+
tleParameters: {
|
|
25334
|
+
EPHEMERIS_TYPE: Number(omm.EPHEMERIS_TYPE),
|
|
25335
|
+
CLASSIFICATION_TYPE: String(omm.CLASSIFICATION_TYPE),
|
|
25336
|
+
NORAD_CAT_ID: Number(omm.NORAD_CAT_ID),
|
|
25337
|
+
ELEMENT_SET_NO: Number(omm.ELEMENT_SET_NO),
|
|
25338
|
+
REV_AT_EPOCH: Number(omm.REV_AT_EPOCH),
|
|
25339
|
+
BSTAR: Number(omm.BSTAR),
|
|
25340
|
+
MEAN_MOTION_DOT: Number(omm.MEAN_MOTION_DOT),
|
|
25341
|
+
MEAN_MOTION_DDOT: Number(omm.MEAN_MOTION_DDOT)
|
|
25342
|
+
}
|
|
25343
|
+
};
|
|
25344
|
+
return result;
|
|
25345
|
+
}
|
|
25346
|
+
/**
|
|
25347
|
+
* Parse an array of CelesTrak-style flat JSON OMM objects.
|
|
25348
|
+
* @param ommArray - Array of flat OMM JSON objects from CelesTrak
|
|
25349
|
+
* @returns Array of parsed OMM structures
|
|
25350
|
+
*/
|
|
25351
|
+
static parseJsonArray(ommArray) {
|
|
25352
|
+
return ommArray.map((omm) => _OmmParser.parseJson(omm));
|
|
25353
|
+
}
|
|
25181
25354
|
/**
|
|
25182
25355
|
* Parse all key-value pairs from OMM lines (excluding COMMENT lines).
|
|
25183
25356
|
*/
|