@saber-usa/node-common 1.6.207 → 1.7.0

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/README.md CHANGED
@@ -36,7 +36,7 @@ A transformer for object keys is provided. This will take an object and transfor
36
36
  ## Publishing changes
37
37
 
38
38
  1. Change the version in package.json
39
- 2. Run `npm publish --access public && npm install`
39
+ 2. Run `npm publish && npm install`
40
40
  3. Enable GPG in GIT: `git config --global commit.gpgsign true`
41
41
  4. Run `gpg --list-keys` to get your <id>
42
42
  5. Tell the GIT to use your key `git config user.signingkey <id>`
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@saber-usa/node-common",
3
- "version": "1.6.207",
3
+ "version": "1.7.0",
4
4
  "description": "Common node functions for Saber",
5
5
  "main": "src/index.js",
6
+ "type": "module",
6
7
  "scripts": {
7
8
  "lint": "eslint . --ext js",
8
9
  "lint:fix": "eslint . --ext js --fix",
@@ -17,10 +18,9 @@
17
18
  "license": "ISC",
18
19
  "dependencies": {
19
20
  "@aws-sdk/client-s3": "^3.666.0",
20
- "date-fns": "^2.28.0",
21
- "local-sidereal-time": "^1.0.4",
21
+ "date-fns": "^4.1.0",
22
22
  "lodash": "4.17.21",
23
- "mathjs": "^11.5.0",
23
+ "mathjs": "^14.7.0",
24
24
  "pious-squid": "^2.3.0",
25
25
  "plotly": "^1.0.6",
26
26
  "satellite.js": "^6.0.1",
@@ -1,10 +1,8 @@
1
1
  // FrameConverter.js - Port from C# FrameConverter.cs
2
- const {Matrix3D,
3
- Vector3D,
4
- } = require("pious-squid");
5
- const {LLA} = require("./LLA.js");
6
- const {TimeConverter, RaDec} = require("./TimeConverter.js");
7
- const {norm, cross} = require("mathjs");
2
+ import {Matrix3D, Vector3D} from "pious-squid";
3
+ import {LLA} from "./LLA.js";
4
+ import {TimeConverter, RaDec} from "./TimeConverter.js";
5
+ import {norm, cross} from "mathjs";
8
6
 
9
7
 
10
8
  // Enums (assuming these exist elsewhere)
@@ -1066,6 +1064,5 @@ class FrameConverter {
1066
1064
  ];
1067
1065
  }
1068
1066
 
1069
- module.exports.FrameConverter = FrameConverter;
1070
- module.exports.ReferenceFrame = ReferenceFrame;
1071
- module.exports.EarthParams = Earth;
1067
+ export {FrameConverter, ReferenceFrame};
1068
+ export const EarthParams = Earth;
package/src/LLA.js CHANGED
@@ -176,6 +176,4 @@ class Angle {
176
176
  }
177
177
 
178
178
  // Export for use
179
- if (typeof module !== "undefined" && module.exports) {
180
- module.exports = {LLA, Angle};
181
- }
179
+ export {LLA, Angle};
@@ -1,12 +1,16 @@
1
- const {degreesToRadians, radiansToDegrees} = require("satellite.js");
2
- const {Vector3D, J2000, EpochUTC} = require("pious-squid");
3
- const {NodeVector3D} = require("./NodeVector3D.js");
4
- const constants = require("./constants.js");
5
- const {FrameConverter} = require("./FrameConverter.js");
6
- const {OrbitUtils} = require("./OrbitUtils.js");
7
- const {wrapOneRevUnsigned} = require("./utils.js");
8
- const {BallisticPropagator} = require("./ballisticPropagator/ballisticPropagator.js");
9
- const {norm, cross, dot} = require("mathjs");
1
+ import {degreesToRadians, radiansToDegrees} from "satellite.js";
2
+ import {Vector3D, J2000, EpochUTC} from "pious-squid";
3
+ import {NodeVector3D} from "./NodeVector3D.js";
4
+ import {WGS84_EARTH_EQUATORIAL_RADIUS_KM,
5
+ GRAV_CONST,
6
+ EARTH_MASS,
7
+ MU,
8
+ EARTH_RADIUS_KM} from "./constants.js";
9
+ import {FrameConverter} from "./FrameConverter.js";
10
+ import {OrbitUtils} from "./OrbitUtils.js";
11
+ import {wrapOneRevUnsigned} from "./utils.js";
12
+ import {BallisticPropagator} from "./ballisticPropagator.js";
13
+ import {norm, cross, dot} from "mathjs";
10
14
 
11
15
  // Reference frames enum
12
16
  const ReferenceFrame = {
@@ -290,7 +294,7 @@ class LaunchNominalClass {
290
294
  initialNominal.states[0].elements.raan,
291
295
  targetEcc,
292
296
  degreesToRadians(targetArgOfPeriapsisDeg),
293
- targetPerigeeKm + constants.WGS84_EARTH_EQUATORIAL_RADIUS_KM,
297
+ targetPerigeeKm + WGS84_EARTH_EQUATORIAL_RADIUS_KM,
294
298
  );
295
299
 
296
300
  // Convert elliptical elements to cartesian state
@@ -406,8 +410,8 @@ class LaunchNominalClass {
406
410
  }
407
411
 
408
412
  const azimuthRad = degreesToRadians(azimuthDeg);
409
- const earthRadius = constants.WGS84_EARTH_EQUATORIAL_RADIUS_KM;
410
- const mu = constants.GRAV_CONST * constants.EARTH_MASS / 1e9; // km^3/s^2
413
+ const earthRadius = WGS84_EARTH_EQUATORIAL_RADIUS_KM;
414
+ const mu = GRAV_CONST * EARTH_MASS / 1e9; // km^3/s^2
411
415
 
412
416
  // Get transformation from ITRF to J2000
413
417
  const itrf2j2000 = FrameConverter.itrfToJ2000(orbitInsertionTime);
@@ -454,7 +458,7 @@ class LaunchNominalClass {
454
458
  }
455
459
 
456
460
  static hohmannTransferWithIncZeroing(state0, targetSMA,
457
- burnAtNodes = 1, mu = constants.MU / 1e9) {
461
+ burnAtNodes = 1, mu = MU / 1e9) {
458
462
  let t0 = state0.epochUtc;
459
463
  let i = null;
460
464
 
@@ -587,7 +591,7 @@ class LaunchNominalClass {
587
591
 
588
592
  static #getNextNodeCrossingGeoOrbit(sv) {
589
593
  const geoElements = {
590
- semiMajorAxis: 35786.0 + constants.EARTH_RADIUS_KM,
594
+ semiMajorAxis: 35786.0 + EARTH_RADIUS_KM,
591
595
  eccentricity: 0,
592
596
  inclination: 0,
593
597
  raan: 0,
@@ -602,7 +606,7 @@ class LaunchNominalClass {
602
606
  return nextNode.nextNodeTime;
603
607
  }
604
608
 
605
- static #findMutualNodeTimes(sv1, sv2, muEarth = constants.MU / 1e9) {
609
+ static #findMutualNodeTimes(sv1, sv2, muEarth = MU / 1e9) {
606
610
  // Implementation for finding mutual node times between two state vectors
607
611
 
608
612
  if (!(sv1.epochUtc === sv2.epochUtc)) {
@@ -817,6 +821,4 @@ class LaunchNominalOutput {
817
821
  }
818
822
  }
819
823
 
820
- module.exports = {
821
- LaunchNominalClass: LaunchNominalClass,
822
- };
824
+ export {LaunchNominalClass};
@@ -1,4 +1,4 @@
1
- const {Vector3D} = require("pious-squid");
1
+ import {Vector3D} from "pious-squid";
2
2
 
3
3
  class NodeVector3D {
4
4
  constructor(x, y, z) {
@@ -68,4 +68,4 @@ class NodeVector3D {
68
68
  // TODO: add angle and join operation methods
69
69
  }
70
70
 
71
- module.exports = {NodeVector3D};
71
+ export {NodeVector3D};
package/src/OrbitUtils.js CHANGED
@@ -1,6 +1,6 @@
1
- const {MU} = require("./constants.js");
2
- const {cross, norm} = require("mathjs");
3
- const {wrapHalfRevUnsigned, wrapOneRevUnsigned} = require("./utils.js");
1
+ import {MU} from "./constants.js";
2
+ import {cross, norm} from "mathjs";
3
+ import {wrapHalfRevUnsigned, wrapOneRevUnsigned} from "./utils.js";
4
4
 
5
5
  const EARTH_MU_KM = MU / 1e9;
6
6
 
@@ -280,11 +280,11 @@ class OrbitUtils {
280
280
  */
281
281
  static stateVectorToElements(r, v, mu = EARTH_MU_KM) {
282
282
  const tol = 1e-9;
283
-
283
+
284
284
  if (mu < 1e-30) {
285
285
  throw new Error("Mu must be greater than 1e-30.");
286
286
  }
287
-
287
+
288
288
  // Helper functions
289
289
  function cross(a, b) {
290
290
  return [
@@ -293,100 +293,102 @@ class OrbitUtils {
293
293
  a[0] * b[1] - a[1] * b[0],
294
294
  ];
295
295
  }
296
-
296
+
297
297
  function dot(a, b) {
298
298
  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
299
299
  }
300
-
300
+
301
301
  function norm(v) {
302
302
  return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
303
303
  }
304
-
304
+
305
305
  function clamp(value, min, max) {
306
306
  return Math.min(Math.max(value, min), max);
307
307
  }
308
-
308
+
309
309
  // Calculate basic vectors
310
310
  const h = cross(r, v);
311
311
  const n = cross([0, 0, 1], h);
312
-
312
+
313
313
  const rLength = norm(r);
314
314
  const vLength = norm(v);
315
-
315
+
316
316
  if (rLength === 0) throw new Error("Position vector must not be zero.");
317
317
  if (vLength === 0) throw new Error("Velocity vector must not be zero.");
318
-
318
+
319
319
  // Eccentricity vector calculation (corrected formula)
320
320
  const vLengthSq = vLength * vLength;
321
321
  const muOverR = mu / rLength;
322
322
  const rvDot = dot(r, v);
323
-
323
+
324
324
  const e = [
325
325
  (1 / mu) * ((vLengthSq - muOverR) * r[0] - rvDot * v[0]),
326
326
  (1 / mu) * ((vLengthSq - muOverR) * r[1] - rvDot * v[1]),
327
327
  (1 / mu) * ((vLengthSq - muOverR) * r[2] - rvDot * v[2]),
328
328
  ];
329
-
329
+
330
330
  const zeta = 0.5 * vLengthSq - muOverR;
331
-
331
+
332
332
  if (zeta === 0) throw new Error("Zeta cannot be zero.");
333
-
333
+
334
334
  const eLength = norm(e);
335
335
  if (Math.abs(1.0 - eLength) <= tol) {
336
336
  throw new Error("Parabolic orbit conversion is not supported.");
337
337
  }
338
-
338
+
339
339
  const a = -mu / (zeta * 2);
340
-
340
+
341
341
  if (Math.abs(a * (1 - eLength)) < 1e-3) {
342
342
  throw new Error("The state results in a singular conic section "
343
343
  + "with radius of periapsis less than 1 m.");
344
344
  }
345
-
345
+
346
346
  const hLength = norm(h);
347
347
  if (hLength === 0) {
348
- throw new Error("Cannot convert from Cartesian to Keplerian - angular momentum is zero.");
348
+ throw new Error(`Cannot convert from Cartesian to Keplerian
349
+ - angular momentum is zero.`);
349
350
  }
350
-
351
+
351
352
  const i = Math.acos(h[2] / hLength);
352
-
353
+
353
354
  if (i >= Math.PI - tol) {
354
355
  throw new Error("Cannot convert orbit with inclination of 180 degrees.");
355
356
  }
356
-
357
+
357
358
  let raan = 0;
358
359
  let w = 0;
359
360
  let f = 0;
360
-
361
+
361
362
  const nLength = norm(n);
362
-
363
+
363
364
  // CASE 1: Non-circular, Inclined Orbit
364
365
  if (eLength >= 1e-11 && i >= 1e-11 && i <= Math.PI - 1e-11) {
365
366
  if (nLength === 0.0) {
366
367
  throw new Error("Cannot convert from Cartesian to Keplerian "
367
368
  + "- line-of-nodes vector is a zero vector.");
368
369
  }
369
-
370
+
370
371
  raan = Math.acos(n[0] / nLength);
371
372
  if (n[1] < 0) raan = 2 * Math.PI - raan;
372
-
373
+
373
374
  w = Math.acos(dot(n, e) / (nLength * eLength));
374
375
  if (e[2] < 0) w = 2 * Math.PI - w;
375
-
376
+
376
377
  f = Math.acos(clamp(dot(e, r) / (eLength * rLength), -1, 1));
377
378
  if (rvDot < 0) f = 2 * Math.PI - f;
378
379
  } else if (eLength >= 1e-11 && (i < 1e-11 || i > Math.PI - 1e-11)) { // CASE 2: Non-circular, Equatorial Orbit
379
380
  if (eLength === 0.0) {
380
- throw new Error("Cannot convert from Cartesian to Keplerian - eccentricity is zero.");
381
+ throw new Error(`Cannot convert from Cartesian to Keplerian
382
+ - eccentricity is zero.`);
381
383
  }
382
384
  raan = 0;
383
385
  w = Math.acos(e[0] / eLength);
384
386
  if (e[1] < 0) w = 2 * Math.PI - w;
385
-
387
+
386
388
  // For GMT-4446 fix (LOJ: 2014.03.21)
387
389
  if (i > Math.PI - 1e-11) w *= -1.0;
388
390
  if (w < 0.0) w += 2 * Math.PI;
389
-
391
+
390
392
  f = Math.acos(clamp(dot(e, r) / (eLength * rLength), -1, 1));
391
393
  if (rvDot < 0) f = 2 * Math.PI - f;
392
394
  } else if (eLength < 1e-11 && i >= 1e-11 && i <= Math.PI - 1e-11) { // CASE 3: Circular, Inclined Orbit
@@ -396,9 +398,9 @@ class OrbitUtils {
396
398
  }
397
399
  raan = Math.acos(n[0] / nLength);
398
400
  if (n[1] < 0) raan = 2 * Math.PI - raan;
399
-
401
+
400
402
  w = 0;
401
-
403
+
402
404
  f = Math.acos(clamp(dot(n, r) / (nLength * rLength), -1, 1));
403
405
  if (r[2] < 0) f = 2 * Math.PI - f;
404
406
  } else if (eLength < 1e-11 && (i < 1e-11 || i > Math.PI - 1e-11)) { // CASE 4: Circular, Equatorial Orbit
@@ -406,16 +408,16 @@ class OrbitUtils {
406
408
  w = 0;
407
409
  f = Math.acos(clamp(r[0] / rLength, -1, 1));
408
410
  if (r[1] < 0) f = 2 * Math.PI - f;
409
-
411
+
410
412
  // For GMT-4446 fix (LOJ: 2014.03.21)
411
413
  if (i > Math.PI - 1e-11) f *= -1.0;
412
414
  if (f < 0.0) f += 2 * Math.PI;
413
415
  }
414
-
416
+
415
417
  // Calculate additional orbital parameters
416
418
  const period = 2 * Math.PI * Math.sqrt(Math.pow(Math.abs(a), 3) / mu);
417
419
  const meanMotion = 2 * Math.PI / period;
418
-
420
+
419
421
  // Convert true anomaly to mean anomaly properly
420
422
  const eccentricAnomaly = this.trueAnomalyToEccentricAnomaly(f, eLength);
421
423
  const meanAnomaly = this.eccentricAnomalyToMeanAnomaly(eccentricAnomaly, eLength);
@@ -432,7 +434,7 @@ class OrbitUtils {
432
434
  meanMotion: meanMotion, // rad/s
433
435
  };
434
436
  }
435
-
437
+
436
438
  /**
437
439
  * Convert true anomaly to eccentric anomaly
438
440
  * @param {number} nu - true anomaly
@@ -444,7 +446,7 @@ class OrbitUtils {
444
446
  const sinE = Math.sqrt(1 - e * e) * Math.sin(nu) / (1 + e * Math.cos(nu));
445
447
  return Math.atan2(sinE, cosE);
446
448
  }
447
-
449
+
448
450
  /**
449
451
  * Convert eccentric anomaly to mean anomaly
450
452
  * @param {number} E - Eccentric anomaly
@@ -454,7 +456,7 @@ class OrbitUtils {
454
456
  static eccentricAnomalyToMeanAnomaly(E, e) {
455
457
  return E - e * Math.sin(E);
456
458
  }
457
-
459
+
458
460
  /**
459
461
  * Convert mean anomaly to eccentric anomaly (Kepler's equation)
460
462
  * @param {number} M - Mean anomaly
@@ -471,7 +473,7 @@ class OrbitUtils {
471
473
  }
472
474
  return E;
473
475
  }
474
-
476
+
475
477
  /**
476
478
  * Convert eccentric anomaly to true anomaly
477
479
  * @param {number} E - Eccentric anomaly
@@ -483,9 +485,6 @@ class OrbitUtils {
483
485
  const sinNu = Math.sqrt(1 - e * e) * Math.sin(E) / (1 - e * Math.cos(E));
484
486
  return Math.atan2(sinNu, cosNu);
485
487
  }
486
-
487
488
  }
488
489
 
489
- module.exports = {
490
- OrbitUtils: OrbitUtils,
491
- };
490
+ export {OrbitUtils};
@@ -0,0 +1,100 @@
1
+ import {BallisticPropagator} from "./ballisticPropagator.js";
2
+ import {RungeKutta4Propagator,
3
+ J2000,
4
+ KeplerPropagator,
5
+ EpochUTC,
6
+ ClassicalElements} from "pious-squid";
7
+ import {sgp4} from "satellite.js";
8
+ import {NodeVector3D} from "./NodeVector3D.js";
9
+ import {checkTle} from "./astro.js";
10
+ import {OrbitUtils} from "./OrbitUtils.js";
11
+
12
+ const ReferenceFrame = {
13
+ ITRF: "ITRF",
14
+ J2000: "J2000",
15
+ TEME: "TEME",
16
+ GCRF: "GCRF",
17
+ };
18
+
19
+ class PropagateUtils {
20
+ static propagatorSelection(initialState, propagatorType, endTime) {
21
+ let propVal = null;
22
+ switch (propagatorType) {
23
+ case "NUMERICAL":
24
+ propVal = PropagateUtils.numericalPropagator(initialState, endTime);
25
+ break;
26
+ case "KEPLERIAN":
27
+ propVal = PropagateUtils.keplerianPropagator(initialState, endTime);
28
+ break;
29
+ case "ANALYTICAL":
30
+ propVal = PropagateUtils.analyticalPropagator(
31
+ initialState, ReferenceFrame.J2000, endTime);
32
+ break;
33
+ case "TLE":
34
+ propVal = PropagateUtils.tlePropagator(initialState, endTime);
35
+ break;
36
+ }
37
+ return propVal;
38
+ }
39
+
40
+ static numericalPropagator(initialState, time) {
41
+ const state0 = new J2000(
42
+ new EpochUTC(initialState.epochUtc), initialState.position, initialState.velocity);
43
+ const prop = new RungeKutta4Propagator(state0);
44
+ const endTime = new EpochUTC(time);
45
+ const result = prop.propagate(endTime);
46
+ return result;
47
+ }
48
+
49
+ static analyticalPropagator(initialState, frame, time) {
50
+ const state = {
51
+ position: new NodeVector3D(
52
+ initialState.position.x, initialState.position.y, initialState.position.z), // km
53
+ velocity: new NodeVector3D(
54
+ initialState.velocity.x, initialState.velocity.y, initialState.velocity.z), // km/s
55
+ epochUtc: initialState.epochUtc,
56
+ referenceFrame: frame,
57
+ };
58
+
59
+ const propagator = new BallisticPropagator(state);
60
+ const result = propagator.propagate(time);
61
+ return result;
62
+ }
63
+
64
+ static keplerianPropagator(initialState, time) {
65
+ const elementsObj = OrbitUtils.stateVectorToElements(
66
+ initialState.position, initialState.velocity);
67
+
68
+ const elements = new ClassicalElements(
69
+ new EpochUTC(initialState.epoch),
70
+ elementsObj.semiMajorAxis,
71
+ elementsObj.eccentricity,
72
+ elementsObj.inclination,
73
+ elementsObj.raan,
74
+ elementsObj.argOfPeriapsis,
75
+ elementsObj.trueAnomaly,
76
+ );
77
+
78
+ // Now pass to KeplerPropagator:
79
+ const prop = new KeplerPropagator(elements);
80
+
81
+ const result = prop.propagate(new EpochUTC(time));
82
+
83
+
84
+ return result;
85
+ }
86
+
87
+ static tlePropagator(tle, time) {
88
+ const line1 = tle[0];
89
+ const line2 = tle[1];
90
+ const satrec = checkTle(line1, line2);
91
+ if (!satrec) {
92
+ throw new Error("Invalid TLE data");
93
+ }
94
+ const result = sgp4(satrec, time);
95
+ return result;
96
+ }
97
+ }
98
+
99
+ export {PropagateUtils};
100
+
@@ -1,8 +1,10 @@
1
- const constants = require("./constants.js");
2
- const solar = require("solar-calculator");
3
- const THREE = require("three");
4
- const {wrapToRange} = require("./utils.js");
5
- const {sunPosAt} = require("./astro.js");
1
+ import constants, {WGS84_EARTH_EQUATORIAL_RADIUS_KM,
2
+ DEG2RAD, AU_KM as _AU_KM,
3
+ GEO_ALTITUDE_KM, RAD2DEG} from "./constants.js";
4
+ import solar from "solar-calculator";
5
+ import {Vector3} from "three";
6
+ import {wrapToRange} from "./utils.js";
7
+ import {sunPosAt} from "./astro.js";
6
8
 
7
9
  class ShadowGEOCalculator {
8
10
  constructor() {
@@ -13,7 +15,7 @@ class ShadowGEOCalculator {
13
15
  }
14
16
 
15
17
  static _calculateUmbraGeometry(deltaPS) {
16
- const Dp = 2 * constants.WGS84_EARTH_EQUATORIAL_RADIUS_KM;
18
+ const Dp = 2 * WGS84_EARTH_EQUATORIAL_RADIUS_KM;
17
19
  const Ds = 2 * 695700; // sunRadiusKm
18
20
 
19
21
  // Distance from Earth center to umbra apex
@@ -26,7 +28,7 @@ class ShadowGEOCalculator {
26
28
  }
27
29
 
28
30
  static _calculatePenumbraGeometry(deltaPS) {
29
- const Dp = 2 * constants.WGS84_EARTH_EQUATORIAL_RADIUS_KM;
31
+ const Dp = 2 * WGS84_EARTH_EQUATORIAL_RADIUS_KM;
30
32
  const Ds = 2 * 695700; // sunRadiusKm
31
33
 
32
34
  // Distance from Earth center to penumbra apex
@@ -52,12 +54,12 @@ class ShadowGEOCalculator {
52
54
  }
53
55
 
54
56
  static _sunUnitVector(sunLongitude, sunDeclination) {
55
- const sunVector = new THREE.Vector3();
56
- sunVector.x = Math.cos(sunDeclination * constants.DEG2RAD)
57
- * Math.cos(sunLongitude * constants.DEG2RAD);
58
- sunVector.y = Math.cos(sunDeclination * constants.DEG2RAD)
59
- * Math.sin(sunLongitude * constants.DEG2RAD);
60
- sunVector.z = Math.sin(sunDeclination * constants.DEG2RAD);
57
+ const sunVector = new Vector3();
58
+ sunVector.x = Math.cos(sunDeclination * DEG2RAD)
59
+ * Math.cos(sunLongitude * DEG2RAD);
60
+ sunVector.y = Math.cos(sunDeclination * DEG2RAD)
61
+ * Math.sin(sunLongitude * DEG2RAD);
62
+ sunVector.z = Math.sin(sunDeclination * DEG2RAD);
61
63
  return sunVector; // returns the unit vector of the Sun's position
62
64
  }
63
65
 
@@ -65,16 +67,16 @@ class ShadowGEOCalculator {
65
67
  // Longitude and declination (latitude) describe direction, not distance.
66
68
  // To get the Earth-Sun distance in km, use astronomical data (mean ≈ 149,597,870.7 km).
67
69
  // If you want the position vector in km, use the distance and direction:
68
- const AU_KM = constants.AU_KM; // Astronomical Unit in kilometers
70
+ const AU_KM = _AU_KM; // Astronomical Unit in kilometers
69
71
  // AstroLibrary uses 149597900
70
72
  const r = AU_KM; // Use actual Earth-Sun distance if available, otherwise mean AU
71
73
 
72
74
  // Convert longitude and declination to a position vector in km
73
- const x = r * Math.cos(sunDeclination * constants.DEG2RAD)
74
- * Math.cos(sunLongitude * constants.DEG2RAD);
75
- const y = r * Math.cos(sunDeclination * constants.DEG2RAD)
76
- * Math.sin(sunLongitude * constants.DEG2RAD);
77
- const z = r * Math.sin(sunDeclination * constants.DEG2RAD);
75
+ const x = r * Math.cos(sunDeclination * DEG2RAD)
76
+ * Math.cos(sunLongitude * DEG2RAD);
77
+ const y = r * Math.cos(sunDeclination * DEG2RAD)
78
+ * Math.sin(sunLongitude * DEG2RAD);
79
+ const z = r * Math.sin(sunDeclination * DEG2RAD);
78
80
 
79
81
  return {x, y, z, distance: r};
80
82
  }
@@ -99,7 +101,7 @@ class ShadowGEOCalculator {
99
101
  const {Xu, alphaU} = ShadowGEOCalculator._calculateUmbraGeometry(deltaPS);
100
102
  const {Xp, alphaP} = ShadowGEOCalculator._calculatePenumbraGeometry(deltaPS);
101
103
 
102
- const geoRadius = constants.WGS84_EARTH_EQUATORIAL_RADIUS_KM + constants.GEO_ALTITUDE_KM;
104
+ const geoRadius = WGS84_EARTH_EQUATORIAL_RADIUS_KM + GEO_ALTITUDE_KM;
103
105
 
104
106
  // Calculate Shadow radii at GEO altitude
105
107
  const umbraRadiusGEO = ShadowGEOCalculator._umbraRadiusDistance(geoRadius, Xu, alphaU);
@@ -121,8 +123,8 @@ class ShadowGEOCalculator {
121
123
  ];
122
124
 
123
125
  // Converting shadow axis to latitude and longitude
124
- const shadowCenterLat = Math.asin(shadowCenter[2] / geoRadius) * constants.RAD2DEG;
125
- const shadowCenterLon = Math.atan2(shadowCenter[1], shadowCenter[0]) * constants.RAD2DEG;
126
+ const shadowCenterLat = Math.asin(shadowCenter[2] / geoRadius) * RAD2DEG;
127
+ const shadowCenterLon = Math.atan2(shadowCenter[1], shadowCenter[0]) * RAD2DEG;
126
128
 
127
129
  // Check if GEO belt intersects the shadow
128
130
  const equatorialDistance = Math.abs(shadowCenter[2]); // Distance from the equator to the shadow center
@@ -145,8 +147,8 @@ class ShadowGEOCalculator {
145
147
  // Intersection points in the GEO belt
146
148
  const centerLon = shadowCenterLon; // You already have this!
147
149
 
148
- let lon1 = centerLon + theta * constants.RAD2DEG;
149
- let lon2 = centerLon - theta * constants.RAD2DEG;
150
+ let lon1 = centerLon + theta * RAD2DEG;
151
+ let lon2 = centerLon - theta * RAD2DEG;
150
152
 
151
153
  // Ensure longitudes are within -180 to 180 degrees
152
154
  lon1 = wrapToRange(lon1, -180, 180);
@@ -173,8 +175,8 @@ class ShadowGEOCalculator {
173
175
  // Intersection points in the GEO belt
174
176
  const centerLon = shadowCenterLon; // You already have this!
175
177
 
176
- let lon1 = centerLon + theta * constants.RAD2DEG;
177
- let lon2 = centerLon - theta * constants.RAD2DEG;
178
+ let lon1 = centerLon + theta * RAD2DEG;
179
+ let lon2 = centerLon - theta * RAD2DEG;
178
180
 
179
181
  // Ensure longitudes are within -180 to 180 degrees
180
182
  lon1 = ((lon1 + 180) % 360 + 360) % 360 - 180;
@@ -198,4 +200,4 @@ class ShadowGEOCalculator {
198
200
  }
199
201
  }
200
202
 
201
- module.exports = ShadowGEOCalculator;
203
+ export {ShadowGEOCalculator};
@@ -1,5 +1,3 @@
1
- // const {gstime} = require("satellite.js");
2
-
3
1
  /**
4
2
  * TimeConverter - Port from C# TimeConverter
5
3
  * Handles conversions between different time systems (UTC, UT1, TAI, GPS, TT)
@@ -308,4 +306,4 @@ class RaDec {
308
306
  }
309
307
  }
310
308
 
311
- module.exports = {TimeConverter, RaDec};
309
+ export {TimeConverter, RaDec};
package/src/astro.js CHANGED
@@ -1,8 +1,7 @@
1
- const {cross, dot, norm, multiply, subtract, inv, polynomialRoot, add} = require("mathjs");
2
- const {dateToMySqlDate, dtStrtoJsDt, parseDate} = require("./fixDate.js");
3
- const solar = require("solar-calculator");
4
- const {
5
- twoline2satrec,
1
+ import {cross, dot, norm, multiply, subtract, inv, polynomialRoot, add} from "mathjs";
2
+ import {dateToMySqlDate, dtStrtoJsDt, parseDate} from "./fixDate.js";
3
+ import {century as _century, declination, equationOfTime} from "solar-calculator";
4
+ import {twoline2satrec,
6
5
  propagate,
7
6
  sgp4,
8
7
  gstime,
@@ -12,12 +11,10 @@ const {
12
11
  eciToEcf,
13
12
  ecfToLookAngles,
14
13
  degreesLong,
15
- degreesLat,
16
- } = require("satellite.js");
17
- const {lowerCaseObjectKeys} = require("./transform.js");
18
- const squid = require("pious-squid");
19
- const {
20
- normalize,
14
+ degreesLat} from "satellite.js";
15
+ import {lowerCaseObjectKeys} from "./transform.js";
16
+ import {EpochUTC, Geodetic, J2000, Vector3D} from "pious-squid";
17
+ import {normalize,
21
18
  transpose,
22
19
  multiplyVector,
23
20
  dist,
@@ -32,10 +29,8 @@ const {
32
29
  getAngle,
33
30
  wrapToRange,
34
31
  getAngleDiffSigned,
35
- posToArray,
36
- } = require("./utils.js");
37
- const {
38
- DEG2RAD,
32
+ posToArray} from "./utils.js";
33
+ import {DEG2RAD,
39
34
  RAD2DEG,
40
35
  SEC2RAD,
41
36
  ARCSEC2RAD,
@@ -47,18 +42,17 @@ const {
47
42
  WGS72_EARTH_EQUATORIAL_RADIUS_KM,
48
43
  WGS84_EARTH_EQUATORIAL_RADIUS_KM,
49
44
  MILLIS_PER_DAY,
50
- GEO_ALTITUDE_KM,
51
- } = require("./constants.js");
45
+ GEO_ALTITUDE_KM} from "./constants.js";
52
46
 
53
47
  // Solar Terminator
54
48
  // Returns sun latitude and longitude as -180/180
55
49
  const sunPosAt = (dt) => {
56
50
  const day = new Date(+dt).setUTCHours(0, 0, 0, 0);
57
- const t = solar.century(dt);
51
+ const t = _century(dt);
58
52
  const longitude = ((day - dt) / 864e5) * 360 - 180;
59
53
  return [
60
- solar.declination(t),
61
- (longitude - solar.equationOfTime(t) / 4) % 360,
54
+ declination(t),
55
+ (longitude - equationOfTime(t) / 4) % 360,
62
56
  ];
63
57
  };
64
58
 
@@ -68,7 +62,9 @@ const checkTle = (line1, line2) => {
68
62
  const satrec = twoline2satrec(line1, line2);
69
63
  satrec.epoch = dateToMySqlDate(julianToGregorian(satrec.jdsatepoch)); // Add the epoch
70
64
  const pv = sgp4(satrec, 0);
71
- if (Number.isNaN(pv.position.x) || Number.isNaN(pv.position.y) || Number.isNaN(pv.position.z)) {
65
+ if (Number.isNaN(pv.position.x)
66
+ || Number.isNaN(pv.position.y)
67
+ || Number.isNaN(pv.position.z)) {
72
68
  return false;
73
69
  } else {
74
70
  return satrec;
@@ -646,8 +642,9 @@ const angleBetweenPlanes = (pv1, pv2) => {
646
642
  */
647
643
  const propTo = (satRec, time) => {
648
644
  const pv = propagate(satRec, new Date(time));
649
- if ( !isDefined(pv))
645
+ if ( !isDefined(pv)) {
650
646
  return null;
647
+ }
651
648
  return {
652
649
  p: pv.position,
653
650
  v: pv.velocity,
@@ -660,7 +657,7 @@ const propTo = (satRec, time) => {
660
657
  argp: pv.meanElements.om,
661
658
  meanmotion: pv.meanElements.nm,
662
659
  meananomaly: pv.meanElements.mm,
663
- }
660
+ },
664
661
  };
665
662
  };
666
663
 
@@ -916,25 +913,25 @@ const RaDecToGeodetic = (
916
913
  return {Altitude: null, Latitude: null, Longitude: null};
917
914
  }
918
915
 
919
- const time = squid.EpochUTC.fromDateString(
916
+ const time = EpochUTC.fromDateString(
920
917
  dtStrtoJsDt(ObTimeUtc).toISOString(),
921
918
  );
922
- const sensorGeo = new squid.Geodetic(
919
+ const sensorGeo = new Geodetic(
923
920
  senLat * DEG2RAD,
924
921
  senLon * DEG2RAD,
925
922
  senAltKm,
926
923
  );
927
924
  const sensorItrf = sensorGeo.toITRF(time);
928
925
  const sensorGcrf = sensorItrf.toJ2000();
929
- const sat = new squid.J2000(
926
+ const sat = new J2000(
930
927
  time,
931
- new squid.Vector3D(
928
+ new Vector3D(
932
929
  rangeKm * Math.cos(Ra * DEG2RAD) * Math.cos(Dec * DEG2RAD),
933
930
  rangeKm * Math.sin(Ra * DEG2RAD) * Math.cos(Dec * DEG2RAD),
934
931
  rangeKm * Math.sin(Dec * DEG2RAD),
935
932
  ),
936
933
  );
937
- const satGcrf = new squid.J2000(
934
+ const satGcrf = new J2000(
938
935
  time,
939
936
  sensorGcrf.position.add(sat.position),
940
937
  );
@@ -980,12 +977,12 @@ const estimateSlantRange = (obTime, ra, dec, senLat, senLon, senAltKm) => {
980
977
  const slantU = [-x, -y, -z];
981
978
 
982
979
  // Sensor coordinates
983
- const sensorGeo = new squid.Geodetic(
980
+ const sensorGeo = new Geodetic(
984
981
  senLat * DEG2RAD,
985
982
  senLon * DEG2RAD,
986
983
  senAltKm,
987
984
  );
988
- const time = squid.EpochUTC.fromDateString(obTime);
985
+ const time = EpochUTC.fromDateString(obTime);
989
986
  const sensorItrf = sensorGeo.toITRF(time);
990
987
  const sensorGcrf = sensorItrf.toJ2000();
991
988
 
@@ -1043,7 +1040,7 @@ const AzElToRaDec = (ObTimeUtc, az, el, lat, lon) => {
1043
1040
  return {ra: null, dec: null};
1044
1041
  }
1045
1042
 
1046
- const time = squid.EpochUTC.fromDateString(ObTimeUtc);
1043
+ const time = EpochUTC.fromDateString(ObTimeUtc);
1047
1044
 
1048
1045
  // Convert all angles to radians
1049
1046
  az = az * DEG2RAD;
@@ -1095,23 +1092,23 @@ const RaDecToAzEl = (ObTime, Ra, Dec, SenLat, SenLon) => {
1095
1092
  const SenAlt = 0;
1096
1093
  const SlantRangeKm = 1;
1097
1094
 
1098
- const time = squid.EpochUTC.fromDateString(ObTime);
1099
- const sensorGeo = new squid.Geodetic(
1095
+ const time = EpochUTC.fromDateString(ObTime);
1096
+ const sensorGeo = new Geodetic(
1100
1097
  SenLat * DEG2RAD,
1101
1098
  SenLon * DEG2RAD,
1102
1099
  SenAlt,
1103
1100
  );
1104
1101
  const sensorITRF = sensorGeo.toITRF(time);
1105
1102
  const sensorGCRF = sensorITRF.toJ2000();
1106
- const satellite = new squid.J2000(
1103
+ const satellite = new J2000(
1107
1104
  time,
1108
- new squid.Vector3D(
1105
+ new Vector3D(
1109
1106
  SlantRangeKm * Math.cos(Ra * DEG2RAD) * Math.cos(Dec * DEG2RAD),
1110
1107
  SlantRangeKm * Math.sin(Ra * DEG2RAD) * Math.cos(Dec * DEG2RAD),
1111
1108
  SlantRangeKm * Math.sin(Dec * DEG2RAD),
1112
1109
  ),
1113
1110
  );
1114
- const satGCRF = new squid.J2000(
1111
+ const satGCRF = new J2000(
1115
1112
  time,
1116
1113
  sensorGCRF.position.add(satellite.position),
1117
1114
  );
@@ -3010,7 +3007,7 @@ const isSatInShadow = (epoch, satPos) => {
3010
3007
  let shadowType = "None";
3011
3008
 
3012
3009
  // Getting Sun's apperent longitude and declination at the current epoch
3013
- const century = solar.century(epoch); // Convert date to Julian centuries since J2000 || equal to var tut1 in GetPosition()
3010
+ const century = _century(epoch); // Convert date to Julian centuries since J2000 || equal to var tut1 in GetPosition()
3014
3011
 
3015
3012
  // Variables to solve for Sun Pos in ___ frame
3016
3013
  const lamM = (280.460 + 36000.771*century % 360) * DEG2RAD;
@@ -3108,62 +3105,62 @@ const isSatInShadow = (epoch, satPos) => {
3108
3105
  return shadowType; // return the shadow type
3109
3106
  };
3110
3107
 
3111
- module.exports.CONSTANTS = require("./constants.js");
3112
- module.exports.REGIMES = REGIMES;
3113
- module.exports.julianToGregorian = julianToGregorian;
3114
- module.exports.calcRegime = calcRegime;
3115
- module.exports.altToRegime = altToRegime;
3116
- module.exports.cartesianToRIC = cartesianToRIC;
3117
- module.exports.multiplyVector = multiplyVector;
3118
- module.exports.dist = dist;
3119
- module.exports.angleBetween3DCoords = angleBetween3DCoords;
3120
- module.exports.prop = prop;
3121
- module.exports.propGeodetic = propGeodetic;
3122
- module.exports.getTRIC = getTRIC;
3123
- module.exports.getSunDirection = getSunDirection;
3124
- module.exports.getLonAndDrift = getLonAndDrift;
3125
- module.exports.getRaanPrecession = getRaanPrecession;
3126
- module.exports.checkTle = checkTle;
3127
- module.exports.sunPosAt = sunPosAt;
3128
- module.exports.raDecToGeodetic = RaDecToGeodetic;
3129
- module.exports.getResiduals = GetResiduals;
3130
- module.exports.raDecToAzEl = RaDecToAzEl;
3131
- module.exports.azElToRaDec = AzElToRaDec;
3132
- module.exports.getElsetUdlFromTle = GetElsetUdlFromTle;
3133
- module.exports.satjs = require("satellite.js");
3134
- module.exports.distGeodetic = distGeodetic;
3135
- module.exports.getSemiMajorAxis = getSemiMajorAxis;
3136
- module.exports.angleBetweenPlanes = angleBetweenPlanes;
3137
- module.exports.propagate = propagate;
3138
- module.exports.planeChangeDeltaV = planeChangeDeltaV;
3139
- module.exports.planeChangePureInclinationDeltaV = planeChangePureInclinationDeltaV;
3140
- module.exports.cartesianToKeplerian = cartesianToKeplerian;
3141
- module.exports.keplerianToCartesian = keplerianToCartesian;
3142
- module.exports.getLeoRpoData = getLeoRpoData;
3143
- module.exports.getGeoRpoData = getGeoRpoData;
3144
- module.exports.getGeoShadowZones = getGeoShadowZones;
3145
- module.exports.getGeoLightIntervals = getGeoLightIntervals;
3146
- module.exports.getEclipseStatus = getEclipseStatus;
3147
- module.exports.estimateSlantRange = estimateSlantRange;
3148
- module.exports.calculateNextApogeePerigeeTimes = calculateNextApogeePerigeeTimes;
3149
- module.exports.calculateNextApogeePerigeeTimesWithPropagation
3150
- = calculateNextApogeePerigeeTimesWithPropagation;
3151
- module.exports.calculateLeoPhaseDifference = calculateLeoPhaseDifference;
3152
- module.exports.getLeoWaterfallData = getLeoWaterfallData;
3153
- module.exports.lambertThomsonAlgorithm = lambertThomsonAlgorithm;
3154
- module.exports.detectManeuverMinDv = detectManeuverMinDv;
3155
- module.exports.getInterceptRendezvousMinDv = getInterceptRendezvousMinDv;
3156
-
3157
- module.exports.wrap360 = wrap360;
3158
- module.exports.inWrappedRange = inWrappedRange;
3159
- module.exports.subtractWrapped = subtractWrapped;
3160
- module.exports.propagateRaan = propagateRaan;
3161
- module.exports.getIncDiff = getIncDiff;
3162
- module.exports.getRaanDiff = getRaanDiff;
3163
- module.exports.getRaanClosureRate = getRaanClosureRate;
3164
- module.exports.getRaanAlignTime = getRaanAlignTime;
3165
- module.exports.getRaanAlignTimeStr = getRaanAlignTimeStr;
3166
- module.exports.getRaanDetails = getRaanDetails;
3167
- module.exports.isSatInShadow = isSatInShadow;
3168
-
3169
- module.exports.calculateGeoCrossingTimes = calculateGeoCrossingTimes;
3108
+ import * as CONSTANTS from "./constants.js";
3109
+ export {CONSTANTS};
3110
+ export {REGIMES,
3111
+ julianToGregorian,
3112
+ calcRegime,
3113
+ altToRegime,
3114
+ cartesianToRIC,
3115
+ multiplyVector,
3116
+ dist,
3117
+ angleBetween3DCoords,
3118
+ prop,
3119
+ propGeodetic,
3120
+ getTRIC,
3121
+ getSunDirection,
3122
+ getLonAndDrift,
3123
+ getRaanPrecession,
3124
+ checkTle,
3125
+ sunPosAt,
3126
+ distGeodetic,
3127
+ getSemiMajorAxis,
3128
+ angleBetweenPlanes,
3129
+ propagate,
3130
+ planeChangeDeltaV,
3131
+ planeChangePureInclinationDeltaV,
3132
+ cartesianToKeplerian,
3133
+ keplerianToCartesian,
3134
+ getLeoRpoData,
3135
+ getGeoRpoData,
3136
+ getGeoShadowZones,
3137
+ getGeoLightIntervals,
3138
+ getEclipseStatus,
3139
+ estimateSlantRange,
3140
+ calculateNextApogeePerigeeTimes,
3141
+ calculateNextApogeePerigeeTimesWithPropagation,
3142
+ calculateLeoPhaseDifference,
3143
+ getLeoWaterfallData,
3144
+ lambertThomsonAlgorithm,
3145
+ detectManeuverMinDv,
3146
+ getInterceptRendezvousMinDv,
3147
+ wrap360,
3148
+ inWrappedRange,
3149
+ subtractWrapped,
3150
+ propagateRaan,
3151
+ getIncDiff,
3152
+ getRaanDiff,
3153
+ getRaanClosureRate,
3154
+ getRaanAlignTime,
3155
+ getRaanAlignTimeStr,
3156
+ getRaanDetails,
3157
+ isSatInShadow,
3158
+ calculateGeoCrossingTimes,
3159
+ };
3160
+ export const raDecToGeodetic = RaDecToGeodetic;
3161
+ export const getResiduals = GetResiduals;
3162
+ export const raDecToAzEl = RaDecToAzEl;
3163
+ export const azElToRaDec = AzElToRaDec;
3164
+ export const getElsetUdlFromTle = GetElsetUdlFromTle;
3165
+ import * as satjs from "satellite.js";
3166
+ export {satjs};
@@ -7,11 +7,8 @@
7
7
  */
8
8
 
9
9
  // Import existing libraries instead of defining custom ones
10
- const {
11
- MU,
12
- WGS84_EARTH_EQUATORIAL_RADIUS_KM,
13
- } = require("../constants");
14
- const {NodeVector3D} = require("../NodeVector3D.js");
10
+ import {MU, WGS84_EARTH_EQUATORIAL_RADIUS_KM} from "./constants.js";
11
+ import {NodeVector3D} from "./NodeVector3D.js";
15
12
 
16
13
  // Earth constants using existing constants.js values
17
14
  const EarthConstants = {
@@ -988,14 +985,7 @@ class BallisticPropagator {
988
985
  }
989
986
 
990
987
  // Export for Node.js
991
- if (typeof module !== "undefined" && module.exports) {
992
- module.exports = {
993
- BallisticPropagator,
994
- BallisticPropagatorUtils,
995
- PosVelVec,
996
- EarthConstants,
997
- };
998
- }
988
+ export {BallisticPropagator, BallisticPropagatorUtils, PosVelVec, EarthConstants};
999
989
 
1000
990
  /**
1001
991
  * REFACTORING SUMMARY:
@@ -1,6 +1,7 @@
1
1
  const _ = require("lodash");
2
2
  const {resolve4} = require("dns").promises;
3
3
 
4
+
4
5
  const checkRecord = (hostName) => resolve4(hostName).
5
6
  then((addresss) => !_.isEmpty(addresss)).
6
7
  catch(_.stubFalse);
package/src/constants.js CHANGED
@@ -1,24 +1,21 @@
1
- // Helper math constants
2
- module.exports.DEG2RAD = Math.PI / 180;
3
- module.exports.RAD2DEG = 180 / Math.PI;
4
- module.exports.SEC2RAD = Math.PI / (180.0 * 3600.0); // seconds to radians conversion
5
- module.exports.ARCSEC2RAD = 1 / (3600 * 180 / Math.PI); // arcseconds to radians conversion (1 arcsec = 1/3600 deg = 1/3600 * π/180 rad)
6
- module.exports.MILLIS_PER_DAY = 24 * 60 * 60 * 1000; // Number of milliseconds in a day
1
+ export const DEG2RAD = Math.PI / 180;
2
+ export const RAD2DEG = 180 / Math.PI;
3
+ export const SEC2RAD = Math.PI / (180.0 * 3600.0); // seconds to radians conversion
4
+ export const ARCSEC2RAD = 1 / (3600 * 180 / Math.PI); // arcseconds to radians conversion (1 arcsec = 1/3600 deg = 1/3600 * π/180 rad)
5
+ export const MILLIS_PER_DAY = 24 * 60 * 60 * 1000; // Number of milliseconds in a day
7
6
 
8
- // Sun Constants
9
- module.exports.SUN_RADIUS_KM = 695701.0; // Sun radius in kilometers
10
- module.exports.AU_KM = 149597870.7; // Astronomical Unit in kilometers
7
+ export const SUN_RADIUS_KM = 695701.0; // Sun radius in kilometers
8
+ export const AU_KM = 149597870.7; // Astronomical Unit in kilometers
11
9
 
12
- // Earth Constants
13
- module.exports.MU = 3.986004418e14; // (m^3)/(s^2) WGS-84 Earth Mu
14
- module.exports.GRAV_CONST = 6.6743e-11; // N⋅m2⋅kg−2
15
- module.exports.EARTH_MASS = 5.97219e24; // kg
16
- module.exports.WGS72_EARTH_EQUATORIAL_RADIUS_KM = 6378.135; // in km. Use this when calculations are done with SGP4 which uses WGS72 assumptions.
17
- module.exports.WGS84_EARTH_EQUATORIAL_RADIUS_KM = 6378.137; // in km. Use this for general calculations.
18
- module.exports.EARTH_RADIUS_KM = 6378.135; // still in use for backwards compatibility with old code. Has been removed from nps, ingest, node-common. TODO: refactor from all other js projects using node-common.
19
- module.exports.GEO_ALTITUDE_KM = 35786; // Km
10
+ export const MU = 3.986004418e14; // (m^3)/(s^2) WGS-84 Earth Mu
11
+ export const GRAV_CONST = 6.6743e-11; // N⋅m2⋅kg−2
12
+ export const EARTH_MASS = 5.97219e24; // kg
13
+ export const WGS72_EARTH_EQUATORIAL_RADIUS_KM = 6378.135; // in km. Use this when calculations are done with SGP4 which uses WGS72 assumptions.
14
+ export const WGS84_EARTH_EQUATORIAL_RADIUS_KM = 6378.137; // in km. Use this for general calculations.
15
+ export const EARTH_RADIUS_KM = 6378.135; // still in use for backwards compatibility with old code. Has been removed from nps, ingest, node-common. TODO: refactor from all other js projects using node-common.
16
+ export const GEO_ALTITUDE_KM = 35786; // Km
20
17
 
21
- module.exports.REGIMES = {
18
+ export const REGIMES = {
22
19
  Undetermined: 1,
23
20
  Leo: 2,
24
21
  Heo: 4,
package/src/fixDate.js CHANGED
@@ -1,4 +1,4 @@
1
- const {isValid, parseISO, format} = require("date-fns");
1
+ import {isValid, parseISO, format} from "date-fns";
2
2
 
3
3
  /**
4
4
  * Formats a date how MySQL wants it.
@@ -6,8 +6,8 @@ const {isValid, parseISO, format} = require("date-fns");
6
6
  * @param {string} date in ISO format used by the UDL
7
7
  * @return {string} date formatted for MySQL
8
8
  */
9
- const fixDate = (date) => isValid(parseISO(date))
10
- ? format(parseISO(date.replace("Z", "")), "yyyy-MM-dd HH:mm:ss")
9
+ export const fixDate = (date) => date && isValid(parseISO(date.toString()))
10
+ ? format(parseISO(date.toString().replace("Z", "")), "yyyy-MM-dd HH:mm:ss")
11
11
  : null;
12
12
 
13
13
  /**
@@ -15,14 +15,15 @@ const fixDate = (date) => isValid(parseISO(date))
15
15
  * @param {Date} date
16
16
  * @return {string} Mysql formatted date string
17
17
  */
18
- const dateToMySqlDate = (date) => new Date(date).toISOString().slice(0, 19).replace("T", " ");
18
+ export const dateToMySqlDate
19
+ = (date) => new Date(date).toISOString().slice(0, 19).replace("T", " ");
19
20
 
20
21
  /**
21
22
  * Converts string, int, or Date input into a Date. Adds Z to end of string if not present
22
23
  * @param {*} date
23
24
  * @return {Date} date
24
25
  */
25
- const parseDate = (date) => {
26
+ export const parseDate = (date) => {
26
27
  const corrected = (typeof date !== "string" || date.endsWith("Z")) ? date : (date+"Z");
27
28
  return new Date(corrected);
28
29
  };
@@ -33,7 +34,7 @@ const parseDate = (date) => {
33
34
  * @param {String} dt date time string
34
35
  * @return {Date} Date object in UTC
35
36
  */
36
- const dtStrtoJsDt = (dt) => {
37
+ export const dtStrtoJsDt = (dt) => {
37
38
  if (isSqlDate(dt)) {
38
39
  // MySql date-time format
39
40
  return mySqlDateToJs(dt);
@@ -45,7 +46,7 @@ const dtStrtoJsDt = (dt) => {
45
46
  * @param {String} dt MySql date-time format must be yyyy-mm-dd hh:mm:ss
46
47
  * @return {Date} JS date-time
47
48
  */
48
- const mySqlDateToJs = (dt) => {
49
+ export const mySqlDateToJs = (dt) => {
49
50
  // check the date is in MySQL format
50
51
  if (isSqlDate(dt)) {
51
52
  return new Date(dt+"Z");
@@ -58,12 +59,4 @@ const mySqlDateToJs = (dt) => {
58
59
  * @param {String} dt The date string to test
59
60
  * @return {Boolean} True if is SQL date, false otherwise
60
61
  */
61
- const isSqlDate = (dt) => dt.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d{1,6})?$/);
62
-
63
- module.exports = {
64
- fixDate: fixDate,
65
- parseDate: parseDate,
66
- dateToMySqlDate: dateToMySqlDate,
67
- mySqlDateToJs: mySqlDateToJs,
68
- dtStrtoJsDt: dtStrtoJsDt,
69
- };
62
+ export const isSqlDate = (dt) => dt.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d{1,6})?$/);
package/src/index.js CHANGED
@@ -1,11 +1,47 @@
1
- module.exports = {
2
- ...require("./loggerFactory.js"),
3
- ...require("./transform.js"),
4
- ...require("./checkNetwork.js"),
5
- ...require("./fixDate.js"),
6
- ...require("./astro.js"),
7
- ...require("./launchNominal.js"),
8
- ...require("./LaunchNominalClass.js"),
9
- ...require("./OrbitUtils.js"),
10
- udl: require("./udl"),
1
+ // Proper ES module barrel file
2
+ export * from "./loggerFactory.cjs";
3
+ export * from "./transform.js";
4
+ export * from "./checkNetwork.cjs";
5
+ export * from "./fixDate.js";
6
+ export * from "./astro.js";
7
+ export * from "./launchNominal.js";
8
+ export * from "./LaunchNominalClass.js";
9
+ export * from "./OrbitUtils.js";
10
+ export * from "./PropagateUtils.js";
11
+ export * from "./ballisticPropagator.js";
12
+ export * from "./NodeVector3D.js";
13
+
14
+ // UDL exports are grouped; re-export individually and as namespace if needed
15
+ import * as udl from "./udl.js";
16
+ export * from "./udl.js";
17
+ export {udl};
18
+
19
+ // Optional default aggregate similar to old CommonJS shape
20
+ import * as loggerFactoryNS from "./loggerFactory.cjs";
21
+ import * as transformNS from "./transform.js";
22
+ import * as checkNetworkNS from "./checkNetwork.cjs";
23
+ import * as fixDateNS from "./fixDate.js";
24
+ import * as astroNS from "./astro.js";
25
+ import * as launchNominalNS from "./launchNominal.js";
26
+ import * as LaunchNominalClassNS from "./LaunchNominalClass.js";
27
+ import * as OrbitUtilsNS from "./OrbitUtils.js";
28
+ import * as PropagateUtilsNS from "./PropagateUtils.js";
29
+ import * as ballisticPropagatorNS from "./ballisticPropagator.js";
30
+ import * as NodeVector3DNS from "./NodeVector3D.js";
31
+
32
+ const aggregate = {
33
+ ...loggerFactoryNS,
34
+ ...transformNS,
35
+ ...checkNetworkNS,
36
+ ...fixDateNS,
37
+ ...astroNS,
38
+ ...launchNominalNS,
39
+ ...LaunchNominalClassNS,
40
+ ...OrbitUtilsNS,
41
+ ...PropagateUtilsNS,
42
+ ...ballisticPropagatorNS,
43
+ ...NodeVector3DNS,
44
+ udl,
11
45
  };
46
+
47
+ export default aggregate;
@@ -1,5 +1,4 @@
1
- const {
2
- twoline2satrec,
1
+ import {twoline2satrec,
3
2
  propagate,
4
3
  gstime,
5
4
  eciToGeodetic,
@@ -8,12 +7,9 @@ const {
8
7
  eciToEcf,
9
8
  ecfToLookAngles,
10
9
  degreesLong,
11
- degreesLat,
12
- } = require("satellite.js");
13
- const {distGeodetic} = require("./astro.js");
14
- const {
15
- wrapToRange,
16
- } = require("./utils.js");
10
+ degreesLat} from "satellite.js";
11
+ import {distGeodetic} from "./astro.js";
12
+ import {wrapToRange} from "./utils.js";
17
13
 
18
14
  const notamToCoordArray = (notam) => {
19
15
  const regexPatterns = [
@@ -209,7 +205,4 @@ const getOpopOtop = (
209
205
  };
210
206
  };
211
207
 
212
- module.exports.notamToCoordArray = notamToCoordArray;
213
- module.exports.getBearingFromTle = getBearingFromTle;
214
- module.exports.getBearing = getBearing;
215
- module.exports.getOpopOtop = getOpopOtop;
208
+ export {notamToCoordArray, getBearingFromTle, getBearing, getOpopOtop};
@@ -95,4 +95,4 @@ module.exports.loggerFactory = ({
95
95
  ...additionalData,
96
96
  nameSpace: nameSpace,
97
97
  });
98
- };
98
+ }
package/src/s3.js CHANGED
@@ -1,8 +1,8 @@
1
- const {S3Client, PutObjectCommand, HeadObjectCommand} = require("@aws-sdk/client-s3");
2
- const {readFileSync} = require("fs");
3
- const {basename} = require("path");
4
- const dotenv = require("dotenv");
5
- dotenv.config();
1
+ import {S3Client, PutObjectCommand, HeadObjectCommand} from "@aws-sdk/client-s3";
2
+ import {readFileSync} from "fs";
3
+ import {basename} from "path";
4
+ import {config} from "dotenv";
5
+ config();
6
6
 
7
7
  const s3Client = new S3Client({
8
8
  region: "us-west-1", // Replace with your AWS region
@@ -24,7 +24,7 @@ const s3Client = new S3Client({
24
24
  * @param {Array|Buffer|null} buffer
25
25
  * @return {Promise<Object>}
26
26
  */
27
- module.exports.s3Upload = async (fileName, type = "image/png", buffer = null) => {
27
+ export async function s3Upload(fileName, type = "image/png", buffer = null) {
28
28
  try {
29
29
  const fileContent = buffer ? buffer : readFileSync(fileName);
30
30
  return await s3Client.send(new PutObjectCommand({
@@ -37,9 +37,9 @@ module.exports.s3Upload = async (fileName, type = "image/png", buffer = null) =>
37
37
  console.error("Error uploading file or buffer to S3: ", err);
38
38
  throw err; // Re-throw the error so it can be caught by the calling function if needed
39
39
  }
40
- };
40
+ }
41
41
 
42
- module.exports.doesS3ObjectExist = async (fileName) => {
42
+ export async function doesS3ObjectExist(fileName) {
43
43
  try {
44
44
  // Try to fetch the metadata of the object to check if it exists
45
45
  await s3Client.send(new HeadObjectCommand({
@@ -56,4 +56,4 @@ module.exports.doesS3ObjectExist = async (fileName) => {
56
56
  console.error("Error checking if file exists in S3: ", err);
57
57
  throw err;
58
58
  }
59
- };
59
+ }
package/src/transform.js CHANGED
@@ -1,4 +1,4 @@
1
- const _ = require("lodash");
1
+ import _ from "lodash";
2
2
 
3
3
  const transformObjectKeys = (transform, object, deep = true) => _.cond([
4
4
  [
@@ -32,9 +32,4 @@ const pascalCaseObjectKeys = (transformItem, deep) => transformObjectKeys(
32
32
  deep,
33
33
  );
34
34
 
35
- module.exports = {
36
- transformObjectKeys,
37
- lowerCaseObjectKeys,
38
- pascalCaseObjectKeys,
39
- pascalCase,
40
- };
35
+ export {transformObjectKeys, lowerCaseObjectKeys, pascalCaseObjectKeys, pascalCase};
package/src/udl.js CHANGED
@@ -1,8 +1,8 @@
1
- const {fixDate} = require("./fixDate.js");
2
- const {calcRegime, getElsetUdlFromTle, getLonAndDrift, getRaanPrecession} = require("./astro.js");
3
- const {lowerCaseObjectKeys} = require("./transform.js");
4
- const {isDefined} = require("./utils.js");
5
- const _ = require("lodash");
1
+ import {fixDate} from "./fixDate.js";
2
+ import {calcRegime, getElsetUdlFromTle, getLonAndDrift, getRaanPrecession} from "./astro.js";
3
+ import {lowerCaseObjectKeys} from "./transform.js";
4
+ import {isDefined} from "./utils.js";
5
+ import _ from "lodash";
6
6
 
7
7
  const udlToNpsElset = (udlRow) => {
8
8
  let derivedElset;
@@ -98,7 +98,7 @@ const udlToNpsGroundSite = (udlRow) => ({
98
98
  * @param {Object[]} udlData
99
99
  * @return {Object[]}
100
100
  */
101
- module.exports.formatUdlData = (topic, udlData) => {
101
+ export function formatUdlData(topic, udlData) {
102
102
  switch (topic) {
103
103
  case "Elsets":
104
104
  return _.map(udlData, udlToNpsElset);
@@ -109,7 +109,6 @@ module.exports.formatUdlData = (topic, udlData) => {
109
109
  default:
110
110
  return udlData;
111
111
  }
112
- };
112
+ }
113
113
 
114
- module.exports.udlToNpsElset = udlToNpsElset;
115
- module.exports.udlToNpsGroundSite = udlToNpsGroundSite;
114
+ export {udlToNpsElset, udlToNpsGroundSite};
package/src/utils.js CHANGED
@@ -1,4 +1,4 @@
1
- const {cross, dot, norm} = require("mathjs");
1
+ import {cross, dot, norm} from "mathjs";
2
2
 
3
3
  /**
4
4
  * Wrap angle to [0, 2π] range (0 to 360 degrees)
@@ -381,7 +381,7 @@ const getAngleDiffSigned = (initial, final) => {
381
381
  return sign * minAngle;
382
382
  };
383
383
 
384
- module.exports = {
384
+ export {
385
385
  wrapOneRevUnsigned,
386
386
  wrapHalfRevUnsigned,
387
387
  wrapHalfRev,