gnss-js 1.1.0 → 1.3.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 +38 -0
- package/dist/{chunk-7NOFXKET.js → chunk-HVXYFUCB.js} +72 -257
- package/dist/chunk-L5OUUNLT.js +198 -0
- package/dist/{chunk-PGHDJFQK.js → chunk-ZCNXERQ2.js} +67 -3
- package/dist/constants.js +22 -22
- package/dist/frames.cjs +250 -0
- package/dist/frames.d.cts +56 -0
- package/dist/frames.d.ts +56 -0
- package/dist/frames.js +222 -0
- package/dist/index.cjs +64 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +85 -81
- package/dist/orbit.cjs +149 -2
- package/dist/orbit.d.cts +38 -1
- package/dist/orbit.d.ts +38 -1
- package/dist/orbit.js +4 -1
- package/dist/positioning.cjs +565 -0
- package/dist/positioning.d.cts +68 -0
- package/dist/positioning.d.ts +68 -0
- package/dist/positioning.js +206 -0
- package/dist/rtcm3.js +2 -2
- package/dist/time.js +20 -18
- package/package.json +11 -1
- package/dist/{chunk-JDO3LEPC.js → chunk-7EEWQ5DU.js} +5 -5
package/README.md
CHANGED
|
@@ -51,6 +51,44 @@ const { distance } = vincenty(
|
|
|
51
51
|
// distance in meters, angles in radians
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
### Visibility / pass prediction
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { computeVisibility } from 'gnss-js/orbit';
|
|
58
|
+
|
|
59
|
+
const vis = computeVisibility(ephemerides, rxEcef, startMs, endMs, 300, 10);
|
|
60
|
+
// vis.passes: rise/peak/set per satellite; vis.pdop / vis.visibleCount
|
|
61
|
+
// per epoch; vis.elevation[prn]: elevation timeline for plotting.
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Single-point positioning
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { solveSpp, ionoFree } from 'gnss-js/positioning';
|
|
68
|
+
|
|
69
|
+
const sol = solveSpp(pseudoranges, ephemerides, epochMs);
|
|
70
|
+
// sol.position (ECEF m), per-system clock biases, DOP, residuals,
|
|
71
|
+
// rejected outliers. ~10 m single-frequency; use ionoFree(p1, p2, f1, f2)
|
|
72
|
+
// pseudoranges for metre-level.
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Reference frame transformations
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { transformFrame, dateToEpoch } from 'gnss-js/frames';
|
|
79
|
+
|
|
80
|
+
// ETRS89 (ETRF2000) station coordinates → ITRF2020 at epoch 2010.5
|
|
81
|
+
const itrf = transformFrame(
|
|
82
|
+
[3924687.7039, 301132.7618, 5001910.7712],
|
|
83
|
+
'ETRF2000',
|
|
84
|
+
'ITRF2020',
|
|
85
|
+
2010.5
|
|
86
|
+
);
|
|
87
|
+
// Time-dependent 14-parameter Helmert (IERS/EPSG parameters);
|
|
88
|
+
// supports ITRF88–ITRF2020, ETRF2000/2014/2020, NAD83(2011).
|
|
89
|
+
// 'WGS84' is treated as an ITRF2020 alias (standard GNSS practice).
|
|
90
|
+
```
|
|
91
|
+
|
|
54
92
|
### RINEX parsing
|
|
55
93
|
|
|
56
94
|
```ts
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DAYS_MJD2000_MJD,
|
|
3
|
-
DAYS_MJD_JULIAN,
|
|
4
2
|
MILLISECONDS_GPS_TAI,
|
|
5
3
|
MILLISECONDS_IN_DAY,
|
|
6
4
|
MILLISECONDS_IN_HOUR,
|
|
@@ -8,98 +6,13 @@ import {
|
|
|
8
6
|
MILLISECONDS_IN_SECOND,
|
|
9
7
|
MILLISECONDS_IN_WEEK,
|
|
10
8
|
MILLISECONDS_TT_TAI,
|
|
11
|
-
RINEX_CODES,
|
|
12
9
|
START_BDS_TIME,
|
|
13
10
|
START_GAL_TIME,
|
|
14
11
|
START_GLO_LEAP,
|
|
15
12
|
START_GPS_TIME,
|
|
16
|
-
|
|
17
|
-
START_NTP_TIME,
|
|
18
|
-
START_TAI_TIME
|
|
13
|
+
START_NTP_TIME
|
|
19
14
|
} from "./chunk-LEEU5OIO.js";
|
|
20
15
|
|
|
21
|
-
// src/types/enums.ts
|
|
22
|
-
var Scale = /* @__PURE__ */ ((Scale2) => {
|
|
23
|
-
Scale2[Scale2["TAI"] = 0] = "TAI";
|
|
24
|
-
Scale2[Scale2["TT"] = 1] = "TT";
|
|
25
|
-
Scale2[Scale2["GPS"] = 2] = "GPS";
|
|
26
|
-
Scale2[Scale2["UTC"] = 3] = "UTC";
|
|
27
|
-
return Scale2;
|
|
28
|
-
})(Scale || {});
|
|
29
|
-
|
|
30
|
-
// src/time/functions.ts
|
|
31
|
-
function getTimeOfDay(date) {
|
|
32
|
-
return date.getTime() - Date.UTC(
|
|
33
|
-
date.getUTCFullYear(),
|
|
34
|
-
date.getUTCMonth(),
|
|
35
|
-
date.getUTCDate(),
|
|
36
|
-
0,
|
|
37
|
-
0,
|
|
38
|
-
0
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
function getDateFromTimeOfDay(timeOfDay, dateRaw) {
|
|
42
|
-
return new Date(
|
|
43
|
-
Date.UTC(
|
|
44
|
-
dateRaw.getUTCFullYear(),
|
|
45
|
-
dateRaw.getUTCMonth(),
|
|
46
|
-
dateRaw.getUTCDate(),
|
|
47
|
-
0,
|
|
48
|
-
0,
|
|
49
|
-
0
|
|
50
|
-
) + timeOfDay
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
function getDayOfYear(date) {
|
|
54
|
-
return Math.floor(
|
|
55
|
-
(date.getTime() - Date.UTC(date.getUTCFullYear())) / MILLISECONDS_IN_DAY
|
|
56
|
-
) + 1;
|
|
57
|
-
}
|
|
58
|
-
function getDateFromDayOfYear(dayOfYear, date) {
|
|
59
|
-
return new Date(
|
|
60
|
-
Date.UTC(
|
|
61
|
-
date.getUTCFullYear(),
|
|
62
|
-
0,
|
|
63
|
-
1,
|
|
64
|
-
date.getUTCHours(),
|
|
65
|
-
date.getUTCMinutes(),
|
|
66
|
-
date.getUTCSeconds(),
|
|
67
|
-
date.getUTCMilliseconds()
|
|
68
|
-
) + (dayOfYear - 1) * MILLISECONDS_IN_DAY
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
function getDayOfWeek(date) {
|
|
72
|
-
return date.getUTCDay();
|
|
73
|
-
}
|
|
74
|
-
function getDateFromDayOfWeek(dayOfWeek, dateRaw) {
|
|
75
|
-
if (dayOfWeek < 0 || dayOfWeek > 6)
|
|
76
|
-
throw new Error("Day of week must be a value between 0 and 7");
|
|
77
|
-
return new Date(
|
|
78
|
-
dateRaw.getTime() + (dayOfWeek - dateRaw.getUTCDay()) * MILLISECONDS_IN_DAY
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
function getDateFromHourCode(hourCode, date) {
|
|
82
|
-
const hour = RINEX_CODES.indexOf(hourCode);
|
|
83
|
-
if (hour === -1)
|
|
84
|
-
throw new Error("Hour code must be a lowercase letter between a and x");
|
|
85
|
-
const newDate = new Date(date.getTime());
|
|
86
|
-
newDate.setUTCHours(hour);
|
|
87
|
-
return newDate;
|
|
88
|
-
}
|
|
89
|
-
function getHourCode(date) {
|
|
90
|
-
return RINEX_CODES[date.getUTCHours()];
|
|
91
|
-
}
|
|
92
|
-
function getWeekOfYear(date) {
|
|
93
|
-
const target = new Date(
|
|
94
|
-
Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())
|
|
95
|
-
);
|
|
96
|
-
const dayNr = (target.getUTCDay() + 6) % 7;
|
|
97
|
-
target.setUTCDate(target.getUTCDate() - dayNr + 3);
|
|
98
|
-
const firstThursday = new Date(Date.UTC(target.getUTCFullYear(), 0, 4));
|
|
99
|
-
const dayDiff = (target.getTime() - firstThursday.getTime()) / (86400 * 1e3);
|
|
100
|
-
return 1 + Math.floor(dayDiff / 7) + 1;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
16
|
// src/time/time-difference.ts
|
|
104
17
|
function getTimeDifference(startDate, finalDate) {
|
|
105
18
|
return Math.floor(finalDate.getTime() - startDate.getTime());
|
|
@@ -139,6 +52,76 @@ function getTimeDifferenceFromObject(timeDifferenceObject) {
|
|
|
139
52
|
return getTimeDifferenceFromSeconds(seconds) + getTimeDifferenceFromMinutes(minutes) + getTimeDifferenceFromHours(hours) + getTimeDifferenceFromDays(days);
|
|
140
53
|
}
|
|
141
54
|
|
|
55
|
+
// src/time/gnss.ts
|
|
56
|
+
function getGpsTime(date) {
|
|
57
|
+
return date.getTime() - START_GPS_TIME.getTime();
|
|
58
|
+
}
|
|
59
|
+
function getDateFromGpsTime(gpsTime) {
|
|
60
|
+
return new Date(gpsTime + START_GPS_TIME.getTime());
|
|
61
|
+
}
|
|
62
|
+
function getGalTime(date) {
|
|
63
|
+
return date.getTime() - START_GAL_TIME.getTime();
|
|
64
|
+
}
|
|
65
|
+
function getDateFromGalTime(galTime) {
|
|
66
|
+
return new Date(galTime + START_GAL_TIME.getTime());
|
|
67
|
+
}
|
|
68
|
+
function getBdsTime(date) {
|
|
69
|
+
return date.getTime() - START_BDS_TIME.getTime();
|
|
70
|
+
}
|
|
71
|
+
function getDateFromBdsTime(bdsTime) {
|
|
72
|
+
return new Date(bdsTime + START_BDS_TIME.getTime());
|
|
73
|
+
}
|
|
74
|
+
function getUnixTime(date) {
|
|
75
|
+
const utc_date = getUtcDate(date);
|
|
76
|
+
return utc_date.getTime();
|
|
77
|
+
}
|
|
78
|
+
function getDateFromUnixTime(unixTime) {
|
|
79
|
+
return getDateFromUtc(new Date(unixTime));
|
|
80
|
+
}
|
|
81
|
+
function getWeekNumber(date) {
|
|
82
|
+
return Math.floor(getGpsTime(date) / MILLISECONDS_IN_WEEK);
|
|
83
|
+
}
|
|
84
|
+
function getTimeOfWeek(date) {
|
|
85
|
+
return getGpsTime(date) % MILLISECONDS_IN_WEEK;
|
|
86
|
+
}
|
|
87
|
+
function getDateFromGpsData(weekNumber, timeOfWeek) {
|
|
88
|
+
return new Date(
|
|
89
|
+
weekNumber * MILLISECONDS_IN_WEEK + timeOfWeek + START_GPS_TIME.getTime()
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
function getTaiDate(date) {
|
|
93
|
+
return new Date(date.getTime() + MILLISECONDS_GPS_TAI);
|
|
94
|
+
}
|
|
95
|
+
function getDateFromTai(tai_date) {
|
|
96
|
+
return new Date(tai_date.getTime() - MILLISECONDS_GPS_TAI);
|
|
97
|
+
}
|
|
98
|
+
function getTtDate(date) {
|
|
99
|
+
return new Date(date.getTime() + MILLISECONDS_GPS_TAI + MILLISECONDS_TT_TAI);
|
|
100
|
+
}
|
|
101
|
+
function getDateFromTt(tt_date) {
|
|
102
|
+
return new Date(
|
|
103
|
+
tt_date.getTime() - MILLISECONDS_GPS_TAI - MILLISECONDS_TT_TAI
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
function getGloN4(date) {
|
|
107
|
+
return Math.floor((date.getUTCFullYear() - START_GLO_LEAP.getFullYear()) / 4);
|
|
108
|
+
}
|
|
109
|
+
function getGloNA(date) {
|
|
110
|
+
const n4 = getGloN4(date);
|
|
111
|
+
const init4YearPeriod = new Date(START_GLO_LEAP);
|
|
112
|
+
init4YearPeriod.setUTCFullYear(init4YearPeriod.getUTCFullYear() + n4 * 4);
|
|
113
|
+
return Math.floor(getTimeDifference(init4YearPeriod, date) / MILLISECONDS_IN_DAY) + 1;
|
|
114
|
+
}
|
|
115
|
+
function getDateFromGloN(n4, na, tod) {
|
|
116
|
+
const date = new Date(START_GLO_LEAP);
|
|
117
|
+
date.setFullYear(date.getUTCFullYear() + n4 * 4);
|
|
118
|
+
date.setTime(date.getTime() + (na - 1) * MILLISECONDS_IN_DAY + tod);
|
|
119
|
+
return date;
|
|
120
|
+
}
|
|
121
|
+
function getNtpTime(date) {
|
|
122
|
+
return getTaiDate(date).getTime() - START_NTP_TIME.getTime();
|
|
123
|
+
}
|
|
124
|
+
|
|
142
125
|
// src/time/utc.ts
|
|
143
126
|
var LEAP_SECONDS_TABLE = [
|
|
144
127
|
[3692217600, 37],
|
|
@@ -228,167 +211,7 @@ function getDateFromUtc(utc_date) {
|
|
|
228
211
|
return gps_date;
|
|
229
212
|
}
|
|
230
213
|
|
|
231
|
-
// src/time/gnss.ts
|
|
232
|
-
function getGpsTime(date) {
|
|
233
|
-
return date.getTime() - START_GPS_TIME.getTime();
|
|
234
|
-
}
|
|
235
|
-
function getDateFromGpsTime(gpsTime) {
|
|
236
|
-
return new Date(gpsTime + START_GPS_TIME.getTime());
|
|
237
|
-
}
|
|
238
|
-
function getGalTime(date) {
|
|
239
|
-
return date.getTime() - START_GAL_TIME.getTime();
|
|
240
|
-
}
|
|
241
|
-
function getDateFromGalTime(galTime) {
|
|
242
|
-
return new Date(galTime + START_GAL_TIME.getTime());
|
|
243
|
-
}
|
|
244
|
-
function getBdsTime(date) {
|
|
245
|
-
return date.getTime() - START_BDS_TIME.getTime();
|
|
246
|
-
}
|
|
247
|
-
function getDateFromBdsTime(bdsTime) {
|
|
248
|
-
return new Date(bdsTime + START_BDS_TIME.getTime());
|
|
249
|
-
}
|
|
250
|
-
function getUnixTime(date) {
|
|
251
|
-
const utc_date = getUtcDate(date);
|
|
252
|
-
return utc_date.getTime();
|
|
253
|
-
}
|
|
254
|
-
function getDateFromUnixTime(unixTime) {
|
|
255
|
-
return getDateFromUtc(new Date(unixTime));
|
|
256
|
-
}
|
|
257
|
-
function getWeekNumber(date) {
|
|
258
|
-
return Math.floor(getGpsTime(date) / MILLISECONDS_IN_WEEK);
|
|
259
|
-
}
|
|
260
|
-
function getTimeOfWeek(date) {
|
|
261
|
-
return getGpsTime(date) % MILLISECONDS_IN_WEEK;
|
|
262
|
-
}
|
|
263
|
-
function getDateFromGpsData(weekNumber, timeOfWeek) {
|
|
264
|
-
return new Date(
|
|
265
|
-
weekNumber * MILLISECONDS_IN_WEEK + timeOfWeek + START_GPS_TIME.getTime()
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
function getTaiDate(date) {
|
|
269
|
-
return new Date(date.getTime() + MILLISECONDS_GPS_TAI);
|
|
270
|
-
}
|
|
271
|
-
function getDateFromTai(tai_date) {
|
|
272
|
-
return new Date(tai_date.getTime() - MILLISECONDS_GPS_TAI);
|
|
273
|
-
}
|
|
274
|
-
function getTtDate(date) {
|
|
275
|
-
return new Date(date.getTime() + MILLISECONDS_GPS_TAI + MILLISECONDS_TT_TAI);
|
|
276
|
-
}
|
|
277
|
-
function getDateFromTt(tt_date) {
|
|
278
|
-
return new Date(
|
|
279
|
-
tt_date.getTime() - MILLISECONDS_GPS_TAI - MILLISECONDS_TT_TAI
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
function getGloN4(date) {
|
|
283
|
-
return Math.floor((date.getUTCFullYear() - START_GLO_LEAP.getFullYear()) / 4);
|
|
284
|
-
}
|
|
285
|
-
function getGloNA(date) {
|
|
286
|
-
const n4 = getGloN4(date);
|
|
287
|
-
const init4YearPeriod = new Date(START_GLO_LEAP);
|
|
288
|
-
init4YearPeriod.setUTCFullYear(init4YearPeriod.getUTCFullYear() + n4 * 4);
|
|
289
|
-
return Math.floor(getTimeDifference(init4YearPeriod, date) / MILLISECONDS_IN_DAY) + 1;
|
|
290
|
-
}
|
|
291
|
-
function getDateFromGloN(n4, na, tod) {
|
|
292
|
-
const date = new Date(START_GLO_LEAP);
|
|
293
|
-
date.setFullYear(date.getUTCFullYear() + n4 * 4);
|
|
294
|
-
date.setTime(date.getTime() + (na - 1) * MILLISECONDS_IN_DAY + tod);
|
|
295
|
-
return date;
|
|
296
|
-
}
|
|
297
|
-
function getNtpTime(date) {
|
|
298
|
-
return getTaiDate(date).getTime() - START_NTP_TIME.getTime();
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// src/time/rinex.ts
|
|
302
|
-
function getRINEX(date) {
|
|
303
|
-
const seconds = date.getUTCSeconds();
|
|
304
|
-
const milliseconds = date.getUTCMilliseconds();
|
|
305
|
-
const fractionalSeconds = (milliseconds / MILLISECONDS_IN_SECOND).toFixed(7).slice(1);
|
|
306
|
-
const formatted = `> ${date.getUTCFullYear()} ${String(
|
|
307
|
-
date.getUTCMonth() + 1
|
|
308
|
-
).padStart(2, "0")} ${String(date.getUTCDate()).padStart(2, "0")} ${String(
|
|
309
|
-
date.getUTCHours()
|
|
310
|
-
).padStart(2, "0")} ${String(date.getUTCMinutes()).padStart(
|
|
311
|
-
2,
|
|
312
|
-
"0"
|
|
313
|
-
)} ${String(seconds).padStart(2, "0")}${fractionalSeconds}`;
|
|
314
|
-
return formatted;
|
|
315
|
-
}
|
|
316
|
-
function getDateFromRINEX(rinex) {
|
|
317
|
-
const year = Number.parseInt(rinex.substring(2, 6));
|
|
318
|
-
const month = Number.parseInt(rinex.substring(7, 9)) - 1;
|
|
319
|
-
const day = Number.parseInt(rinex.substring(10, 12));
|
|
320
|
-
const hour = Number.parseInt(rinex.substring(13, 15));
|
|
321
|
-
const minute = Number.parseInt(rinex.substring(16, 18));
|
|
322
|
-
const second = Number.parseInt(rinex.substring(19, 21));
|
|
323
|
-
const millisecond = Number.parseInt(rinex.substring(22, 29)) / 1e4;
|
|
324
|
-
const date = new Date(
|
|
325
|
-
Date.UTC(year, month, day, hour, minute, second, millisecond)
|
|
326
|
-
);
|
|
327
|
-
return date;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// src/time/julian.ts
|
|
331
|
-
function getJulianDate(date, scale = 1 /* TT */) {
|
|
332
|
-
if (scale === 0 /* TAI */) {
|
|
333
|
-
return (date.getTime() - START_TAI_TIME.getTime()) / MILLISECONDS_IN_DAY + START_JULIAN_TAI;
|
|
334
|
-
}
|
|
335
|
-
if (scale === 2 /* GPS */) {
|
|
336
|
-
return (date.getTime() - START_TAI_TIME.getTime() - MILLISECONDS_GPS_TAI) / MILLISECONDS_IN_DAY + START_JULIAN_TAI;
|
|
337
|
-
}
|
|
338
|
-
if (scale === 3 /* UTC */) {
|
|
339
|
-
return (date.getTime() - START_TAI_TIME.getTime() - getLeap(date) * MILLISECONDS_IN_SECOND) / MILLISECONDS_IN_DAY + START_JULIAN_TAI;
|
|
340
|
-
}
|
|
341
|
-
return (date.getTime() - START_TAI_TIME.getTime() + MILLISECONDS_TT_TAI) / MILLISECONDS_IN_DAY + START_JULIAN_TAI;
|
|
342
|
-
}
|
|
343
|
-
function getDateFromJulianDate(julianDate, scale = 1 /* TT */) {
|
|
344
|
-
if (scale === 0 /* TAI */) {
|
|
345
|
-
return new Date(
|
|
346
|
-
(julianDate - START_JULIAN_TAI) * MILLISECONDS_IN_DAY + START_TAI_TIME.getTime()
|
|
347
|
-
);
|
|
348
|
-
}
|
|
349
|
-
if (scale === 2 /* GPS */) {
|
|
350
|
-
return new Date(
|
|
351
|
-
(julianDate - START_JULIAN_TAI) * MILLISECONDS_IN_DAY + START_TAI_TIME.getTime() + MILLISECONDS_GPS_TAI
|
|
352
|
-
);
|
|
353
|
-
}
|
|
354
|
-
if (scale === 3 /* UTC */) {
|
|
355
|
-
const utc_date = new Date(
|
|
356
|
-
(julianDate - START_JULIAN_TAI) * MILLISECONDS_IN_DAY + START_TAI_TIME.getTime()
|
|
357
|
-
);
|
|
358
|
-
const tai_date = new Date(
|
|
359
|
-
utc_date.getTime() + getLeap(utc_date) * MILLISECONDS_IN_SECOND
|
|
360
|
-
);
|
|
361
|
-
const leap_seconds = getLeap(getDateFromTai(tai_date));
|
|
362
|
-
return new Date(utc_date.getTime() + leap_seconds * MILLISECONDS_IN_SECOND);
|
|
363
|
-
}
|
|
364
|
-
return new Date(
|
|
365
|
-
(julianDate - START_JULIAN_TAI) * MILLISECONDS_IN_DAY + START_TAI_TIME.getTime() - MILLISECONDS_TT_TAI
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
function getMJD(date, scale = 1 /* TT */) {
|
|
369
|
-
return getJulianDate(date, scale) - DAYS_MJD_JULIAN;
|
|
370
|
-
}
|
|
371
|
-
function getDateFromMJD(mjd, scale = 1 /* TT */) {
|
|
372
|
-
return getDateFromJulianDate(mjd + DAYS_MJD_JULIAN, scale);
|
|
373
|
-
}
|
|
374
|
-
function getMJD2000(date, scale = 1 /* TT */) {
|
|
375
|
-
return getMJD(date, scale) - DAYS_MJD2000_MJD;
|
|
376
|
-
}
|
|
377
|
-
function getDateFromMJD2000(mjd2000, scale = 1 /* TT */) {
|
|
378
|
-
return getDateFromMJD(mjd2000 + DAYS_MJD2000_MJD, scale);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
214
|
export {
|
|
382
|
-
Scale,
|
|
383
|
-
getTimeOfDay,
|
|
384
|
-
getDateFromTimeOfDay,
|
|
385
|
-
getDayOfYear,
|
|
386
|
-
getDateFromDayOfYear,
|
|
387
|
-
getDayOfWeek,
|
|
388
|
-
getDateFromDayOfWeek,
|
|
389
|
-
getDateFromHourCode,
|
|
390
|
-
getHourCode,
|
|
391
|
-
getWeekOfYear,
|
|
392
215
|
getTimeDifference,
|
|
393
216
|
getSecondsFromTimeDifference,
|
|
394
217
|
getMinutesFromTimeDifference,
|
|
@@ -421,13 +244,5 @@ export {
|
|
|
421
244
|
getGloN4,
|
|
422
245
|
getGloNA,
|
|
423
246
|
getDateFromGloN,
|
|
424
|
-
getNtpTime
|
|
425
|
-
getRINEX,
|
|
426
|
-
getDateFromRINEX,
|
|
427
|
-
getJulianDate,
|
|
428
|
-
getDateFromJulianDate,
|
|
429
|
-
getMJD,
|
|
430
|
-
getDateFromMJD,
|
|
431
|
-
getMJD2000,
|
|
432
|
-
getDateFromMJD2000
|
|
247
|
+
getNtpTime
|
|
433
248
|
};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getDateFromTai,
|
|
3
|
+
getLeap
|
|
4
|
+
} from "./chunk-HVXYFUCB.js";
|
|
5
|
+
import {
|
|
6
|
+
DAYS_MJD2000_MJD,
|
|
7
|
+
DAYS_MJD_JULIAN,
|
|
8
|
+
MILLISECONDS_GPS_TAI,
|
|
9
|
+
MILLISECONDS_IN_DAY,
|
|
10
|
+
MILLISECONDS_IN_SECOND,
|
|
11
|
+
MILLISECONDS_TT_TAI,
|
|
12
|
+
RINEX_CODES,
|
|
13
|
+
START_JULIAN_TAI,
|
|
14
|
+
START_TAI_TIME
|
|
15
|
+
} from "./chunk-LEEU5OIO.js";
|
|
16
|
+
|
|
17
|
+
// src/types/enums.ts
|
|
18
|
+
var Scale = /* @__PURE__ */ ((Scale2) => {
|
|
19
|
+
Scale2[Scale2["TAI"] = 0] = "TAI";
|
|
20
|
+
Scale2[Scale2["TT"] = 1] = "TT";
|
|
21
|
+
Scale2[Scale2["GPS"] = 2] = "GPS";
|
|
22
|
+
Scale2[Scale2["UTC"] = 3] = "UTC";
|
|
23
|
+
return Scale2;
|
|
24
|
+
})(Scale || {});
|
|
25
|
+
|
|
26
|
+
// src/time/functions.ts
|
|
27
|
+
function getTimeOfDay(date) {
|
|
28
|
+
return date.getTime() - Date.UTC(
|
|
29
|
+
date.getUTCFullYear(),
|
|
30
|
+
date.getUTCMonth(),
|
|
31
|
+
date.getUTCDate(),
|
|
32
|
+
0,
|
|
33
|
+
0,
|
|
34
|
+
0
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
function getDateFromTimeOfDay(timeOfDay, dateRaw) {
|
|
38
|
+
return new Date(
|
|
39
|
+
Date.UTC(
|
|
40
|
+
dateRaw.getUTCFullYear(),
|
|
41
|
+
dateRaw.getUTCMonth(),
|
|
42
|
+
dateRaw.getUTCDate(),
|
|
43
|
+
0,
|
|
44
|
+
0,
|
|
45
|
+
0
|
|
46
|
+
) + timeOfDay
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
function getDayOfYear(date) {
|
|
50
|
+
return Math.floor(
|
|
51
|
+
(date.getTime() - Date.UTC(date.getUTCFullYear())) / MILLISECONDS_IN_DAY
|
|
52
|
+
) + 1;
|
|
53
|
+
}
|
|
54
|
+
function getDateFromDayOfYear(dayOfYear, date) {
|
|
55
|
+
return new Date(
|
|
56
|
+
Date.UTC(
|
|
57
|
+
date.getUTCFullYear(),
|
|
58
|
+
0,
|
|
59
|
+
1,
|
|
60
|
+
date.getUTCHours(),
|
|
61
|
+
date.getUTCMinutes(),
|
|
62
|
+
date.getUTCSeconds(),
|
|
63
|
+
date.getUTCMilliseconds()
|
|
64
|
+
) + (dayOfYear - 1) * MILLISECONDS_IN_DAY
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
function getDayOfWeek(date) {
|
|
68
|
+
return date.getUTCDay();
|
|
69
|
+
}
|
|
70
|
+
function getDateFromDayOfWeek(dayOfWeek, dateRaw) {
|
|
71
|
+
if (dayOfWeek < 0 || dayOfWeek > 6)
|
|
72
|
+
throw new Error("Day of week must be a value between 0 and 7");
|
|
73
|
+
return new Date(
|
|
74
|
+
dateRaw.getTime() + (dayOfWeek - dateRaw.getUTCDay()) * MILLISECONDS_IN_DAY
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
function getDateFromHourCode(hourCode, date) {
|
|
78
|
+
const hour = RINEX_CODES.indexOf(hourCode);
|
|
79
|
+
if (hour === -1)
|
|
80
|
+
throw new Error("Hour code must be a lowercase letter between a and x");
|
|
81
|
+
const newDate = new Date(date.getTime());
|
|
82
|
+
newDate.setUTCHours(hour);
|
|
83
|
+
return newDate;
|
|
84
|
+
}
|
|
85
|
+
function getHourCode(date) {
|
|
86
|
+
return RINEX_CODES[date.getUTCHours()];
|
|
87
|
+
}
|
|
88
|
+
function getWeekOfYear(date) {
|
|
89
|
+
const target = new Date(
|
|
90
|
+
Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())
|
|
91
|
+
);
|
|
92
|
+
const dayNr = (target.getUTCDay() + 6) % 7;
|
|
93
|
+
target.setUTCDate(target.getUTCDate() - dayNr + 3);
|
|
94
|
+
const firstThursday = new Date(Date.UTC(target.getUTCFullYear(), 0, 4));
|
|
95
|
+
const dayDiff = (target.getTime() - firstThursday.getTime()) / (86400 * 1e3);
|
|
96
|
+
return 1 + Math.floor(dayDiff / 7) + 1;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/time/rinex.ts
|
|
100
|
+
function getRINEX(date) {
|
|
101
|
+
const seconds = date.getUTCSeconds();
|
|
102
|
+
const milliseconds = date.getUTCMilliseconds();
|
|
103
|
+
const fractionalSeconds = (milliseconds / MILLISECONDS_IN_SECOND).toFixed(7).slice(1);
|
|
104
|
+
const formatted = `> ${date.getUTCFullYear()} ${String(
|
|
105
|
+
date.getUTCMonth() + 1
|
|
106
|
+
).padStart(2, "0")} ${String(date.getUTCDate()).padStart(2, "0")} ${String(
|
|
107
|
+
date.getUTCHours()
|
|
108
|
+
).padStart(2, "0")} ${String(date.getUTCMinutes()).padStart(
|
|
109
|
+
2,
|
|
110
|
+
"0"
|
|
111
|
+
)} ${String(seconds).padStart(2, "0")}${fractionalSeconds}`;
|
|
112
|
+
return formatted;
|
|
113
|
+
}
|
|
114
|
+
function getDateFromRINEX(rinex) {
|
|
115
|
+
const year = Number.parseInt(rinex.substring(2, 6));
|
|
116
|
+
const month = Number.parseInt(rinex.substring(7, 9)) - 1;
|
|
117
|
+
const day = Number.parseInt(rinex.substring(10, 12));
|
|
118
|
+
const hour = Number.parseInt(rinex.substring(13, 15));
|
|
119
|
+
const minute = Number.parseInt(rinex.substring(16, 18));
|
|
120
|
+
const second = Number.parseInt(rinex.substring(19, 21));
|
|
121
|
+
const millisecond = Number.parseInt(rinex.substring(22, 29)) / 1e4;
|
|
122
|
+
const date = new Date(
|
|
123
|
+
Date.UTC(year, month, day, hour, minute, second, millisecond)
|
|
124
|
+
);
|
|
125
|
+
return date;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/time/julian.ts
|
|
129
|
+
function getJulianDate(date, scale = 1 /* TT */) {
|
|
130
|
+
if (scale === 0 /* TAI */) {
|
|
131
|
+
return (date.getTime() - START_TAI_TIME.getTime()) / MILLISECONDS_IN_DAY + START_JULIAN_TAI;
|
|
132
|
+
}
|
|
133
|
+
if (scale === 2 /* GPS */) {
|
|
134
|
+
return (date.getTime() - START_TAI_TIME.getTime() - MILLISECONDS_GPS_TAI) / MILLISECONDS_IN_DAY + START_JULIAN_TAI;
|
|
135
|
+
}
|
|
136
|
+
if (scale === 3 /* UTC */) {
|
|
137
|
+
return (date.getTime() - START_TAI_TIME.getTime() - getLeap(date) * MILLISECONDS_IN_SECOND) / MILLISECONDS_IN_DAY + START_JULIAN_TAI;
|
|
138
|
+
}
|
|
139
|
+
return (date.getTime() - START_TAI_TIME.getTime() + MILLISECONDS_TT_TAI) / MILLISECONDS_IN_DAY + START_JULIAN_TAI;
|
|
140
|
+
}
|
|
141
|
+
function getDateFromJulianDate(julianDate, scale = 1 /* TT */) {
|
|
142
|
+
if (scale === 0 /* TAI */) {
|
|
143
|
+
return new Date(
|
|
144
|
+
(julianDate - START_JULIAN_TAI) * MILLISECONDS_IN_DAY + START_TAI_TIME.getTime()
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
if (scale === 2 /* GPS */) {
|
|
148
|
+
return new Date(
|
|
149
|
+
(julianDate - START_JULIAN_TAI) * MILLISECONDS_IN_DAY + START_TAI_TIME.getTime() + MILLISECONDS_GPS_TAI
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
if (scale === 3 /* UTC */) {
|
|
153
|
+
const utc_date = new Date(
|
|
154
|
+
(julianDate - START_JULIAN_TAI) * MILLISECONDS_IN_DAY + START_TAI_TIME.getTime()
|
|
155
|
+
);
|
|
156
|
+
const tai_date = new Date(
|
|
157
|
+
utc_date.getTime() + getLeap(utc_date) * MILLISECONDS_IN_SECOND
|
|
158
|
+
);
|
|
159
|
+
const leap_seconds = getLeap(getDateFromTai(tai_date));
|
|
160
|
+
return new Date(utc_date.getTime() + leap_seconds * MILLISECONDS_IN_SECOND);
|
|
161
|
+
}
|
|
162
|
+
return new Date(
|
|
163
|
+
(julianDate - START_JULIAN_TAI) * MILLISECONDS_IN_DAY + START_TAI_TIME.getTime() - MILLISECONDS_TT_TAI
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
function getMJD(date, scale = 1 /* TT */) {
|
|
167
|
+
return getJulianDate(date, scale) - DAYS_MJD_JULIAN;
|
|
168
|
+
}
|
|
169
|
+
function getDateFromMJD(mjd, scale = 1 /* TT */) {
|
|
170
|
+
return getDateFromJulianDate(mjd + DAYS_MJD_JULIAN, scale);
|
|
171
|
+
}
|
|
172
|
+
function getMJD2000(date, scale = 1 /* TT */) {
|
|
173
|
+
return getMJD(date, scale) - DAYS_MJD2000_MJD;
|
|
174
|
+
}
|
|
175
|
+
function getDateFromMJD2000(mjd2000, scale = 1 /* TT */) {
|
|
176
|
+
return getDateFromMJD(mjd2000 + DAYS_MJD2000_MJD, scale);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export {
|
|
180
|
+
Scale,
|
|
181
|
+
getTimeOfDay,
|
|
182
|
+
getDateFromTimeOfDay,
|
|
183
|
+
getDayOfYear,
|
|
184
|
+
getDateFromDayOfYear,
|
|
185
|
+
getDayOfWeek,
|
|
186
|
+
getDateFromDayOfWeek,
|
|
187
|
+
getDateFromHourCode,
|
|
188
|
+
getHourCode,
|
|
189
|
+
getWeekOfYear,
|
|
190
|
+
getRINEX,
|
|
191
|
+
getDateFromRINEX,
|
|
192
|
+
getJulianDate,
|
|
193
|
+
getDateFromJulianDate,
|
|
194
|
+
getMJD,
|
|
195
|
+
getDateFromMJD,
|
|
196
|
+
getMJD2000,
|
|
197
|
+
getDateFromMJD2000
|
|
198
|
+
};
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getGpsLeap
|
|
3
|
+
} from "./chunk-HVXYFUCB.js";
|
|
1
4
|
import {
|
|
2
5
|
ecefToGeodetic
|
|
3
6
|
} from "./chunk-37QNKGTC.js";
|
|
@@ -230,7 +233,8 @@ function selectEphemeris(ephemerides, prn, timeMs) {
|
|
|
230
233
|
}
|
|
231
234
|
function computeSatPosition(eph, timeMs) {
|
|
232
235
|
if (eph.system === "R" || eph.system === "S") {
|
|
233
|
-
|
|
236
|
+
const leapMs = getGpsLeap(new Date(timeMs)) * 1e3;
|
|
237
|
+
return glonassPosition(eph, (timeMs - leapMs) / 1e3);
|
|
234
238
|
}
|
|
235
239
|
const GPS_EPOCH = START_GPS_TIME.getTime();
|
|
236
240
|
const gpsSeconds = (timeMs - GPS_EPOCH) / 1e3;
|
|
@@ -403,7 +407,7 @@ function ephInfoToEphemeris(info) {
|
|
|
403
407
|
};
|
|
404
408
|
}
|
|
405
409
|
function computeLiveSkyPositions(ephemerides, rxPos, cn0Map) {
|
|
406
|
-
const now = Date.now();
|
|
410
|
+
const now = Date.now() + getGpsLeap(/* @__PURE__ */ new Date()) * 1e3;
|
|
407
411
|
const result = [];
|
|
408
412
|
const [rxX, rxY, rxZ] = rxPos;
|
|
409
413
|
const [rxLat, rxLon] = ecefToGeodetic(rxX, rxY, rxZ);
|
|
@@ -436,6 +440,65 @@ function computeLiveSkyPositions(ephemerides, rxPos, cn0Map) {
|
|
|
436
440
|
}
|
|
437
441
|
return result;
|
|
438
442
|
}
|
|
443
|
+
function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, elevationMaskDeg = 10) {
|
|
444
|
+
const stepMs = stepSec * 1e3;
|
|
445
|
+
const times = [];
|
|
446
|
+
for (let t = startMs; t <= endMs; t += stepMs) times.push(t);
|
|
447
|
+
const maskRad = elevationMaskDeg * Math.PI / 180;
|
|
448
|
+
const all = computeAllPositions(ephemerides, times, rxPos);
|
|
449
|
+
const elevation = {};
|
|
450
|
+
const visibleCount = new Array(times.length).fill(0);
|
|
451
|
+
const pdop = new Array(times.length).fill(null);
|
|
452
|
+
const visiblePerEpoch = times.map(() => []);
|
|
453
|
+
for (const prn of all.prns) {
|
|
454
|
+
const series = all.positions[prn];
|
|
455
|
+
elevation[prn] = series.map((p) => p ? p.el : null);
|
|
456
|
+
for (let i = 0; i < series.length; i++) {
|
|
457
|
+
const p = series[i];
|
|
458
|
+
if (p && p.el >= maskRad) {
|
|
459
|
+
visibleCount[i]++;
|
|
460
|
+
visiblePerEpoch[i].push({ az: p.az, el: p.el });
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
for (let i = 0; i < times.length; i++) {
|
|
465
|
+
const dop = computeDop(visiblePerEpoch[i]);
|
|
466
|
+
pdop[i] = dop ? dop.pdop : null;
|
|
467
|
+
}
|
|
468
|
+
const passes = [];
|
|
469
|
+
for (const prn of all.prns) {
|
|
470
|
+
const els = elevation[prn];
|
|
471
|
+
let start = -1;
|
|
472
|
+
let peakEl = -Infinity;
|
|
473
|
+
let peakTime = 0;
|
|
474
|
+
for (let i = 0; i <= els.length; i++) {
|
|
475
|
+
const el = i < els.length ? els[i] : null;
|
|
476
|
+
const above = el !== null && el !== void 0 && el >= maskRad;
|
|
477
|
+
if (above) {
|
|
478
|
+
if (start === -1) {
|
|
479
|
+
start = i;
|
|
480
|
+
peakEl = -Infinity;
|
|
481
|
+
}
|
|
482
|
+
if (el > peakEl) {
|
|
483
|
+
peakEl = el;
|
|
484
|
+
peakTime = times[i];
|
|
485
|
+
}
|
|
486
|
+
} else if (start !== -1) {
|
|
487
|
+
passes.push({
|
|
488
|
+
prn,
|
|
489
|
+
system: prn[0],
|
|
490
|
+
rise: times[start],
|
|
491
|
+
set: times[i - 1],
|
|
492
|
+
peakTime,
|
|
493
|
+
peakEl
|
|
494
|
+
});
|
|
495
|
+
start = -1;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
passes.sort((a, b) => a.rise - b.rise);
|
|
500
|
+
return { times, elevation, visibleCount, pdop, passes };
|
|
501
|
+
}
|
|
439
502
|
|
|
440
503
|
export {
|
|
441
504
|
keplerPosition,
|
|
@@ -446,5 +509,6 @@ export {
|
|
|
446
509
|
computeSatPosition,
|
|
447
510
|
navTimesFromEph,
|
|
448
511
|
computeAllPositions,
|
|
449
|
-
computeLiveSkyPositions
|
|
512
|
+
computeLiveSkyPositions,
|
|
513
|
+
computeVisibility
|
|
450
514
|
};
|