gnss-js 2.8.1 → 2.9.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/dist/{chunk-T5M3LVBJ.js → chunk-7T5DLVZL.js} +52 -18
- package/dist/{chunk-F6KOFOXN.js → chunk-NOGA5KD7.js} +1 -1
- package/dist/index.cjs +72 -35
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +8 -2
- package/dist/orbit.cjs +55 -18
- package/dist/orbit.d.cts +44 -6
- package/dist/orbit.d.ts +44 -6
- package/dist/orbit.js +7 -1
- package/dist/positioning.cjs +56 -29
- package/dist/positioning.js +2 -2
- package/package.json +1 -1
|
@@ -37,6 +37,42 @@ function invertMatrix(A) {
|
|
|
37
37
|
return M.map((row) => row.slice(n));
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
// src/orbit/validity.ts
|
|
41
|
+
var H = 36e5;
|
|
42
|
+
var MIN = 6e4;
|
|
43
|
+
var EPHEMERIS_VALIDITY_MS = {
|
|
44
|
+
G: 2 * H,
|
|
45
|
+
J: 2 * H,
|
|
46
|
+
E: 2.5 * H,
|
|
47
|
+
C: 90 * MIN,
|
|
48
|
+
R: 15 * MIN,
|
|
49
|
+
I: 2 * H,
|
|
50
|
+
S: 6 * MIN
|
|
51
|
+
};
|
|
52
|
+
function tocDistanceMs(eph, tGpsMs) {
|
|
53
|
+
const t = eph.system === "R" || eph.system === "S" ? tGpsMs - getGpsLeap(new Date(tGpsMs)) * 1e3 : tGpsMs;
|
|
54
|
+
return Math.abs(eph.tocDate.getTime() - t);
|
|
55
|
+
}
|
|
56
|
+
function isEphemerisValid(eph, tGpsMs) {
|
|
57
|
+
const w = EPHEMERIS_VALIDITY_MS[eph.system];
|
|
58
|
+
return w !== void 0 && tocDistanceMs(eph, tGpsMs) <= w;
|
|
59
|
+
}
|
|
60
|
+
function nearestValidEphemeris(ephs, tGpsMs) {
|
|
61
|
+
if (!ephs) return null;
|
|
62
|
+
let best = null;
|
|
63
|
+
let bestDt = Infinity;
|
|
64
|
+
for (const eph of ephs) {
|
|
65
|
+
const dt = tocDistanceMs(eph, tGpsMs);
|
|
66
|
+
const w = EPHEMERIS_VALIDITY_MS[eph.system];
|
|
67
|
+
if (w === void 0 || dt > w) continue;
|
|
68
|
+
if (dt < bestDt) {
|
|
69
|
+
bestDt = dt;
|
|
70
|
+
best = eph;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return best;
|
|
74
|
+
}
|
|
75
|
+
|
|
40
76
|
// src/orbit/almanac.ts
|
|
41
77
|
var GM_GPS = 3986005e8;
|
|
42
78
|
var GM_GAL = 3986004418e5;
|
|
@@ -409,24 +445,30 @@ function dopClock(prn) {
|
|
|
409
445
|
return sys === "J" || sys === "S" ? "G" : sys;
|
|
410
446
|
}
|
|
411
447
|
function computeDop(satAzEls) {
|
|
412
|
-
const
|
|
413
|
-
const
|
|
448
|
+
const perClock = /* @__PURE__ */ new Map();
|
|
449
|
+
for (const s of satAzEls) {
|
|
450
|
+
const c = dopClock(s.prn);
|
|
451
|
+
perClock.set(c, (perClock.get(c) ?? 0) + 1);
|
|
452
|
+
}
|
|
453
|
+
const sats = perClock.size > 1 ? satAzEls.filter((s) => perClock.get(dopClock(s.prn)) > 1) : satAzEls;
|
|
454
|
+
const n = sats.length;
|
|
455
|
+
const clocks = [...new Set(sats.map((s) => dopClock(s.prn)))];
|
|
414
456
|
const m = 3 + clocks.length;
|
|
415
457
|
if (n < Math.max(4, m)) return null;
|
|
416
|
-
const
|
|
417
|
-
for (const { az, el, prn } of
|
|
458
|
+
const H2 = [];
|
|
459
|
+
for (const { az, el, prn } of sats) {
|
|
418
460
|
const cosEl = Math.cos(el);
|
|
419
461
|
const row = [cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el)];
|
|
420
462
|
const clock = dopClock(prn);
|
|
421
463
|
for (const c of clocks) row.push(c === clock ? 1 : 0);
|
|
422
|
-
|
|
464
|
+
H2.push(row);
|
|
423
465
|
}
|
|
424
466
|
const HtH = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
425
467
|
for (let i = 0; i < m; i++) {
|
|
426
468
|
for (let j = 0; j < m; j++) {
|
|
427
469
|
let sum = 0;
|
|
428
470
|
for (let k = 0; k < n; k++) {
|
|
429
|
-
sum +=
|
|
471
|
+
sum += H2[k][i] * H2[k][j];
|
|
430
472
|
}
|
|
431
473
|
HtH[i][j] = sum;
|
|
432
474
|
}
|
|
@@ -527,18 +569,7 @@ function computeAllPositions(ephemerides, times, rxPos) {
|
|
|
527
569
|
return { prns, times, positions };
|
|
528
570
|
}
|
|
529
571
|
function selectBest(ephs, timeMs) {
|
|
530
|
-
|
|
531
|
-
let bestDt = Infinity;
|
|
532
|
-
for (const eph of ephs) {
|
|
533
|
-
const dt = Math.abs(timeMs - eph.tocDate.getTime());
|
|
534
|
-
const maxAge = eph.system === "R" || eph.system === "S" ? 18e5 : 4 * 36e5;
|
|
535
|
-
if (dt > maxAge) continue;
|
|
536
|
-
if (dt < bestDt) {
|
|
537
|
-
bestDt = dt;
|
|
538
|
-
best = eph;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
return best;
|
|
572
|
+
return nearestValidEphemeris(ephs, timeMs);
|
|
542
573
|
}
|
|
543
574
|
var GPS_EPOCH_MS2 = START_GPS_TIME.getTime();
|
|
544
575
|
var MS_PER_WEEK = 7 * 864e5;
|
|
@@ -780,6 +811,9 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
780
811
|
|
|
781
812
|
export {
|
|
782
813
|
invertMatrix,
|
|
814
|
+
EPHEMERIS_VALIDITY_MS,
|
|
815
|
+
isEphemerisValid,
|
|
816
|
+
nearestValidEphemeris,
|
|
783
817
|
almanacEpochMs,
|
|
784
818
|
almanacSatPosition,
|
|
785
819
|
glonassAlmanacEpochMs,
|
package/dist/index.cjs
CHANGED
|
@@ -36,6 +36,7 @@ __export(src_exports, {
|
|
|
36
36
|
DELTA_GLO_L2: () => DELTA_GLO_L2,
|
|
37
37
|
DUAL_FREQ_PAIRS: () => DUAL_FREQ_PAIRS,
|
|
38
38
|
EMPTY_WARNINGS: () => EMPTY_WARNINGS,
|
|
39
|
+
EPHEMERIS_VALIDITY_MS: () => EPHEMERIS_VALIDITY_MS,
|
|
39
40
|
FREQ: () => FREQ,
|
|
40
41
|
FREQ_BDS_B1A: () => FREQ_BDS_B1A,
|
|
41
42
|
FREQ_BDS_B1C: () => FREQ_BDS_B1C,
|
|
@@ -252,6 +253,7 @@ __export(src_exports, {
|
|
|
252
253
|
hdrLine: () => hdrLine,
|
|
253
254
|
horizonDistance: () => horizonDistance,
|
|
254
255
|
ionoFree: () => ionoFree,
|
|
256
|
+
isEphemerisValid: () => isEphemerisValid,
|
|
255
257
|
isSbasL1Preamble: () => isSbasL1Preamble,
|
|
256
258
|
isSbasL5Correction: () => isSbasL5Correction,
|
|
257
259
|
isSsrMessage: () => isSsrMessage,
|
|
@@ -264,6 +266,7 @@ __export(src_exports, {
|
|
|
264
266
|
meridianArc: () => meridianArc,
|
|
265
267
|
moonEcef: () => moonEcef,
|
|
266
268
|
navTimesFromEph: () => navTimesFromEph,
|
|
269
|
+
nearestValidEphemeris: () => nearestValidEphemeris,
|
|
267
270
|
niellMapping: () => niellMapping,
|
|
268
271
|
nlWavelength: () => nlWavelength,
|
|
269
272
|
nmeaCoordToDecimal: () => nmeaCoordToDecimal,
|
|
@@ -12312,6 +12315,42 @@ function invertMatrix(A) {
|
|
|
12312
12315
|
return M.map((row) => row.slice(n));
|
|
12313
12316
|
}
|
|
12314
12317
|
|
|
12318
|
+
// src/orbit/validity.ts
|
|
12319
|
+
var H = 36e5;
|
|
12320
|
+
var MIN = 6e4;
|
|
12321
|
+
var EPHEMERIS_VALIDITY_MS = {
|
|
12322
|
+
G: 2 * H,
|
|
12323
|
+
J: 2 * H,
|
|
12324
|
+
E: 2.5 * H,
|
|
12325
|
+
C: 90 * MIN,
|
|
12326
|
+
R: 15 * MIN,
|
|
12327
|
+
I: 2 * H,
|
|
12328
|
+
S: 6 * MIN
|
|
12329
|
+
};
|
|
12330
|
+
function tocDistanceMs(eph, tGpsMs) {
|
|
12331
|
+
const t = eph.system === "R" || eph.system === "S" ? tGpsMs - getGpsLeap(new Date(tGpsMs)) * 1e3 : tGpsMs;
|
|
12332
|
+
return Math.abs(eph.tocDate.getTime() - t);
|
|
12333
|
+
}
|
|
12334
|
+
function isEphemerisValid(eph, tGpsMs) {
|
|
12335
|
+
const w = EPHEMERIS_VALIDITY_MS[eph.system];
|
|
12336
|
+
return w !== void 0 && tocDistanceMs(eph, tGpsMs) <= w;
|
|
12337
|
+
}
|
|
12338
|
+
function nearestValidEphemeris(ephs, tGpsMs) {
|
|
12339
|
+
if (!ephs) return null;
|
|
12340
|
+
let best = null;
|
|
12341
|
+
let bestDt = Infinity;
|
|
12342
|
+
for (const eph of ephs) {
|
|
12343
|
+
const dt = tocDistanceMs(eph, tGpsMs);
|
|
12344
|
+
const w = EPHEMERIS_VALIDITY_MS[eph.system];
|
|
12345
|
+
if (w === void 0 || dt > w) continue;
|
|
12346
|
+
if (dt < bestDt) {
|
|
12347
|
+
bestDt = dt;
|
|
12348
|
+
best = eph;
|
|
12349
|
+
}
|
|
12350
|
+
}
|
|
12351
|
+
return best;
|
|
12352
|
+
}
|
|
12353
|
+
|
|
12315
12354
|
// src/orbit/almanac.ts
|
|
12316
12355
|
var GM_GPS = 3986005e8;
|
|
12317
12356
|
var GM_GAL = 3986004418e5;
|
|
@@ -12684,12 +12723,18 @@ function dopClock(prn) {
|
|
|
12684
12723
|
return sys === "J" || sys === "S" ? "G" : sys;
|
|
12685
12724
|
}
|
|
12686
12725
|
function computeDop(satAzEls) {
|
|
12687
|
-
const
|
|
12688
|
-
const
|
|
12726
|
+
const perClock = /* @__PURE__ */ new Map();
|
|
12727
|
+
for (const s of satAzEls) {
|
|
12728
|
+
const c = dopClock(s.prn);
|
|
12729
|
+
perClock.set(c, (perClock.get(c) ?? 0) + 1);
|
|
12730
|
+
}
|
|
12731
|
+
const sats = perClock.size > 1 ? satAzEls.filter((s) => perClock.get(dopClock(s.prn)) > 1) : satAzEls;
|
|
12732
|
+
const n = sats.length;
|
|
12733
|
+
const clocks = [...new Set(sats.map((s) => dopClock(s.prn)))];
|
|
12689
12734
|
const m = 3 + clocks.length;
|
|
12690
12735
|
if (n < Math.max(4, m)) return null;
|
|
12691
12736
|
const H3 = [];
|
|
12692
|
-
for (const { az, el, prn } of
|
|
12737
|
+
for (const { az, el, prn } of sats) {
|
|
12693
12738
|
const cosEl = Math.cos(el);
|
|
12694
12739
|
const row = [cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el)];
|
|
12695
12740
|
const clock = dopClock(prn);
|
|
@@ -12802,18 +12847,7 @@ function computeAllPositions(ephemerides, times, rxPos) {
|
|
|
12802
12847
|
return { prns, times, positions };
|
|
12803
12848
|
}
|
|
12804
12849
|
function selectBest(ephs, timeMs) {
|
|
12805
|
-
|
|
12806
|
-
let bestDt = Infinity;
|
|
12807
|
-
for (const eph of ephs) {
|
|
12808
|
-
const dt = Math.abs(timeMs - eph.tocDate.getTime());
|
|
12809
|
-
const maxAge = eph.system === "R" || eph.system === "S" ? 18e5 : 4 * 36e5;
|
|
12810
|
-
if (dt > maxAge) continue;
|
|
12811
|
-
if (dt < bestDt) {
|
|
12812
|
-
bestDt = dt;
|
|
12813
|
-
best = eph;
|
|
12814
|
-
}
|
|
12815
|
-
}
|
|
12816
|
-
return best;
|
|
12850
|
+
return nearestValidEphemeris(ephs, timeMs);
|
|
12817
12851
|
}
|
|
12818
12852
|
var GPS_EPOCH_MS24 = START_GPS_TIME.getTime();
|
|
12819
12853
|
var MS_PER_WEEK13 = 7 * 864e5;
|
|
@@ -13054,14 +13088,14 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
13054
13088
|
}
|
|
13055
13089
|
|
|
13056
13090
|
// src/frames/index.ts
|
|
13057
|
-
var
|
|
13091
|
+
var H2 = (t, d, r, tDot, dDot, rDot, epoch) => ({ t, d, r, tDot, dDot, rDot, epoch });
|
|
13058
13092
|
var Z = [0, 0, 0];
|
|
13059
13093
|
var FROM_ITRF2020 = {
|
|
13060
|
-
ITRF2014:
|
|
13061
|
-
ITRF2008:
|
|
13062
|
-
ITRF2005:
|
|
13063
|
-
ITRF2000:
|
|
13064
|
-
ITRF97:
|
|
13094
|
+
ITRF2014: H2([-1.4, -0.9, 1.4], -0.42, Z, [0, -0.1, 0.2], 0, Z, 2015),
|
|
13095
|
+
ITRF2008: H2([0.2, 1, 3.3], -0.29, Z, [0, -0.1, 0.1], 0.03, Z, 2015),
|
|
13096
|
+
ITRF2005: H2([2.7, 0.1, -1.4], 0.65, Z, [0.3, -0.1, 0.1], 0.03, Z, 2015),
|
|
13097
|
+
ITRF2000: H2([-0.2, 0.8, -34.2], 2.25, Z, [0.1, 0, -1.7], 0.11, Z, 2015),
|
|
13098
|
+
ITRF97: H2(
|
|
13065
13099
|
[6.5, -3.9, -77.9],
|
|
13066
13100
|
3.98,
|
|
13067
13101
|
[0, 0, 0.36],
|
|
@@ -13070,7 +13104,7 @@ var FROM_ITRF2020 = {
|
|
|
13070
13104
|
[0, 0, 0.02],
|
|
13071
13105
|
2015
|
|
13072
13106
|
),
|
|
13073
|
-
ITRF96:
|
|
13107
|
+
ITRF96: H2(
|
|
13074
13108
|
[6.5, -3.9, -77.9],
|
|
13075
13109
|
3.98,
|
|
13076
13110
|
[0, 0, 0.36],
|
|
@@ -13079,7 +13113,7 @@ var FROM_ITRF2020 = {
|
|
|
13079
13113
|
[0, 0, 0.02],
|
|
13080
13114
|
2015
|
|
13081
13115
|
),
|
|
13082
|
-
ITRF94:
|
|
13116
|
+
ITRF94: H2(
|
|
13083
13117
|
[6.5, -3.9, -77.9],
|
|
13084
13118
|
3.98,
|
|
13085
13119
|
[0, 0, 0.36],
|
|
@@ -13088,7 +13122,7 @@ var FROM_ITRF2020 = {
|
|
|
13088
13122
|
[0, 0, 0.02],
|
|
13089
13123
|
2015
|
|
13090
13124
|
),
|
|
13091
|
-
ITRF93:
|
|
13125
|
+
ITRF93: H2(
|
|
13092
13126
|
[-65.8, 1.9, -71.3],
|
|
13093
13127
|
4.47,
|
|
13094
13128
|
[-3.36, -4.33, 0.75],
|
|
@@ -13097,7 +13131,7 @@ var FROM_ITRF2020 = {
|
|
|
13097
13131
|
[-0.11, -0.19, 0.07],
|
|
13098
13132
|
2015
|
|
13099
13133
|
),
|
|
13100
|
-
ITRF92:
|
|
13134
|
+
ITRF92: H2(
|
|
13101
13135
|
[14.5, -1.9, -85.9],
|
|
13102
13136
|
3.27,
|
|
13103
13137
|
[0, 0, 0.36],
|
|
@@ -13106,7 +13140,7 @@ var FROM_ITRF2020 = {
|
|
|
13106
13140
|
[0, 0, 0.02],
|
|
13107
13141
|
2015
|
|
13108
13142
|
),
|
|
13109
|
-
ITRF91:
|
|
13143
|
+
ITRF91: H2(
|
|
13110
13144
|
[26.5, 12.1, -91.9],
|
|
13111
13145
|
4.67,
|
|
13112
13146
|
[0, 0, 0.36],
|
|
@@ -13115,7 +13149,7 @@ var FROM_ITRF2020 = {
|
|
|
13115
13149
|
[0, 0, 0.02],
|
|
13116
13150
|
2015
|
|
13117
13151
|
),
|
|
13118
|
-
ITRF90:
|
|
13152
|
+
ITRF90: H2(
|
|
13119
13153
|
[24.5, 8.1, -107.9],
|
|
13120
13154
|
4.97,
|
|
13121
13155
|
[0, 0, 0.36],
|
|
@@ -13124,7 +13158,7 @@ var FROM_ITRF2020 = {
|
|
|
13124
13158
|
[0, 0, 0.02],
|
|
13125
13159
|
2015
|
|
13126
13160
|
),
|
|
13127
|
-
ITRF89:
|
|
13161
|
+
ITRF89: H2(
|
|
13128
13162
|
[29.5, 32.1, -145.9],
|
|
13129
13163
|
8.37,
|
|
13130
13164
|
[0, 0, 0.36],
|
|
@@ -13133,7 +13167,7 @@ var FROM_ITRF2020 = {
|
|
|
13133
13167
|
[0, 0, 0.02],
|
|
13134
13168
|
2015
|
|
13135
13169
|
),
|
|
13136
|
-
ITRF88:
|
|
13170
|
+
ITRF88: H2(
|
|
13137
13171
|
[24.5, -3.9, -169.9],
|
|
13138
13172
|
11.47,
|
|
13139
13173
|
[0.1, 0, 0.36],
|
|
@@ -13143,10 +13177,10 @@ var FROM_ITRF2020 = {
|
|
|
13143
13177
|
2015
|
|
13144
13178
|
),
|
|
13145
13179
|
/** ITRF2020 → ETRF2020, EPSG:10572 (epoch-1989 variant) */
|
|
13146
|
-
ETRF2020:
|
|
13180
|
+
ETRF2020: H2(Z, 0, Z, Z, 0, [0.086, 0.519, -0.753], 1989)
|
|
13147
13181
|
};
|
|
13148
|
-
var ITRF2014_TO_ETRF2014 =
|
|
13149
|
-
var ITRF2014_TO_ETRF2000 =
|
|
13182
|
+
var ITRF2014_TO_ETRF2014 = H2(Z, 0, Z, Z, 0, [0.085, 0.531, -0.77], 1989);
|
|
13183
|
+
var ITRF2014_TO_ETRF2000 = H2(
|
|
13150
13184
|
[54.7, 52.2, -74.1],
|
|
13151
13185
|
2.12,
|
|
13152
13186
|
[1.701, 10.29, -16.632],
|
|
@@ -13155,7 +13189,7 @@ var ITRF2014_TO_ETRF2000 = H(
|
|
|
13155
13189
|
[0.081, 0.49, -0.792],
|
|
13156
13190
|
2010
|
|
13157
13191
|
);
|
|
13158
|
-
var ITRF2014_TO_NAD83_2011 =
|
|
13192
|
+
var ITRF2014_TO_NAD83_2011 = H2(
|
|
13159
13193
|
[1005.3, -1909.21, -541.57],
|
|
13160
13194
|
0.36891,
|
|
13161
13195
|
[-26.78138, 0.42027, -10.93206],
|
|
@@ -15831,7 +15865,7 @@ function moonEcef(timeMs) {
|
|
|
15831
15865
|
];
|
|
15832
15866
|
return eciToEcef(eci, gmst(timeMs));
|
|
15833
15867
|
}
|
|
15834
|
-
var
|
|
15868
|
+
var H22 = 0.6078;
|
|
15835
15869
|
var L2 = 0.0847;
|
|
15836
15870
|
var RE = 6378137;
|
|
15837
15871
|
var GM_SUN_RATIO = 332946.0482;
|
|
@@ -15856,7 +15890,7 @@ function solidEarthTide(rcv, sun, moon) {
|
|
|
15856
15890
|
];
|
|
15857
15891
|
const dot2 = rHat[0] * jHat[0] + rHat[1] * jHat[1] + rHat[2] * jHat[2];
|
|
15858
15892
|
const factor = ratio * RE * RE * RE * RE / (rj * rj * rj);
|
|
15859
|
-
const radialScale =
|
|
15893
|
+
const radialScale = H22 * (1.5 * dot2 * dot2 - 0.5);
|
|
15860
15894
|
const tanScale = 3 * L2 * dot2;
|
|
15861
15895
|
for (let k = 0; k < 3; k++) {
|
|
15862
15896
|
disp[k] += factor * (radialScale * rHat[k] + tanScale * (jHat[k] - dot2 * rHat[k]));
|
|
@@ -19516,6 +19550,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
19516
19550
|
DELTA_GLO_L2,
|
|
19517
19551
|
DUAL_FREQ_PAIRS,
|
|
19518
19552
|
EMPTY_WARNINGS,
|
|
19553
|
+
EPHEMERIS_VALIDITY_MS,
|
|
19519
19554
|
FREQ,
|
|
19520
19555
|
FREQ_BDS_B1A,
|
|
19521
19556
|
FREQ_BDS_B1C,
|
|
@@ -19732,6 +19767,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
19732
19767
|
hdrLine,
|
|
19733
19768
|
horizonDistance,
|
|
19734
19769
|
ionoFree,
|
|
19770
|
+
isEphemerisValid,
|
|
19735
19771
|
isSbasL1Preamble,
|
|
19736
19772
|
isSbasL5Correction,
|
|
19737
19773
|
isSsrMessage,
|
|
@@ -19744,6 +19780,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
19744
19780
|
meridianArc,
|
|
19745
19781
|
moonEcef,
|
|
19746
19782
|
navTimesFromEph,
|
|
19783
|
+
nearestValidEphemeris,
|
|
19747
19784
|
niellMapping,
|
|
19748
19785
|
nlWavelength,
|
|
19749
19786
|
nmeaCoordToDecimal,
|
package/dist/index.d.cts
CHANGED
|
@@ -17,7 +17,7 @@ export { DfmcCensus, DfmcMessageCb, GeoL5Result, SBAS_L5_MT_NAMES, SBAS_L5_PREAM
|
|
|
17
17
|
export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, NovatelPvtResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelPvt, parseNovatelRange } from './novatel.cjs';
|
|
18
18
|
export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, TrimbleParseResult, parseTrimble, parseTrimbleNav, trimbleFrames } from './trimble.cjs';
|
|
19
19
|
export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.cjs';
|
|
20
|
-
export { AllPositionsData, AlmanacPosition, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.cjs';
|
|
20
|
+
export { AllPositionsData, AlmanacPosition, DopValues, EPHEMERIS_VALIDITY_MS, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, isEphemerisValid, keplerPosition, maskRadForAzimuth, navTimesFromEph, nearestValidEphemeris, rangeRate, selectEphemeris } from './orbit.cjs';
|
|
21
21
|
export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.cjs';
|
|
22
22
|
export { AntennaOffset, AppliedOrbitClock, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, Degradation, DgnssOptions, DgnssSolution, EphemerisSource, FixedPositionResult, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, NetworkFcbResult, NetworkFcbSummary, NlArc, NlFcbResult, OrbitClockCorrection, PppAntennaModel, PppArc, PppCorrectionConfig, PppCorrections, PppEngine, PppEphemerisSource, PppEpoch, PppEpochContext, PppEpochResult, PppFixState, PppOptions, PppSatObs, PppSolution, RawObservation, ReceiverBias, ReceiverClockSample, RtkAntennaConfig, RtkAntennaModel, RtkAntennaOffset, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, RtkObsEpoch, RtkObsInput, RtkPostProcessOptions, RtkPostProcessResult, RtkReceiverAntenna, RtkTrackPoint, SatGeom, SatSample, SbasCorrectionSource, SbasIgp, SbasIonoDelay, SbasProcessor, SbasSatCorrection, Sp3EphemerisSource, SppOptions, SppSolution, TropoMapping, WlArc, WlFcbOptions, WlFcbResult, WlObs, ZeroBaselineEngine, ZeroBaselineOptions, antexFreqOfGroup, applyOrbitClock, buildPppAntenna, buildRtkAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, fixPppPosition, gimSlantIonoDelayL1, gimVerticalTec, gmst, hasToOrbitClock, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, postProcessRtk, rcvAntennaRangeM, resolvePppAmbiguities, satClockCorrection, sbasIonoDeg, sbasLongTermDeg, sbasProtectionLevels, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.cjs';
|
|
23
23
|
export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export { DfmcCensus, DfmcMessageCb, GeoL5Result, SBAS_L5_MT_NAMES, SBAS_L5_PREAM
|
|
|
17
17
|
export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, NovatelPvtResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelPvt, parseNovatelRange } from './novatel.js';
|
|
18
18
|
export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, TrimbleParseResult, parseTrimble, parseTrimbleNav, trimbleFrames } from './trimble.js';
|
|
19
19
|
export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.js';
|
|
20
|
-
export { AllPositionsData, AlmanacPosition, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.js';
|
|
20
|
+
export { AllPositionsData, AlmanacPosition, DopValues, EPHEMERIS_VALIDITY_MS, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, isEphemerisValid, keplerPosition, maskRadForAzimuth, navTimesFromEph, nearestValidEphemeris, rangeRate, selectEphemeris } from './orbit.js';
|
|
21
21
|
export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.js';
|
|
22
22
|
export { AntennaOffset, AppliedOrbitClock, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, Degradation, DgnssOptions, DgnssSolution, EphemerisSource, FixedPositionResult, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, NetworkFcbResult, NetworkFcbSummary, NlArc, NlFcbResult, OrbitClockCorrection, PppAntennaModel, PppArc, PppCorrectionConfig, PppCorrections, PppEngine, PppEphemerisSource, PppEpoch, PppEpochContext, PppEpochResult, PppFixState, PppOptions, PppSatObs, PppSolution, RawObservation, ReceiverBias, ReceiverClockSample, RtkAntennaConfig, RtkAntennaModel, RtkAntennaOffset, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, RtkObsEpoch, RtkObsInput, RtkPostProcessOptions, RtkPostProcessResult, RtkReceiverAntenna, RtkTrackPoint, SatGeom, SatSample, SbasCorrectionSource, SbasIgp, SbasIonoDelay, SbasProcessor, SbasSatCorrection, Sp3EphemerisSource, SppOptions, SppSolution, TropoMapping, WlArc, WlFcbOptions, WlFcbResult, WlObs, ZeroBaselineEngine, ZeroBaselineOptions, antexFreqOfGroup, applyOrbitClock, buildPppAntenna, buildRtkAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, fixPppPosition, gimSlantIonoDelayL1, gimVerticalTec, gmst, hasToOrbitClock, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, postProcessRtk, rcvAntennaRangeM, resolvePppAmbiguities, satClockCorrection, sbasIonoDeg, sbasLongTermDeg, sbasProtectionLevels, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.js';
|
|
23
23
|
export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.js';
|
package/dist/index.js
CHANGED
|
@@ -213,9 +213,10 @@ import {
|
|
|
213
213
|
sunEcef,
|
|
214
214
|
toRtkEpoch,
|
|
215
215
|
wlWavelength
|
|
216
|
-
} from "./chunk-
|
|
216
|
+
} from "./chunk-NOGA5KD7.js";
|
|
217
217
|
import "./chunk-WQX354KD.js";
|
|
218
218
|
import {
|
|
219
|
+
EPHEMERIS_VALIDITY_MS,
|
|
219
220
|
almanacEpochMs,
|
|
220
221
|
almanacSatPosition,
|
|
221
222
|
computeAllPositions,
|
|
@@ -230,12 +231,14 @@ import {
|
|
|
230
231
|
glonassAlmanacEpochMs,
|
|
231
232
|
glonassAlmanacPosition,
|
|
232
233
|
glonassPosition,
|
|
234
|
+
isEphemerisValid,
|
|
233
235
|
keplerPosition,
|
|
234
236
|
maskRadForAzimuth,
|
|
235
237
|
navTimesFromEph,
|
|
238
|
+
nearestValidEphemeris,
|
|
236
239
|
rangeRate,
|
|
237
240
|
selectEphemeris
|
|
238
|
-
} from "./chunk-
|
|
241
|
+
} from "./chunk-7T5DLVZL.js";
|
|
239
242
|
import {
|
|
240
243
|
getBdsTime,
|
|
241
244
|
getDateFromBdsTime,
|
|
@@ -415,6 +418,7 @@ export {
|
|
|
415
418
|
DELTA_GLO_L2,
|
|
416
419
|
DUAL_FREQ_PAIRS,
|
|
417
420
|
EMPTY_WARNINGS,
|
|
421
|
+
EPHEMERIS_VALIDITY_MS,
|
|
418
422
|
FREQ,
|
|
419
423
|
FREQ_BDS_B1A,
|
|
420
424
|
FREQ_BDS_B1C,
|
|
@@ -631,6 +635,7 @@ export {
|
|
|
631
635
|
hdrLine,
|
|
632
636
|
horizonDistance,
|
|
633
637
|
ionoFree,
|
|
638
|
+
isEphemerisValid,
|
|
634
639
|
isSbasL1Preamble,
|
|
635
640
|
isSbasL5Correction,
|
|
636
641
|
isSsrMessage,
|
|
@@ -643,6 +648,7 @@ export {
|
|
|
643
648
|
meridianArc,
|
|
644
649
|
moonEcef,
|
|
645
650
|
navTimesFromEph,
|
|
651
|
+
nearestValidEphemeris,
|
|
646
652
|
niellMapping,
|
|
647
653
|
nlWavelength,
|
|
648
654
|
nmeaCoordToDecimal,
|
package/dist/orbit.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/orbit/index.ts
|
|
21
21
|
var orbit_exports = {};
|
|
22
22
|
__export(orbit_exports, {
|
|
23
|
+
EPHEMERIS_VALIDITY_MS: () => EPHEMERIS_VALIDITY_MS,
|
|
23
24
|
almanacEpochMs: () => almanacEpochMs,
|
|
24
25
|
almanacSatPosition: () => almanacSatPosition,
|
|
25
26
|
computeAllPositions: () => computeAllPositions,
|
|
@@ -36,9 +37,11 @@ __export(orbit_exports, {
|
|
|
36
37
|
glonassAlmanacEpochMs: () => glonassAlmanacEpochMs,
|
|
37
38
|
glonassAlmanacPosition: () => glonassAlmanacPosition,
|
|
38
39
|
glonassPosition: () => glonassPosition,
|
|
40
|
+
isEphemerisValid: () => isEphemerisValid,
|
|
39
41
|
keplerPosition: () => keplerPosition,
|
|
40
42
|
maskRadForAzimuth: () => maskRadForAzimuth,
|
|
41
43
|
navTimesFromEph: () => navTimesFromEph,
|
|
44
|
+
nearestValidEphemeris: () => nearestValidEphemeris,
|
|
42
45
|
rangeRate: () => rangeRate,
|
|
43
46
|
selectEphemeris: () => selectEphemeris
|
|
44
47
|
});
|
|
@@ -198,6 +201,42 @@ function invertMatrix(A) {
|
|
|
198
201
|
return M.map((row) => row.slice(n));
|
|
199
202
|
}
|
|
200
203
|
|
|
204
|
+
// src/orbit/validity.ts
|
|
205
|
+
var H = 36e5;
|
|
206
|
+
var MIN = 6e4;
|
|
207
|
+
var EPHEMERIS_VALIDITY_MS = {
|
|
208
|
+
G: 2 * H,
|
|
209
|
+
J: 2 * H,
|
|
210
|
+
E: 2.5 * H,
|
|
211
|
+
C: 90 * MIN,
|
|
212
|
+
R: 15 * MIN,
|
|
213
|
+
I: 2 * H,
|
|
214
|
+
S: 6 * MIN
|
|
215
|
+
};
|
|
216
|
+
function tocDistanceMs(eph, tGpsMs) {
|
|
217
|
+
const t = eph.system === "R" || eph.system === "S" ? tGpsMs - getGpsLeap(new Date(tGpsMs)) * 1e3 : tGpsMs;
|
|
218
|
+
return Math.abs(eph.tocDate.getTime() - t);
|
|
219
|
+
}
|
|
220
|
+
function isEphemerisValid(eph, tGpsMs) {
|
|
221
|
+
const w = EPHEMERIS_VALIDITY_MS[eph.system];
|
|
222
|
+
return w !== void 0 && tocDistanceMs(eph, tGpsMs) <= w;
|
|
223
|
+
}
|
|
224
|
+
function nearestValidEphemeris(ephs, tGpsMs) {
|
|
225
|
+
if (!ephs) return null;
|
|
226
|
+
let best = null;
|
|
227
|
+
let bestDt = Infinity;
|
|
228
|
+
for (const eph of ephs) {
|
|
229
|
+
const dt = tocDistanceMs(eph, tGpsMs);
|
|
230
|
+
const w = EPHEMERIS_VALIDITY_MS[eph.system];
|
|
231
|
+
if (w === void 0 || dt > w) continue;
|
|
232
|
+
if (dt < bestDt) {
|
|
233
|
+
bestDt = dt;
|
|
234
|
+
best = eph;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return best;
|
|
238
|
+
}
|
|
239
|
+
|
|
201
240
|
// src/orbit/almanac.ts
|
|
202
241
|
var GM_GPS = 3986005e8;
|
|
203
242
|
var GM_GAL = 3986004418e5;
|
|
@@ -570,24 +609,30 @@ function dopClock(prn) {
|
|
|
570
609
|
return sys === "J" || sys === "S" ? "G" : sys;
|
|
571
610
|
}
|
|
572
611
|
function computeDop(satAzEls) {
|
|
573
|
-
const
|
|
574
|
-
const
|
|
612
|
+
const perClock = /* @__PURE__ */ new Map();
|
|
613
|
+
for (const s of satAzEls) {
|
|
614
|
+
const c = dopClock(s.prn);
|
|
615
|
+
perClock.set(c, (perClock.get(c) ?? 0) + 1);
|
|
616
|
+
}
|
|
617
|
+
const sats = perClock.size > 1 ? satAzEls.filter((s) => perClock.get(dopClock(s.prn)) > 1) : satAzEls;
|
|
618
|
+
const n = sats.length;
|
|
619
|
+
const clocks = [...new Set(sats.map((s) => dopClock(s.prn)))];
|
|
575
620
|
const m = 3 + clocks.length;
|
|
576
621
|
if (n < Math.max(4, m)) return null;
|
|
577
|
-
const
|
|
578
|
-
for (const { az, el, prn } of
|
|
622
|
+
const H2 = [];
|
|
623
|
+
for (const { az, el, prn } of sats) {
|
|
579
624
|
const cosEl = Math.cos(el);
|
|
580
625
|
const row = [cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el)];
|
|
581
626
|
const clock = dopClock(prn);
|
|
582
627
|
for (const c of clocks) row.push(c === clock ? 1 : 0);
|
|
583
|
-
|
|
628
|
+
H2.push(row);
|
|
584
629
|
}
|
|
585
630
|
const HtH = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
586
631
|
for (let i = 0; i < m; i++) {
|
|
587
632
|
for (let j = 0; j < m; j++) {
|
|
588
633
|
let sum = 0;
|
|
589
634
|
for (let k = 0; k < n; k++) {
|
|
590
|
-
sum +=
|
|
635
|
+
sum += H2[k][i] * H2[k][j];
|
|
591
636
|
}
|
|
592
637
|
HtH[i][j] = sum;
|
|
593
638
|
}
|
|
@@ -688,18 +733,7 @@ function computeAllPositions(ephemerides, times, rxPos) {
|
|
|
688
733
|
return { prns, times, positions };
|
|
689
734
|
}
|
|
690
735
|
function selectBest(ephs, timeMs) {
|
|
691
|
-
|
|
692
|
-
let bestDt = Infinity;
|
|
693
|
-
for (const eph of ephs) {
|
|
694
|
-
const dt = Math.abs(timeMs - eph.tocDate.getTime());
|
|
695
|
-
const maxAge = eph.system === "R" || eph.system === "S" ? 18e5 : 4 * 36e5;
|
|
696
|
-
if (dt > maxAge) continue;
|
|
697
|
-
if (dt < bestDt) {
|
|
698
|
-
bestDt = dt;
|
|
699
|
-
best = eph;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
return best;
|
|
736
|
+
return nearestValidEphemeris(ephs, timeMs);
|
|
703
737
|
}
|
|
704
738
|
var GPS_EPOCH_MS2 = START_GPS_TIME.getTime();
|
|
705
739
|
var MS_PER_WEEK = 7 * 864e5;
|
|
@@ -940,6 +974,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
940
974
|
}
|
|
941
975
|
// Annotate the CommonJS export names for ESM import in node:
|
|
942
976
|
0 && (module.exports = {
|
|
977
|
+
EPHEMERIS_VALIDITY_MS,
|
|
943
978
|
almanacEpochMs,
|
|
944
979
|
almanacSatPosition,
|
|
945
980
|
computeAllPositions,
|
|
@@ -956,9 +991,11 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
956
991
|
glonassAlmanacEpochMs,
|
|
957
992
|
glonassAlmanacPosition,
|
|
958
993
|
glonassPosition,
|
|
994
|
+
isEphemerisValid,
|
|
959
995
|
keplerPosition,
|
|
960
996
|
maskRadForAzimuth,
|
|
961
997
|
navTimesFromEph,
|
|
998
|
+
nearestValidEphemeris,
|
|
962
999
|
rangeRate,
|
|
963
1000
|
selectEphemeris
|
|
964
1001
|
});
|
package/dist/orbit.d.cts
CHANGED
|
@@ -91,6 +91,40 @@ declare function glonassAlmanacEpochMs(alm: SbfGlonassAlmanac): number;
|
|
|
91
91
|
*/
|
|
92
92
|
declare function glonassAlmanacPosition(alm: SbfGlonassAlmanac, timeMs: number): AlmanacPosition;
|
|
93
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Broadcast-ephemeris validity — whether an ephemeris may position its
|
|
96
|
+
* satellite at a given epoch, and the nearest one that may.
|
|
97
|
+
*
|
|
98
|
+
* Each system's half-window |t − toc| follows its broadcast design, never
|
|
99
|
+
* wider than the documented validity:
|
|
100
|
+
* - GPS / QZSS: the 4-h curve fit centred on toe → ±2 h (IS-GPS-200,
|
|
101
|
+
* IS-QZSS; RTKLIB MAXDTOE).
|
|
102
|
+
* - Galileo: 2.5 h, inside the 4-h nominal validity (RTKLIB MAXDTOE_GAL).
|
|
103
|
+
* - BeiDou: 90 min — ephemerides are refreshed hourly.
|
|
104
|
+
* - GLONASS: the immediate data cover a 30-min interval centred on tb →
|
|
105
|
+
* ±15 min.
|
|
106
|
+
* - NavIC: ±2 h (2-h update cycle).
|
|
107
|
+
* - SBAS GEO (MT9 state vector): 6 min (RTKLIB MAXDTOE_SBS) — a GEO
|
|
108
|
+
* extrapolated from an hours-old state vector is not an orbit.
|
|
109
|
+
* Any other system is never valid.
|
|
110
|
+
*
|
|
111
|
+
* Time: `tGpsMs` is GPS-scale epoch ms, like everywhere in this module.
|
|
112
|
+
* GLONASS and SBAS tocs are on the UTC axis (see {@link computeSatPosition}),
|
|
113
|
+
* so for those t is moved to UTC first — on a ±15-min window the 18-s
|
|
114
|
+
* leap-second offset matters.
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
/** Validity half-window |t − toc| per system letter, in ms. */
|
|
118
|
+
declare const EPHEMERIS_VALIDITY_MS: Readonly<Record<string, number>>;
|
|
119
|
+
/** May `eph` position its satellite at GPS-scale epoch `tGpsMs`? */
|
|
120
|
+
declare function isEphemerisValid(eph: Ephemeris, tGpsMs: number): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* The ephemeris in `ephs` whose toc is nearest to `tGpsMs` among those valid
|
|
123
|
+
* at `tGpsMs`, or null when none is. `ephs` may mix satellites; filter by PRN
|
|
124
|
+
* first if it does.
|
|
125
|
+
*/
|
|
126
|
+
declare function nearestValidEphemeris(ephs: readonly Ephemeris[] | undefined, tGpsMs: number): Ephemeris | null;
|
|
127
|
+
|
|
94
128
|
/**
|
|
95
129
|
* Satellite orbit computation from broadcast ephemerides.
|
|
96
130
|
* Supports GPS, Galileo, BeiDou (Keplerian) and GLONASS (Runge-Kutta).
|
|
@@ -164,8 +198,11 @@ declare function ecefToAzEl(rxX: number, rxY: number, rxZ: number, satX: number,
|
|
|
164
198
|
* constellation time scale, as a multi-GNSS receiver solves: every extra
|
|
165
199
|
* time scale costs one observation. QZSS and SBAS share the GPS clock —
|
|
166
200
|
* QZSST and SBAS network time are steered to GPST (RTKLIB pntpos does the
|
|
167
|
-
* same) — so a lone SBAS GEO doesn't inflate TDOP/GDOP.
|
|
168
|
-
*
|
|
201
|
+
* same) — so a lone SBAS GEO doesn't inflate TDOP/GDOP. A time scale
|
|
202
|
+
* with a single satellite in view is left out: that satellite only fixes
|
|
203
|
+
* its own clock, adding nothing to PDOP/HDOP/VDOP and an unrecoverable ~1
|
|
204
|
+
* to TDOP². Untagged satellites share a single clock (the classic
|
|
205
|
+
* single-system model).
|
|
169
206
|
*
|
|
170
207
|
* @param satAzEls Satellite azimuth/elevation pairs (radians), optionally
|
|
171
208
|
* tagged with their PRN.
|
|
@@ -178,11 +215,12 @@ declare function computeDop(satAzEls: {
|
|
|
178
215
|
prn?: string;
|
|
179
216
|
}[]): DopValues | null;
|
|
180
217
|
/**
|
|
181
|
-
* Find the best ephemeris for a given PRN at a given time
|
|
182
|
-
*
|
|
218
|
+
* Find the best ephemeris for a given PRN at a given time: the one with the
|
|
219
|
+
* closest epoch (toe/toc) among those within their broadcast validity at
|
|
220
|
+
* that time ({@link isEphemerisValid}); null when none is valid.
|
|
183
221
|
* @param ephemerides Array of candidate ephemerides
|
|
184
222
|
* @param prn Satellite PRN identifier (e.g. "G01")
|
|
185
|
-
* @param timeMs Target time
|
|
223
|
+
* @param timeMs Target time, GPS-scale epoch milliseconds
|
|
186
224
|
*/
|
|
187
225
|
declare function selectEphemeris(ephemerides: Ephemeris[], prn: string, timeMs: number): Ephemeris | null;
|
|
188
226
|
/**
|
|
@@ -300,4 +338,4 @@ declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, num
|
|
|
300
338
|
*/
|
|
301
339
|
declare function computeVisibilityFromPositions(all: AllPositionsData, elevationMaskDeg?: number | number[]): VisibilityResult;
|
|
302
340
|
|
|
303
|
-
export { type AllPositionsData, type AlmanacPosition, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris };
|
|
341
|
+
export { type AllPositionsData, type AlmanacPosition, type DopValues, EPHEMERIS_VALIDITY_MS, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, isEphemerisValid, keplerPosition, maskRadForAzimuth, navTimesFromEph, nearestValidEphemeris, rangeRate, selectEphemeris };
|
package/dist/orbit.d.ts
CHANGED
|
@@ -91,6 +91,40 @@ declare function glonassAlmanacEpochMs(alm: SbfGlonassAlmanac): number;
|
|
|
91
91
|
*/
|
|
92
92
|
declare function glonassAlmanacPosition(alm: SbfGlonassAlmanac, timeMs: number): AlmanacPosition;
|
|
93
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Broadcast-ephemeris validity — whether an ephemeris may position its
|
|
96
|
+
* satellite at a given epoch, and the nearest one that may.
|
|
97
|
+
*
|
|
98
|
+
* Each system's half-window |t − toc| follows its broadcast design, never
|
|
99
|
+
* wider than the documented validity:
|
|
100
|
+
* - GPS / QZSS: the 4-h curve fit centred on toe → ±2 h (IS-GPS-200,
|
|
101
|
+
* IS-QZSS; RTKLIB MAXDTOE).
|
|
102
|
+
* - Galileo: 2.5 h, inside the 4-h nominal validity (RTKLIB MAXDTOE_GAL).
|
|
103
|
+
* - BeiDou: 90 min — ephemerides are refreshed hourly.
|
|
104
|
+
* - GLONASS: the immediate data cover a 30-min interval centred on tb →
|
|
105
|
+
* ±15 min.
|
|
106
|
+
* - NavIC: ±2 h (2-h update cycle).
|
|
107
|
+
* - SBAS GEO (MT9 state vector): 6 min (RTKLIB MAXDTOE_SBS) — a GEO
|
|
108
|
+
* extrapolated from an hours-old state vector is not an orbit.
|
|
109
|
+
* Any other system is never valid.
|
|
110
|
+
*
|
|
111
|
+
* Time: `tGpsMs` is GPS-scale epoch ms, like everywhere in this module.
|
|
112
|
+
* GLONASS and SBAS tocs are on the UTC axis (see {@link computeSatPosition}),
|
|
113
|
+
* so for those t is moved to UTC first — on a ±15-min window the 18-s
|
|
114
|
+
* leap-second offset matters.
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
/** Validity half-window |t − toc| per system letter, in ms. */
|
|
118
|
+
declare const EPHEMERIS_VALIDITY_MS: Readonly<Record<string, number>>;
|
|
119
|
+
/** May `eph` position its satellite at GPS-scale epoch `tGpsMs`? */
|
|
120
|
+
declare function isEphemerisValid(eph: Ephemeris, tGpsMs: number): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* The ephemeris in `ephs` whose toc is nearest to `tGpsMs` among those valid
|
|
123
|
+
* at `tGpsMs`, or null when none is. `ephs` may mix satellites; filter by PRN
|
|
124
|
+
* first if it does.
|
|
125
|
+
*/
|
|
126
|
+
declare function nearestValidEphemeris(ephs: readonly Ephemeris[] | undefined, tGpsMs: number): Ephemeris | null;
|
|
127
|
+
|
|
94
128
|
/**
|
|
95
129
|
* Satellite orbit computation from broadcast ephemerides.
|
|
96
130
|
* Supports GPS, Galileo, BeiDou (Keplerian) and GLONASS (Runge-Kutta).
|
|
@@ -164,8 +198,11 @@ declare function ecefToAzEl(rxX: number, rxY: number, rxZ: number, satX: number,
|
|
|
164
198
|
* constellation time scale, as a multi-GNSS receiver solves: every extra
|
|
165
199
|
* time scale costs one observation. QZSS and SBAS share the GPS clock —
|
|
166
200
|
* QZSST and SBAS network time are steered to GPST (RTKLIB pntpos does the
|
|
167
|
-
* same) — so a lone SBAS GEO doesn't inflate TDOP/GDOP.
|
|
168
|
-
*
|
|
201
|
+
* same) — so a lone SBAS GEO doesn't inflate TDOP/GDOP. A time scale
|
|
202
|
+
* with a single satellite in view is left out: that satellite only fixes
|
|
203
|
+
* its own clock, adding nothing to PDOP/HDOP/VDOP and an unrecoverable ~1
|
|
204
|
+
* to TDOP². Untagged satellites share a single clock (the classic
|
|
205
|
+
* single-system model).
|
|
169
206
|
*
|
|
170
207
|
* @param satAzEls Satellite azimuth/elevation pairs (radians), optionally
|
|
171
208
|
* tagged with their PRN.
|
|
@@ -178,11 +215,12 @@ declare function computeDop(satAzEls: {
|
|
|
178
215
|
prn?: string;
|
|
179
216
|
}[]): DopValues | null;
|
|
180
217
|
/**
|
|
181
|
-
* Find the best ephemeris for a given PRN at a given time
|
|
182
|
-
*
|
|
218
|
+
* Find the best ephemeris for a given PRN at a given time: the one with the
|
|
219
|
+
* closest epoch (toe/toc) among those within their broadcast validity at
|
|
220
|
+
* that time ({@link isEphemerisValid}); null when none is valid.
|
|
183
221
|
* @param ephemerides Array of candidate ephemerides
|
|
184
222
|
* @param prn Satellite PRN identifier (e.g. "G01")
|
|
185
|
-
* @param timeMs Target time
|
|
223
|
+
* @param timeMs Target time, GPS-scale epoch milliseconds
|
|
186
224
|
*/
|
|
187
225
|
declare function selectEphemeris(ephemerides: Ephemeris[], prn: string, timeMs: number): Ephemeris | null;
|
|
188
226
|
/**
|
|
@@ -300,4 +338,4 @@ declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, num
|
|
|
300
338
|
*/
|
|
301
339
|
declare function computeVisibilityFromPositions(all: AllPositionsData, elevationMaskDeg?: number | number[]): VisibilityResult;
|
|
302
340
|
|
|
303
|
-
export { type AllPositionsData, type AlmanacPosition, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris };
|
|
341
|
+
export { type AllPositionsData, type AlmanacPosition, type DopValues, EPHEMERIS_VALIDITY_MS, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, isEphemerisValid, keplerPosition, maskRadForAzimuth, navTimesFromEph, nearestValidEphemeris, rangeRate, selectEphemeris };
|
package/dist/orbit.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
EPHEMERIS_VALIDITY_MS,
|
|
2
3
|
almanacEpochMs,
|
|
3
4
|
almanacSatPosition,
|
|
4
5
|
computeAllPositions,
|
|
@@ -13,12 +14,14 @@ import {
|
|
|
13
14
|
glonassAlmanacEpochMs,
|
|
14
15
|
glonassAlmanacPosition,
|
|
15
16
|
glonassPosition,
|
|
17
|
+
isEphemerisValid,
|
|
16
18
|
keplerPosition,
|
|
17
19
|
maskRadForAzimuth,
|
|
18
20
|
navTimesFromEph,
|
|
21
|
+
nearestValidEphemeris,
|
|
19
22
|
rangeRate,
|
|
20
23
|
selectEphemeris
|
|
21
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-7T5DLVZL.js";
|
|
22
25
|
import "./chunk-HVXYFUCB.js";
|
|
23
26
|
import {
|
|
24
27
|
ecefToGeodetic,
|
|
@@ -28,6 +31,7 @@ import "./chunk-LEEU5OIO.js";
|
|
|
28
31
|
import "./chunk-6FAL6P4G.js";
|
|
29
32
|
import "./chunk-FIEWO4J4.js";
|
|
30
33
|
export {
|
|
34
|
+
EPHEMERIS_VALIDITY_MS,
|
|
31
35
|
almanacEpochMs,
|
|
32
36
|
almanacSatPosition,
|
|
33
37
|
computeAllPositions,
|
|
@@ -44,9 +48,11 @@ export {
|
|
|
44
48
|
glonassAlmanacEpochMs,
|
|
45
49
|
glonassAlmanacPosition,
|
|
46
50
|
glonassPosition,
|
|
51
|
+
isEphemerisValid,
|
|
47
52
|
keplerPosition,
|
|
48
53
|
maskRadForAzimuth,
|
|
49
54
|
navTimesFromEph,
|
|
55
|
+
nearestValidEphemeris,
|
|
50
56
|
rangeRate,
|
|
51
57
|
selectEphemeris
|
|
52
58
|
};
|
package/dist/positioning.cjs
CHANGED
|
@@ -254,6 +254,38 @@ function invertMatrix(A) {
|
|
|
254
254
|
return M.map((row) => row.slice(n));
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
// src/orbit/validity.ts
|
|
258
|
+
var H = 36e5;
|
|
259
|
+
var MIN = 6e4;
|
|
260
|
+
var EPHEMERIS_VALIDITY_MS = {
|
|
261
|
+
G: 2 * H,
|
|
262
|
+
J: 2 * H,
|
|
263
|
+
E: 2.5 * H,
|
|
264
|
+
C: 90 * MIN,
|
|
265
|
+
R: 15 * MIN,
|
|
266
|
+
I: 2 * H,
|
|
267
|
+
S: 6 * MIN
|
|
268
|
+
};
|
|
269
|
+
function tocDistanceMs(eph, tGpsMs) {
|
|
270
|
+
const t = eph.system === "R" || eph.system === "S" ? tGpsMs - getGpsLeap(new Date(tGpsMs)) * 1e3 : tGpsMs;
|
|
271
|
+
return Math.abs(eph.tocDate.getTime() - t);
|
|
272
|
+
}
|
|
273
|
+
function nearestValidEphemeris(ephs, tGpsMs) {
|
|
274
|
+
if (!ephs) return null;
|
|
275
|
+
let best = null;
|
|
276
|
+
let bestDt = Infinity;
|
|
277
|
+
for (const eph of ephs) {
|
|
278
|
+
const dt = tocDistanceMs(eph, tGpsMs);
|
|
279
|
+
const w = EPHEMERIS_VALIDITY_MS[eph.system];
|
|
280
|
+
if (w === void 0 || dt > w) continue;
|
|
281
|
+
if (dt < bestDt) {
|
|
282
|
+
bestDt = dt;
|
|
283
|
+
best = eph;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return best;
|
|
287
|
+
}
|
|
288
|
+
|
|
257
289
|
// src/orbit/index.ts
|
|
258
290
|
var GM_GPS = 3986005e8;
|
|
259
291
|
var GM_GAL = 3986004418e5;
|
|
@@ -442,24 +474,30 @@ function dopClock(prn) {
|
|
|
442
474
|
return sys === "J" || sys === "S" ? "G" : sys;
|
|
443
475
|
}
|
|
444
476
|
function computeDop(satAzEls) {
|
|
445
|
-
const
|
|
446
|
-
const
|
|
477
|
+
const perClock = /* @__PURE__ */ new Map();
|
|
478
|
+
for (const s of satAzEls) {
|
|
479
|
+
const c = dopClock(s.prn);
|
|
480
|
+
perClock.set(c, (perClock.get(c) ?? 0) + 1);
|
|
481
|
+
}
|
|
482
|
+
const sats = perClock.size > 1 ? satAzEls.filter((s) => perClock.get(dopClock(s.prn)) > 1) : satAzEls;
|
|
483
|
+
const n = sats.length;
|
|
484
|
+
const clocks = [...new Set(sats.map((s) => dopClock(s.prn)))];
|
|
447
485
|
const m = 3 + clocks.length;
|
|
448
486
|
if (n < Math.max(4, m)) return null;
|
|
449
|
-
const
|
|
450
|
-
for (const { az, el, prn } of
|
|
487
|
+
const H3 = [];
|
|
488
|
+
for (const { az, el, prn } of sats) {
|
|
451
489
|
const cosEl = Math.cos(el);
|
|
452
490
|
const row = [cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el)];
|
|
453
491
|
const clock = dopClock(prn);
|
|
454
492
|
for (const c of clocks) row.push(c === clock ? 1 : 0);
|
|
455
|
-
|
|
493
|
+
H3.push(row);
|
|
456
494
|
}
|
|
457
495
|
const HtH = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
458
496
|
for (let i = 0; i < m; i++) {
|
|
459
497
|
for (let j = 0; j < m; j++) {
|
|
460
498
|
let sum = 0;
|
|
461
499
|
for (let k = 0; k < n; k++) {
|
|
462
|
-
sum +=
|
|
500
|
+
sum += H3[k][i] * H3[k][j];
|
|
463
501
|
}
|
|
464
502
|
HtH[i][j] = sum;
|
|
465
503
|
}
|
|
@@ -495,18 +533,7 @@ function computeSatPosition(eph, timeMs) {
|
|
|
495
533
|
return keplerPosition(eph, tow);
|
|
496
534
|
}
|
|
497
535
|
function selectBest(ephs, timeMs) {
|
|
498
|
-
|
|
499
|
-
let bestDt = Infinity;
|
|
500
|
-
for (const eph of ephs) {
|
|
501
|
-
const dt = Math.abs(timeMs - eph.tocDate.getTime());
|
|
502
|
-
const maxAge = eph.system === "R" || eph.system === "S" ? 18e5 : 4 * 36e5;
|
|
503
|
-
if (dt > maxAge) continue;
|
|
504
|
-
if (dt < bestDt) {
|
|
505
|
-
bestDt = dt;
|
|
506
|
-
best = eph;
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
return best;
|
|
536
|
+
return nearestValidEphemeris(ephs, timeMs);
|
|
510
537
|
}
|
|
511
538
|
var GPS_EPOCH_MS = START_GPS_TIME.getTime();
|
|
512
539
|
var MS_PER_WEEK = 7 * 864e5;
|
|
@@ -1302,7 +1329,7 @@ function solveDgnss(rover, base, basePos, ephemerides, timeMs, opts = {}) {
|
|
|
1302
1329
|
let cov = null;
|
|
1303
1330
|
for (let iter = 0; iter < maxIterations; iter++) {
|
|
1304
1331
|
iterations = iter + 1;
|
|
1305
|
-
const
|
|
1332
|
+
const H3 = [];
|
|
1306
1333
|
const v = [];
|
|
1307
1334
|
const terms = /* @__PURE__ */ new Map();
|
|
1308
1335
|
const termOf = (g) => {
|
|
@@ -1318,11 +1345,11 @@ function solveDgnss(rover, base, basePos, ephemerides, timeMs, opts = {}) {
|
|
|
1318
1345
|
const tr = termOf(row.ref);
|
|
1319
1346
|
const pred = ts.rho - row.g.rhoB + ts.dTropo - (tr.rho - row.ref.rhoB + tr.dTropo);
|
|
1320
1347
|
v.push(row.z - pred);
|
|
1321
|
-
|
|
1348
|
+
H3.push([ts.u[0] - tr.u[0], ts.u[1] - tr.u[1], ts.u[2] - tr.u[2]]);
|
|
1322
1349
|
}
|
|
1323
|
-
const Ht = transpose(
|
|
1350
|
+
const Ht = transpose(H3);
|
|
1324
1351
|
const HtW = matMul(Ht, W);
|
|
1325
|
-
const N = matMul(HtW,
|
|
1352
|
+
const N = matMul(HtW, H3);
|
|
1326
1353
|
const b = matMul(
|
|
1327
1354
|
HtW,
|
|
1328
1355
|
v.map((s) => [s])
|
|
@@ -1338,7 +1365,7 @@ function solveDgnss(rover, base, basePos, ephemerides, timeMs, opts = {}) {
|
|
|
1338
1365
|
z += dx[2][0];
|
|
1339
1366
|
cov = Ninv;
|
|
1340
1367
|
rows.forEach((row, i) => {
|
|
1341
|
-
residuals[row.g.prn] = v[i] - (
|
|
1368
|
+
residuals[row.g.prn] = v[i] - (H3[i][0] * dx[0][0] + H3[i][1] * dx[1][0] + H3[i][2] * dx[2][0]);
|
|
1342
1369
|
});
|
|
1343
1370
|
if (Math.hypot(dx[0][0], dx[1][0], dx[2][0]) < convergenceM) {
|
|
1344
1371
|
converged = true;
|
|
@@ -1732,19 +1759,19 @@ var RtkFloatEngine = class {
|
|
|
1732
1759
|
const PPrior = this.P;
|
|
1733
1760
|
let xi = [...this.x];
|
|
1734
1761
|
let K = [];
|
|
1735
|
-
let
|
|
1762
|
+
let H3 = [];
|
|
1736
1763
|
for (let it = 0; it < Math.max(o.updateIterations, 1); it++) {
|
|
1737
|
-
|
|
1764
|
+
H3 = [];
|
|
1738
1765
|
const v = [];
|
|
1739
1766
|
for (const row of rows) {
|
|
1740
1767
|
const { pred, h } = predict(row, xi);
|
|
1741
1768
|
let corr = 0;
|
|
1742
1769
|
for (let j = 0; j < n; j++) corr += h[j] * (xPrior[j] - xi[j]);
|
|
1743
1770
|
v.push(row.z - pred - corr);
|
|
1744
|
-
|
|
1771
|
+
H3.push(h);
|
|
1745
1772
|
}
|
|
1746
|
-
const Ht = transpose(
|
|
1747
|
-
const S = matMul(matMul(
|
|
1773
|
+
const Ht = transpose(H3);
|
|
1774
|
+
const S = matMul(matMul(H3, PPrior), Ht);
|
|
1748
1775
|
for (let i = 0; i < rows.length; i++)
|
|
1749
1776
|
for (let j = 0; j < rows.length; j++) S[i][j] += R[i][j];
|
|
1750
1777
|
const Sinv = matInv(S);
|
|
@@ -1760,7 +1787,7 @@ var RtkFloatEngine = class {
|
|
|
1760
1787
|
xi = xPrior.map((s, i) => s + dx[i][0]);
|
|
1761
1788
|
}
|
|
1762
1789
|
this.x = xi;
|
|
1763
|
-
const KH = matMul(K,
|
|
1790
|
+
const KH = matMul(K, H3);
|
|
1764
1791
|
const IKH = zeros(n, n);
|
|
1765
1792
|
for (let i = 0; i < n; i++)
|
|
1766
1793
|
for (let j = 0; j < n; j++) IKH[i][j] = (i === j ? 1 : 0) - KH[i][j];
|
package/dist/positioning.js
CHANGED
|
@@ -40,9 +40,9 @@ import {
|
|
|
40
40
|
sunEcef,
|
|
41
41
|
toRtkEpoch,
|
|
42
42
|
wlWavelength
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-NOGA5KD7.js";
|
|
44
44
|
import "./chunk-WQX354KD.js";
|
|
45
|
-
import "./chunk-
|
|
45
|
+
import "./chunk-7T5DLVZL.js";
|
|
46
46
|
import "./chunk-HVXYFUCB.js";
|
|
47
47
|
import "./chunk-CVCTRIWU.js";
|
|
48
48
|
import "./chunk-37QNKGTC.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gnss-js",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.0",
|
|
4
4
|
"description": "Comprehensive GNSS library for JavaScript — time scales, coordinates, RINEX parsing, RTCM3 decoding, orbit computation, and signal analysis",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|