@saber-usa/node-common 1.7.7 → 1.7.9-alpha.1
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 +13 -42
- package/package.json +51 -52
- package/src/FrameConverter.js +1120 -1121
- package/src/LLA.js +179 -179
- package/src/LaunchNominalClass.js +772 -753
- package/src/NodeVector3D.js +71 -71
- package/src/OrbitUtils.js +490 -309
- package/src/PropagateUtils.js +100 -100
- package/src/ShadowGEOCalculator.js +203 -203
- package/src/TimeConverter.js +309 -309
- package/src/astro.js +3315 -3301
- package/src/ballisticPropagator.js +1037 -1037
- package/src/constants.js +35 -37
- package/src/fixDate.js +62 -62
- package/src/index.js +47 -47
- package/src/launchNominal.js +208 -208
- package/src/s3.js +59 -59
- package/src/transform.js +35 -35
- package/src/udl.js +231 -116
- package/src/utils.js +406 -406
package/src/udl.js
CHANGED
|
@@ -1,116 +1,231 @@
|
|
|
1
|
-
import {fixDate} from "./fixDate.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
),
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
1
|
+
import {fixDate} from "./fixDate.js";
|
|
2
|
+
import {
|
|
3
|
+
calcRegime,
|
|
4
|
+
getElsetUdlFromTle,
|
|
5
|
+
getLonAndDrift,
|
|
6
|
+
getRaanPrecession,
|
|
7
|
+
raDecToAzEl,
|
|
8
|
+
azElToRaDec,
|
|
9
|
+
raDecToGeodetic,
|
|
10
|
+
estimateSlantRange,
|
|
11
|
+
} from "./astro.js";
|
|
12
|
+
import {lowerCaseObjectKeys} from "./transform.js";
|
|
13
|
+
import {isDefined} from "./utils.js";
|
|
14
|
+
import _ from "lodash";
|
|
15
|
+
|
|
16
|
+
const udlToNpsElset = (udlRow) => {
|
|
17
|
+
let derivedElset;
|
|
18
|
+
try {
|
|
19
|
+
derivedElset = getElsetUdlFromTle(udlRow.line1, udlRow.line2, udlRow.dataMode);
|
|
20
|
+
} catch {
|
|
21
|
+
// invalid TLE
|
|
22
|
+
derivedElset = null;
|
|
23
|
+
}
|
|
24
|
+
const enrichedUdlFields = [];
|
|
25
|
+
const enrichField = (field) => {
|
|
26
|
+
if (derivedElset && (derivedElset[field] || derivedElset[field] === 0)) {
|
|
27
|
+
enrichedUdlFields.push(field);
|
|
28
|
+
return derivedElset[field];
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
};
|
|
32
|
+
const lonAndDrift = getLonAndDrift(udlRow.line1, udlRow.line2);
|
|
33
|
+
|
|
34
|
+
const getElsetValue = (value, defaultValueFunc) => {
|
|
35
|
+
return (isDefined(value)) ? value : defaultValueFunc();
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const npsElset = lowerCaseObjectKeys({
|
|
39
|
+
Satno: getElsetValue(udlRow.satNo, ()=>enrichField("satNo")),
|
|
40
|
+
Epoch: fixDate(getElsetValue(udlRow.epoch, ()=>enrichField("epoch"))),
|
|
41
|
+
MeanMotion: getElsetValue(udlRow.meanMotion, ()=>enrichField("meanMotion")),
|
|
42
|
+
Eccentricity: getElsetValue(udlRow.eccentricity, ()=>enrichField("eccentricity")),
|
|
43
|
+
Inclination: getElsetValue(udlRow.inclination, ()=>enrichField("inclination")),
|
|
44
|
+
Raan: getElsetValue(udlRow.raan, ()=>enrichField("raan")),
|
|
45
|
+
ArgOfPerigee: getElsetValue(udlRow.argOfPerigee, ()=>enrichField("argOfPerigee")),
|
|
46
|
+
MeanAnomaly: getElsetValue(udlRow.meanAnomaly, ()=>enrichField("meanAnomaly")),
|
|
47
|
+
BStar: getElsetValue(udlRow.bStar, ()=>enrichField("bStar")),
|
|
48
|
+
SemiMajorAxis: getElsetValue(udlRow.semiMajorAxis, ()=>enrichField("semiMajorAxis")),
|
|
49
|
+
Period: getElsetValue(udlRow.period, ()=>enrichField("period")),
|
|
50
|
+
Apogee: getElsetValue(udlRow.apogee, ()=>enrichField("apogee")),
|
|
51
|
+
Perigee: getElsetValue(udlRow.perigee, ()=>enrichField("perigee")),
|
|
52
|
+
Line1: getElsetValue(udlRow.line1, ()=>null),
|
|
53
|
+
Line2: getElsetValue(udlRow.line2, ()=>null),
|
|
54
|
+
Source: getElsetValue(udlRow.source, ()=>null),
|
|
55
|
+
DataMode: getElsetValue(udlRow.dataMode, ()=>null),
|
|
56
|
+
CreatedAt: fixDate(getElsetValue(udlRow.createdAt, ()=>null)),
|
|
57
|
+
Origin: getElsetValue(udlRow.origin, ()=>null),
|
|
58
|
+
Algorithm: getElsetValue(udlRow.algorithm, ()=>null),
|
|
59
|
+
Descriptor: getElsetValue(udlRow.descriptor, ()=>null),
|
|
60
|
+
ClassificationMarking: getElsetValue(udlRow.classificationMarking, ()=>null),
|
|
61
|
+
Latitude: lonAndDrift.latitude,
|
|
62
|
+
Longitude: lonAndDrift.longitude,
|
|
63
|
+
LonDriftDegreesPerDay: lonAndDrift.lonDriftDegreesPerDay,
|
|
64
|
+
RaanPrecessionDegreesPerDay: getRaanPrecession(udlRow.line1, udlRow.line2),
|
|
65
|
+
// Ensure we reset all the derived calcs so we know if they have been updated by Sentinel or not.
|
|
66
|
+
MinEccentricity: 0,
|
|
67
|
+
MaxEccentricity: 0,
|
|
68
|
+
MinInclination: 0,
|
|
69
|
+
MaxInclination: 0,
|
|
70
|
+
MinRaan: 0,
|
|
71
|
+
MaxRaan: 0,
|
|
72
|
+
MinArgOfPerigee: 0,
|
|
73
|
+
MaxArgOfPerigee: 0,
|
|
74
|
+
MinSemiMajorAxis: 0,
|
|
75
|
+
MaxSemiMajorAxis: 0,
|
|
76
|
+
});
|
|
77
|
+
npsElset.regime = calcRegime(npsElset);
|
|
78
|
+
npsElset.enrichedudlfields = enrichedUdlFields.join(",");
|
|
79
|
+
return npsElset;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const udlToNpsGroundSite = (udlRow) => ({
|
|
83
|
+
SensorId: _.get(udlRow, "idSensor", null),
|
|
84
|
+
Number: _.get(udlRow, "sensorNumber", null),
|
|
85
|
+
Name: _.get(udlRow, "sensorName", null),
|
|
86
|
+
Source: _.get(udlRow, "source", null),
|
|
87
|
+
Description: null,
|
|
88
|
+
LastObsTime: _.get(udlRow, "sensorStats[0].lastObTime", null),
|
|
89
|
+
CountryCode: _.get(udlRow, "entity.countryCode", "None"),
|
|
90
|
+
Taskable: _.get(udlRow, "entity.taskable", 0),
|
|
91
|
+
Type: _.get(udlRow, "sensorType.id", 0),
|
|
92
|
+
Latitude: _.get(udlRow, "entity.location.lat", 0),
|
|
93
|
+
Longitude: _.get(udlRow, "entity.location.lon", 0),
|
|
94
|
+
KmAboveSeaLevel: _.get(udlRow, "entity.location.altitude", 0),
|
|
95
|
+
MinRangeKm: _.get(udlRow, "sensorcharacteristics[0].minRangeLimit", null),
|
|
96
|
+
MaxRangeKm: _.get(udlRow, "sensorcharacteristics[0].maxRangeLimit", null),
|
|
97
|
+
ClassificationLevel: _.get(
|
|
98
|
+
udlRow,
|
|
99
|
+
"sensorcharacteristics[0].classificationMarking",
|
|
100
|
+
"",
|
|
101
|
+
),
|
|
102
|
+
createdAt: fixDate(_.get(udlRow, "createdAt")),
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Formats the response data based on the topic
|
|
107
|
+
*
|
|
108
|
+
* @param {String} topic
|
|
109
|
+
* @param {Object[]} udlData
|
|
110
|
+
* @return {Object[]}
|
|
111
|
+
*/
|
|
112
|
+
export function formatUdlData(topic, udlData) {
|
|
113
|
+
switch (topic) {
|
|
114
|
+
case "Elsets":
|
|
115
|
+
return _.map(udlData, udlToNpsElset);
|
|
116
|
+
|
|
117
|
+
case "GroundSites":
|
|
118
|
+
return _.map(udlData, udlToNpsGroundSite);
|
|
119
|
+
|
|
120
|
+
default:
|
|
121
|
+
return udlData;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Enriches the Azimuth and Elevation fields of the given object, if needed.
|
|
127
|
+
*
|
|
128
|
+
* @param {object} npsOb - The object to be enriched.
|
|
129
|
+
* @param {array} enrichedFields - The array of already enriched fields.
|
|
130
|
+
* @return {array} The updated array of enriched fields.
|
|
131
|
+
*/
|
|
132
|
+
const enrichAzimuthAndElevation = (npsOb, enrichedFields) => {
|
|
133
|
+
const azel = raDecToAzEl(npsOb.ObTime, npsOb.Ra, npsOb.Dec, npsOb.SenLat, npsOb.SenLon);
|
|
134
|
+
const {Az, El} = azel;
|
|
135
|
+
if (Az && !npsOb.Azimuth) {
|
|
136
|
+
npsOb.Azimuth = Az;
|
|
137
|
+
enrichedFields.push("Azimuth");
|
|
138
|
+
}
|
|
139
|
+
if (El && !npsOb.Elevation) {
|
|
140
|
+
npsOb.Elevation = El;
|
|
141
|
+
enrichedFields.push("Elevation");
|
|
142
|
+
}
|
|
143
|
+
return enrichedFields;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Enriches the Ra and Dec fields of the given object, if needed.
|
|
148
|
+
*
|
|
149
|
+
* @param {object} npsOb - The object to be enriched.
|
|
150
|
+
* @param {array} enrichedFields - The array of already enriched fields.
|
|
151
|
+
* @return {array} The updated array of enriched fields.
|
|
152
|
+
*/
|
|
153
|
+
const enrichRaAndDec = (npsOb, enrichedFields) => {
|
|
154
|
+
const radec = azElToRaDec(
|
|
155
|
+
npsOb.ObTime,
|
|
156
|
+
npsOb.Azimuth,
|
|
157
|
+
npsOb.Elevation,
|
|
158
|
+
npsOb.SenLat,
|
|
159
|
+
npsOb.SenLon,
|
|
160
|
+
);
|
|
161
|
+
const {ra, dec} = radec;
|
|
162
|
+
if (ra && !npsOb.Ra) {
|
|
163
|
+
npsOb.Ra = ra;
|
|
164
|
+
enrichedFields.push("Ra");
|
|
165
|
+
}
|
|
166
|
+
if (dec && !npsOb.Dec) {
|
|
167
|
+
npsOb.Dec = dec;
|
|
168
|
+
enrichedFields.push("Dec");
|
|
169
|
+
}
|
|
170
|
+
return enrichedFields;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Enriches the GeoLon field of the given object, if needed.
|
|
175
|
+
*
|
|
176
|
+
* @param {object} npsOb - The object to be enriched.
|
|
177
|
+
* @param {array} enrichedFields - The array of already enriched fields.
|
|
178
|
+
* @return {array} The updated array of enriched fields.
|
|
179
|
+
*/
|
|
180
|
+
const enrichGeoLon = (npsOb, enrichedFields) => {
|
|
181
|
+
// In the absence of range, we estimate the slant range from the sensor to the sat
|
|
182
|
+
const slantRange = npsOb.Range ?? npsOb.GeoRange ?? estimateSlantRange(
|
|
183
|
+
npsOb.ObTime,
|
|
184
|
+
npsOb.Ra, npsOb.Dec,
|
|
185
|
+
npsOb.SenLat, npsOb.SenLon, npsOb.SenAlt,
|
|
186
|
+
);
|
|
187
|
+
const geodetic= raDecToGeodetic(
|
|
188
|
+
npsOb.ObTime,
|
|
189
|
+
npsOb.Ra,
|
|
190
|
+
npsOb.Dec,
|
|
191
|
+
npsOb.SenLat,
|
|
192
|
+
npsOb.SenLon,
|
|
193
|
+
npsOb.SenAlt,
|
|
194
|
+
slantRange,
|
|
195
|
+
);
|
|
196
|
+
npsOb.GeoLon = geodetic.Longitude;
|
|
197
|
+
npsOb.GeoLat = geodetic.Latitude;
|
|
198
|
+
npsOb.GeoRange = slantRange;
|
|
199
|
+
if (!npsOb.Range && !npsOb.GeoRange) enrichedFields.push("GeoRange");
|
|
200
|
+
if (npsOb.GeoLon) enrichedFields.push("GeoLon");
|
|
201
|
+
if (npsOb.GeoLat) enrichedFields.push("GeoLat");
|
|
202
|
+
return enrichedFields;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Enriches the given object by adding missing fields.
|
|
207
|
+
* This is the main function that uses helper functions to enrich different fields of the object.
|
|
208
|
+
*
|
|
209
|
+
* @param {object} npsOb - The object to be enriched.
|
|
210
|
+
* @return {object} The enriched object.
|
|
211
|
+
*/
|
|
212
|
+
const enrichUdlFields = (npsOb) => {
|
|
213
|
+
let enrichedFields = [];
|
|
214
|
+
|
|
215
|
+
if (!npsOb.Azimuth || !npsOb.Elevation) {
|
|
216
|
+
enrichedFields = enrichAzimuthAndElevation(npsOb, enrichedFields);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (!npsOb.Ra || !npsOb.Dec) {
|
|
220
|
+
enrichedFields = enrichRaAndDec(npsOb, enrichedFields);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (!npsOb.GeoLon) {
|
|
224
|
+
enrichedFields = enrichGeoLon(npsOb, enrichedFields);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
npsOb.EnrichedFields = enrichedFields.join(",");
|
|
228
|
+
return npsOb;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
export {udlToNpsElset, udlToNpsGroundSite, enrichUdlFields};
|