@saber-usa/node-common 1.7.2 → 1.7.4
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/package.json +1 -1
- package/src/FrameConverter.js +52 -0
- package/src/LaunchNominalClass.js +11 -61
- package/src/astro.js +3 -0
package/package.json
CHANGED
package/src/FrameConverter.js
CHANGED
|
@@ -31,6 +31,58 @@ const Earth = {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
class FrameConverter {
|
|
34
|
+
/**
|
|
35
|
+
* Helper method to transform a vector using a Matrix3D
|
|
36
|
+
* @param {Vector3D} vector - Vector to transform
|
|
37
|
+
* @param {Matrix3D} matrix - Matrix to use for transformation
|
|
38
|
+
* @return {Vector3D} Transformed vector
|
|
39
|
+
*/
|
|
40
|
+
static transformVector(vector, matrix) {
|
|
41
|
+
// Manual matrix-vector multiplication since pious-squid has issues
|
|
42
|
+
const x = matrix.get(0, 0) * vector.x
|
|
43
|
+
+ matrix.get(0, 1) * vector.y + matrix.get(0, 2) * vector.z;
|
|
44
|
+
const y = matrix.get(1, 0) * vector.x
|
|
45
|
+
+ matrix.get(1, 1) * vector.y + matrix.get(1, 2) * vector.z;
|
|
46
|
+
const z = matrix.get(2, 0) * vector.x
|
|
47
|
+
+ matrix.get(2, 1) * vector.y + matrix.get(2, 2) * vector.z;
|
|
48
|
+
return new Vector3D(x, y, z);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Rotate a vector around an axis by an angle (Rodrigues' rotation formula)
|
|
53
|
+
* @param {Vector3D} vector - Vector to rotate
|
|
54
|
+
* @param {Vector3D} axis - Axis to rotate around (should be normalized)
|
|
55
|
+
* @param {number} angleRad - Angle in radians
|
|
56
|
+
* @return {Vector3D} Rotated vector
|
|
57
|
+
*/
|
|
58
|
+
static rotateVector(vector, axis, angleRad) {
|
|
59
|
+
// Ensure axis is normalized
|
|
60
|
+
const k = axis.normalized();
|
|
61
|
+
const v = vector;
|
|
62
|
+
const cosTheta = Math.cos(angleRad);
|
|
63
|
+
const sinTheta = Math.sin(angleRad);
|
|
64
|
+
|
|
65
|
+
// Rodrigues' rotation formula:
|
|
66
|
+
// v_rot = v*cos(θ) + (k × v)*sin(θ) + k*(k·v)*(1-cos(θ))
|
|
67
|
+
|
|
68
|
+
// k × v (cross product)
|
|
69
|
+
const kCrossV = new Vector3D(
|
|
70
|
+
k.y * v.z - k.z * v.y,
|
|
71
|
+
k.z * v.x - k.x * v.z,
|
|
72
|
+
k.x * v.y - k.y * v.x,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// k·v (dot product)
|
|
76
|
+
const kDotV = k.x * v.x + k.y * v.y + k.z * v.z;
|
|
77
|
+
|
|
78
|
+
// Final rotation
|
|
79
|
+
return new Vector3D(
|
|
80
|
+
v.x * cosTheta + kCrossV.x * sinTheta + k.x * kDotV * (1 - cosTheta),
|
|
81
|
+
v.y * cosTheta + kCrossV.y * sinTheta + k.y * kDotV * (1 - cosTheta),
|
|
82
|
+
v.z * cosTheta + kCrossV.z * sinTheta + k.z * kDotV * (1 - cosTheta),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
34
86
|
/**
|
|
35
87
|
* Helper to transpose a Matrix3D
|
|
36
88
|
* @param {Matrix3D} m - The matrix to transpose
|
|
@@ -21,57 +21,7 @@ const ReferenceFrame = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
class LaunchNominalClass {
|
|
24
|
-
|
|
25
|
-
* Helper method to transform a vector using a Matrix3D
|
|
26
|
-
* @param {Vector3D} vector - Vector to transform
|
|
27
|
-
* @param {Matrix3D} matrix - Matrix to use for transformation
|
|
28
|
-
* @return {Vector3D} Transformed vector
|
|
29
|
-
*/
|
|
30
|
-
static transformVector(vector, matrix) {
|
|
31
|
-
// Manual matrix-vector multiplication since pious-squid has issues
|
|
32
|
-
const x = matrix.get(0, 0) * vector.x
|
|
33
|
-
+ matrix.get(0, 1) * vector.y + matrix.get(0, 2) * vector.z;
|
|
34
|
-
const y = matrix.get(1, 0) * vector.x
|
|
35
|
-
+ matrix.get(1, 1) * vector.y + matrix.get(1, 2) * vector.z;
|
|
36
|
-
const z = matrix.get(2, 0) * vector.x
|
|
37
|
-
+ matrix.get(2, 1) * vector.y + matrix.get(2, 2) * vector.z;
|
|
38
|
-
return new Vector3D(x, y, z);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Rotate a vector around an axis by an angle (Rodrigues' rotation formula)
|
|
43
|
-
* @param {Vector3D} vector - Vector to rotate
|
|
44
|
-
* @param {Vector3D} axis - Axis to rotate around (should be normalized)
|
|
45
|
-
* @param {number} angleRad - Angle in radians
|
|
46
|
-
* @return {Vector3D} Rotated vector
|
|
47
|
-
*/
|
|
48
|
-
static rotateVector(vector, axis, angleRad) {
|
|
49
|
-
// Ensure axis is normalized
|
|
50
|
-
const k = axis.normalized();
|
|
51
|
-
const v = vector;
|
|
52
|
-
const cosTheta = Math.cos(angleRad);
|
|
53
|
-
const sinTheta = Math.sin(angleRad);
|
|
54
|
-
|
|
55
|
-
// Rodrigues' rotation formula:
|
|
56
|
-
// v_rot = v*cos(θ) + (k × v)*sin(θ) + k*(k·v)*(1-cos(θ))
|
|
57
|
-
|
|
58
|
-
// k × v (cross product)
|
|
59
|
-
const kCrossV = new Vector3D(
|
|
60
|
-
k.y * v.z - k.z * v.y,
|
|
61
|
-
k.z * v.x - k.x * v.z,
|
|
62
|
-
k.x * v.y - k.y * v.x,
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
// k·v (dot product)
|
|
66
|
-
const kDotV = k.x * v.x + k.y * v.y + k.z * v.z;
|
|
67
|
-
|
|
68
|
-
// Final rotation
|
|
69
|
-
return new Vector3D(
|
|
70
|
-
v.x * cosTheta + kCrossV.x * sinTheta + k.x * kDotV * (1 - cosTheta),
|
|
71
|
-
v.y * cosTheta + kCrossV.y * sinTheta + k.y * kDotV * (1 - cosTheta),
|
|
72
|
-
v.z * cosTheta + kCrossV.z * sinTheta + k.z * kDotV * (1 - cosTheta),
|
|
73
|
-
);
|
|
74
|
-
}
|
|
24
|
+
|
|
75
25
|
|
|
76
26
|
/** Get position at a given time in specified reference frame
|
|
77
27
|
*
|
|
@@ -82,7 +32,7 @@ class LaunchNominalClass {
|
|
|
82
32
|
static getPositionJ2000(utc, posITRF) {
|
|
83
33
|
const transformMatrix = FrameConverter.itrfToJ2000(utc);
|
|
84
34
|
|
|
85
|
-
return
|
|
35
|
+
return FrameConverter.transformVector(posITRF, transformMatrix);
|
|
86
36
|
}
|
|
87
37
|
|
|
88
38
|
/** Generate a circular launch nominal.
|
|
@@ -427,16 +377,16 @@ class LaunchNominalClass {
|
|
|
427
377
|
// Cardinal directions in ITRF frame
|
|
428
378
|
// South vector (1, 0, 0) in SEZ
|
|
429
379
|
const southSEZ = new Vector3D(1, 0, 0);
|
|
430
|
-
const south =
|
|
380
|
+
const south = FrameConverter.transformVector(southSEZ, sez2ecef).normalized();
|
|
431
381
|
const north = south.scale(-1);
|
|
432
382
|
|
|
433
383
|
// Zenith vector (0, 0, 1) in SEZ
|
|
434
384
|
const zenithSEZ = new Vector3D(0, 0, 1);
|
|
435
|
-
const zenith =
|
|
385
|
+
const zenith = FrameConverter.transformVector(zenithSEZ, sez2ecef).normalized();
|
|
436
386
|
const nadir = zenith.scale(-1);
|
|
437
387
|
|
|
438
|
-
const northJ2000 =
|
|
439
|
-
const nadirJ2000 =
|
|
388
|
+
const northJ2000 = FrameConverter.transformVector(north, itrf2j2000).normalized();
|
|
389
|
+
const nadirJ2000 = FrameConverter.transformVector(nadir, itrf2j2000).normalized();
|
|
440
390
|
|
|
441
391
|
// Position of site in J2000 scaled by the orbit altitude
|
|
442
392
|
const siteJ2000 = this.getPositionJ2000(orbitInsertionTime, positionITRF);
|
|
@@ -446,7 +396,7 @@ class LaunchNominalClass {
|
|
|
446
396
|
// North vector rotated by azimuth along nadir vector scaled by the velocity of a circular orbit
|
|
447
397
|
const rLength = Math.sqrt(r.x * r.x + r.y * r.y + r.z * r.z);
|
|
448
398
|
const velocityMagnitude = Math.sqrt(mu / rLength);
|
|
449
|
-
const velocityDirection =
|
|
399
|
+
const velocityDirection = FrameConverter.rotateVector(northJ2000, nadirJ2000, azimuthRad);
|
|
450
400
|
const v = velocityDirection.scale(velocityMagnitude);
|
|
451
401
|
|
|
452
402
|
return {
|
|
@@ -502,7 +452,7 @@ class LaunchNominalClass {
|
|
|
502
452
|
};
|
|
503
453
|
|
|
504
454
|
const rtnToEci = FrameConverter.rtnToEci(stateAtM1.position, stateAtM1.velocity);
|
|
505
|
-
const dv1eci =
|
|
455
|
+
const dv1eci = FrameConverter.transformVector(burn1.dv, rtnToEci);
|
|
506
456
|
|
|
507
457
|
const state1 = {
|
|
508
458
|
position: new NodeVector3D(
|
|
@@ -564,7 +514,7 @@ class LaunchNominalClass {
|
|
|
564
514
|
};
|
|
565
515
|
|
|
566
516
|
const rtnToEci2 = FrameConverter.rtnToEci(stateAtM2.position, stateAtM2.velocity);
|
|
567
|
-
const dv1eci2 =
|
|
517
|
+
const dv1eci2 = FrameConverter.transformVector(burn2.dv, rtnToEci2);
|
|
568
518
|
|
|
569
519
|
const state2 = {
|
|
570
520
|
position: new NodeVector3D(
|
|
@@ -769,8 +719,8 @@ class LaunchNominalOutput {
|
|
|
769
719
|
|
|
770
720
|
if (!elements) {
|
|
771
721
|
const j2000ToTeme = FrameConverter.getTransform("J2000", "TEME", epoch);
|
|
772
|
-
const posTeme =
|
|
773
|
-
const velTeme =
|
|
722
|
+
const posTeme = FrameConverter.transformVector(pos, j2000ToTeme);
|
|
723
|
+
const velTeme = FrameConverter.transformVector(vel, j2000ToTeme);
|
|
774
724
|
elements = OrbitUtils.stateVectorToElements(
|
|
775
725
|
[posTeme.x, posTeme.y, posTeme.z],
|
|
776
726
|
[velTeme.x, velTeme.y, velTeme.z]);
|
package/src/astro.js
CHANGED
|
@@ -779,6 +779,7 @@ const getTRIC = (pEphem, tEphem) => {
|
|
|
779
779
|
const isPrimaryEpoch = []; // Whether point is primary epoch
|
|
780
780
|
const isTargetEpoch = []; // Whether point is target epoch
|
|
781
781
|
const sources = []; // Sources
|
|
782
|
+
const datamodes = []; // Data modes
|
|
782
783
|
|
|
783
784
|
for (let j = 0; j < pEphem.length; j++) {
|
|
784
785
|
const prim = pEphem[j];
|
|
@@ -788,6 +789,7 @@ const getTRIC = (pEphem, tEphem) => {
|
|
|
788
789
|
isPrimaryEpoch.push((!!prim.isEpoch)+""); // it can't be a boolean for some reason
|
|
789
790
|
isTargetEpoch.push((!!target.isEpoch)+"");
|
|
790
791
|
sources.push(prim.source + ", " + target.source);
|
|
792
|
+
datamodes.push(prim.datamode + ", " + target.datamode);
|
|
791
793
|
|
|
792
794
|
// Calculate RIC values.
|
|
793
795
|
const deltaR = {
|
|
@@ -828,6 +830,7 @@ const getTRIC = (pEphem, tEphem) => {
|
|
|
828
830
|
isPrimaryEpoch,
|
|
829
831
|
isTargetEpoch,
|
|
830
832
|
sources,
|
|
833
|
+
datamodes,
|
|
831
834
|
targetVisibility,
|
|
832
835
|
primaryVisibility,
|
|
833
836
|
};
|