gnss-js 2.8.2 → 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-5OWRCF56.js → chunk-7T5DLVZL.js} +43 -15
- package/dist/{chunk-CLNLOYBX.js → chunk-NOGA5KD7.js} +1 -1
- package/dist/index.cjs +63 -32
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +8 -2
- package/dist/orbit.cjs +46 -15
- package/dist/orbit.d.cts +39 -4
- package/dist/orbit.d.ts +39 -4
- package/dist/orbit.js +7 -1
- package/dist/positioning.cjs +47 -26
- 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;
|
|
@@ -419,20 +455,20 @@ function computeDop(satAzEls) {
|
|
|
419
455
|
const clocks = [...new Set(sats.map((s) => dopClock(s.prn)))];
|
|
420
456
|
const m = 3 + clocks.length;
|
|
421
457
|
if (n < Math.max(4, m)) return null;
|
|
422
|
-
const
|
|
458
|
+
const H2 = [];
|
|
423
459
|
for (const { az, el, prn } of sats) {
|
|
424
460
|
const cosEl = Math.cos(el);
|
|
425
461
|
const row = [cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el)];
|
|
426
462
|
const clock = dopClock(prn);
|
|
427
463
|
for (const c of clocks) row.push(c === clock ? 1 : 0);
|
|
428
|
-
|
|
464
|
+
H2.push(row);
|
|
429
465
|
}
|
|
430
466
|
const HtH = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
431
467
|
for (let i = 0; i < m; i++) {
|
|
432
468
|
for (let j = 0; j < m; j++) {
|
|
433
469
|
let sum = 0;
|
|
434
470
|
for (let k = 0; k < n; k++) {
|
|
435
|
-
sum +=
|
|
471
|
+
sum += H2[k][i] * H2[k][j];
|
|
436
472
|
}
|
|
437
473
|
HtH[i][j] = sum;
|
|
438
474
|
}
|
|
@@ -533,18 +569,7 @@ function computeAllPositions(ephemerides, times, rxPos) {
|
|
|
533
569
|
return { prns, times, positions };
|
|
534
570
|
}
|
|
535
571
|
function selectBest(ephs, timeMs) {
|
|
536
|
-
|
|
537
|
-
let bestDt = Infinity;
|
|
538
|
-
for (const eph of ephs) {
|
|
539
|
-
const dt = Math.abs(timeMs - eph.tocDate.getTime());
|
|
540
|
-
const maxAge = eph.system === "R" || eph.system === "S" ? 18e5 : 4 * 36e5;
|
|
541
|
-
if (dt > maxAge) continue;
|
|
542
|
-
if (dt < bestDt) {
|
|
543
|
-
bestDt = dt;
|
|
544
|
-
best = eph;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
return best;
|
|
572
|
+
return nearestValidEphemeris(ephs, timeMs);
|
|
548
573
|
}
|
|
549
574
|
var GPS_EPOCH_MS2 = START_GPS_TIME.getTime();
|
|
550
575
|
var MS_PER_WEEK = 7 * 864e5;
|
|
@@ -786,6 +811,9 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
786
811
|
|
|
787
812
|
export {
|
|
788
813
|
invertMatrix,
|
|
814
|
+
EPHEMERIS_VALIDITY_MS,
|
|
815
|
+
isEphemerisValid,
|
|
816
|
+
nearestValidEphemeris,
|
|
789
817
|
almanacEpochMs,
|
|
790
818
|
almanacSatPosition,
|
|
791
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;
|
|
@@ -12808,18 +12847,7 @@ function computeAllPositions(ephemerides, times, rxPos) {
|
|
|
12808
12847
|
return { prns, times, positions };
|
|
12809
12848
|
}
|
|
12810
12849
|
function selectBest(ephs, timeMs) {
|
|
12811
|
-
|
|
12812
|
-
let bestDt = Infinity;
|
|
12813
|
-
for (const eph of ephs) {
|
|
12814
|
-
const dt = Math.abs(timeMs - eph.tocDate.getTime());
|
|
12815
|
-
const maxAge = eph.system === "R" || eph.system === "S" ? 18e5 : 4 * 36e5;
|
|
12816
|
-
if (dt > maxAge) continue;
|
|
12817
|
-
if (dt < bestDt) {
|
|
12818
|
-
bestDt = dt;
|
|
12819
|
-
best = eph;
|
|
12820
|
-
}
|
|
12821
|
-
}
|
|
12822
|
-
return best;
|
|
12850
|
+
return nearestValidEphemeris(ephs, timeMs);
|
|
12823
12851
|
}
|
|
12824
12852
|
var GPS_EPOCH_MS24 = START_GPS_TIME.getTime();
|
|
12825
12853
|
var MS_PER_WEEK13 = 7 * 864e5;
|
|
@@ -13060,14 +13088,14 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
13060
13088
|
}
|
|
13061
13089
|
|
|
13062
13090
|
// src/frames/index.ts
|
|
13063
|
-
var
|
|
13091
|
+
var H2 = (t, d, r, tDot, dDot, rDot, epoch) => ({ t, d, r, tDot, dDot, rDot, epoch });
|
|
13064
13092
|
var Z = [0, 0, 0];
|
|
13065
13093
|
var FROM_ITRF2020 = {
|
|
13066
|
-
ITRF2014:
|
|
13067
|
-
ITRF2008:
|
|
13068
|
-
ITRF2005:
|
|
13069
|
-
ITRF2000:
|
|
13070
|
-
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(
|
|
13071
13099
|
[6.5, -3.9, -77.9],
|
|
13072
13100
|
3.98,
|
|
13073
13101
|
[0, 0, 0.36],
|
|
@@ -13076,7 +13104,7 @@ var FROM_ITRF2020 = {
|
|
|
13076
13104
|
[0, 0, 0.02],
|
|
13077
13105
|
2015
|
|
13078
13106
|
),
|
|
13079
|
-
ITRF96:
|
|
13107
|
+
ITRF96: H2(
|
|
13080
13108
|
[6.5, -3.9, -77.9],
|
|
13081
13109
|
3.98,
|
|
13082
13110
|
[0, 0, 0.36],
|
|
@@ -13085,7 +13113,7 @@ var FROM_ITRF2020 = {
|
|
|
13085
13113
|
[0, 0, 0.02],
|
|
13086
13114
|
2015
|
|
13087
13115
|
),
|
|
13088
|
-
ITRF94:
|
|
13116
|
+
ITRF94: H2(
|
|
13089
13117
|
[6.5, -3.9, -77.9],
|
|
13090
13118
|
3.98,
|
|
13091
13119
|
[0, 0, 0.36],
|
|
@@ -13094,7 +13122,7 @@ var FROM_ITRF2020 = {
|
|
|
13094
13122
|
[0, 0, 0.02],
|
|
13095
13123
|
2015
|
|
13096
13124
|
),
|
|
13097
|
-
ITRF93:
|
|
13125
|
+
ITRF93: H2(
|
|
13098
13126
|
[-65.8, 1.9, -71.3],
|
|
13099
13127
|
4.47,
|
|
13100
13128
|
[-3.36, -4.33, 0.75],
|
|
@@ -13103,7 +13131,7 @@ var FROM_ITRF2020 = {
|
|
|
13103
13131
|
[-0.11, -0.19, 0.07],
|
|
13104
13132
|
2015
|
|
13105
13133
|
),
|
|
13106
|
-
ITRF92:
|
|
13134
|
+
ITRF92: H2(
|
|
13107
13135
|
[14.5, -1.9, -85.9],
|
|
13108
13136
|
3.27,
|
|
13109
13137
|
[0, 0, 0.36],
|
|
@@ -13112,7 +13140,7 @@ var FROM_ITRF2020 = {
|
|
|
13112
13140
|
[0, 0, 0.02],
|
|
13113
13141
|
2015
|
|
13114
13142
|
),
|
|
13115
|
-
ITRF91:
|
|
13143
|
+
ITRF91: H2(
|
|
13116
13144
|
[26.5, 12.1, -91.9],
|
|
13117
13145
|
4.67,
|
|
13118
13146
|
[0, 0, 0.36],
|
|
@@ -13121,7 +13149,7 @@ var FROM_ITRF2020 = {
|
|
|
13121
13149
|
[0, 0, 0.02],
|
|
13122
13150
|
2015
|
|
13123
13151
|
),
|
|
13124
|
-
ITRF90:
|
|
13152
|
+
ITRF90: H2(
|
|
13125
13153
|
[24.5, 8.1, -107.9],
|
|
13126
13154
|
4.97,
|
|
13127
13155
|
[0, 0, 0.36],
|
|
@@ -13130,7 +13158,7 @@ var FROM_ITRF2020 = {
|
|
|
13130
13158
|
[0, 0, 0.02],
|
|
13131
13159
|
2015
|
|
13132
13160
|
),
|
|
13133
|
-
ITRF89:
|
|
13161
|
+
ITRF89: H2(
|
|
13134
13162
|
[29.5, 32.1, -145.9],
|
|
13135
13163
|
8.37,
|
|
13136
13164
|
[0, 0, 0.36],
|
|
@@ -13139,7 +13167,7 @@ var FROM_ITRF2020 = {
|
|
|
13139
13167
|
[0, 0, 0.02],
|
|
13140
13168
|
2015
|
|
13141
13169
|
),
|
|
13142
|
-
ITRF88:
|
|
13170
|
+
ITRF88: H2(
|
|
13143
13171
|
[24.5, -3.9, -169.9],
|
|
13144
13172
|
11.47,
|
|
13145
13173
|
[0.1, 0, 0.36],
|
|
@@ -13149,10 +13177,10 @@ var FROM_ITRF2020 = {
|
|
|
13149
13177
|
2015
|
|
13150
13178
|
),
|
|
13151
13179
|
/** ITRF2020 → ETRF2020, EPSG:10572 (epoch-1989 variant) */
|
|
13152
|
-
ETRF2020:
|
|
13180
|
+
ETRF2020: H2(Z, 0, Z, Z, 0, [0.086, 0.519, -0.753], 1989)
|
|
13153
13181
|
};
|
|
13154
|
-
var ITRF2014_TO_ETRF2014 =
|
|
13155
|
-
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(
|
|
13156
13184
|
[54.7, 52.2, -74.1],
|
|
13157
13185
|
2.12,
|
|
13158
13186
|
[1.701, 10.29, -16.632],
|
|
@@ -13161,7 +13189,7 @@ var ITRF2014_TO_ETRF2000 = H(
|
|
|
13161
13189
|
[0.081, 0.49, -0.792],
|
|
13162
13190
|
2010
|
|
13163
13191
|
);
|
|
13164
|
-
var ITRF2014_TO_NAD83_2011 =
|
|
13192
|
+
var ITRF2014_TO_NAD83_2011 = H2(
|
|
13165
13193
|
[1005.3, -1909.21, -541.57],
|
|
13166
13194
|
0.36891,
|
|
13167
13195
|
[-26.78138, 0.42027, -10.93206],
|
|
@@ -15837,7 +15865,7 @@ function moonEcef(timeMs) {
|
|
|
15837
15865
|
];
|
|
15838
15866
|
return eciToEcef(eci, gmst(timeMs));
|
|
15839
15867
|
}
|
|
15840
|
-
var
|
|
15868
|
+
var H22 = 0.6078;
|
|
15841
15869
|
var L2 = 0.0847;
|
|
15842
15870
|
var RE = 6378137;
|
|
15843
15871
|
var GM_SUN_RATIO = 332946.0482;
|
|
@@ -15862,7 +15890,7 @@ function solidEarthTide(rcv, sun, moon) {
|
|
|
15862
15890
|
];
|
|
15863
15891
|
const dot2 = rHat[0] * jHat[0] + rHat[1] * jHat[1] + rHat[2] * jHat[2];
|
|
15864
15892
|
const factor = ratio * RE * RE * RE * RE / (rj * rj * rj);
|
|
15865
|
-
const radialScale =
|
|
15893
|
+
const radialScale = H22 * (1.5 * dot2 * dot2 - 0.5);
|
|
15866
15894
|
const tanScale = 3 * L2 * dot2;
|
|
15867
15895
|
for (let k = 0; k < 3; k++) {
|
|
15868
15896
|
disp[k] += factor * (radialScale * rHat[k] + tanScale * (jHat[k] - dot2 * rHat[k]));
|
|
@@ -19522,6 +19550,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
19522
19550
|
DELTA_GLO_L2,
|
|
19523
19551
|
DUAL_FREQ_PAIRS,
|
|
19524
19552
|
EMPTY_WARNINGS,
|
|
19553
|
+
EPHEMERIS_VALIDITY_MS,
|
|
19525
19554
|
FREQ,
|
|
19526
19555
|
FREQ_BDS_B1A,
|
|
19527
19556
|
FREQ_BDS_B1C,
|
|
@@ -19738,6 +19767,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
19738
19767
|
hdrLine,
|
|
19739
19768
|
horizonDistance,
|
|
19740
19769
|
ionoFree,
|
|
19770
|
+
isEphemerisValid,
|
|
19741
19771
|
isSbasL1Preamble,
|
|
19742
19772
|
isSbasL5Correction,
|
|
19743
19773
|
isSsrMessage,
|
|
@@ -19750,6 +19780,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
19750
19780
|
meridianArc,
|
|
19751
19781
|
moonEcef,
|
|
19752
19782
|
navTimesFromEph,
|
|
19783
|
+
nearestValidEphemeris,
|
|
19753
19784
|
niellMapping,
|
|
19754
19785
|
nlWavelength,
|
|
19755
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;
|
|
@@ -580,20 +619,20 @@ function computeDop(satAzEls) {
|
|
|
580
619
|
const clocks = [...new Set(sats.map((s) => dopClock(s.prn)))];
|
|
581
620
|
const m = 3 + clocks.length;
|
|
582
621
|
if (n < Math.max(4, m)) return null;
|
|
583
|
-
const
|
|
622
|
+
const H2 = [];
|
|
584
623
|
for (const { az, el, prn } of sats) {
|
|
585
624
|
const cosEl = Math.cos(el);
|
|
586
625
|
const row = [cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el)];
|
|
587
626
|
const clock = dopClock(prn);
|
|
588
627
|
for (const c of clocks) row.push(c === clock ? 1 : 0);
|
|
589
|
-
|
|
628
|
+
H2.push(row);
|
|
590
629
|
}
|
|
591
630
|
const HtH = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
592
631
|
for (let i = 0; i < m; i++) {
|
|
593
632
|
for (let j = 0; j < m; j++) {
|
|
594
633
|
let sum = 0;
|
|
595
634
|
for (let k = 0; k < n; k++) {
|
|
596
|
-
sum +=
|
|
635
|
+
sum += H2[k][i] * H2[k][j];
|
|
597
636
|
}
|
|
598
637
|
HtH[i][j] = sum;
|
|
599
638
|
}
|
|
@@ -694,18 +733,7 @@ function computeAllPositions(ephemerides, times, rxPos) {
|
|
|
694
733
|
return { prns, times, positions };
|
|
695
734
|
}
|
|
696
735
|
function selectBest(ephs, timeMs) {
|
|
697
|
-
|
|
698
|
-
let bestDt = Infinity;
|
|
699
|
-
for (const eph of ephs) {
|
|
700
|
-
const dt = Math.abs(timeMs - eph.tocDate.getTime());
|
|
701
|
-
const maxAge = eph.system === "R" || eph.system === "S" ? 18e5 : 4 * 36e5;
|
|
702
|
-
if (dt > maxAge) continue;
|
|
703
|
-
if (dt < bestDt) {
|
|
704
|
-
bestDt = dt;
|
|
705
|
-
best = eph;
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
return best;
|
|
736
|
+
return nearestValidEphemeris(ephs, timeMs);
|
|
709
737
|
}
|
|
710
738
|
var GPS_EPOCH_MS2 = START_GPS_TIME.getTime();
|
|
711
739
|
var MS_PER_WEEK = 7 * 864e5;
|
|
@@ -946,6 +974,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
946
974
|
}
|
|
947
975
|
// Annotate the CommonJS export names for ESM import in node:
|
|
948
976
|
0 && (module.exports = {
|
|
977
|
+
EPHEMERIS_VALIDITY_MS,
|
|
949
978
|
almanacEpochMs,
|
|
950
979
|
almanacSatPosition,
|
|
951
980
|
computeAllPositions,
|
|
@@ -962,9 +991,11 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
962
991
|
glonassAlmanacEpochMs,
|
|
963
992
|
glonassAlmanacPosition,
|
|
964
993
|
glonassPosition,
|
|
994
|
+
isEphemerisValid,
|
|
965
995
|
keplerPosition,
|
|
966
996
|
maskRadForAzimuth,
|
|
967
997
|
navTimesFromEph,
|
|
998
|
+
nearestValidEphemeris,
|
|
968
999
|
rangeRate,
|
|
969
1000
|
selectEphemeris
|
|
970
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).
|
|
@@ -181,11 +215,12 @@ declare function computeDop(satAzEls: {
|
|
|
181
215
|
prn?: string;
|
|
182
216
|
}[]): DopValues | null;
|
|
183
217
|
/**
|
|
184
|
-
* Find the best ephemeris for a given PRN at a given time
|
|
185
|
-
*
|
|
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.
|
|
186
221
|
* @param ephemerides Array of candidate ephemerides
|
|
187
222
|
* @param prn Satellite PRN identifier (e.g. "G01")
|
|
188
|
-
* @param timeMs Target time
|
|
223
|
+
* @param timeMs Target time, GPS-scale epoch milliseconds
|
|
189
224
|
*/
|
|
190
225
|
declare function selectEphemeris(ephemerides: Ephemeris[], prn: string, timeMs: number): Ephemeris | null;
|
|
191
226
|
/**
|
|
@@ -303,4 +338,4 @@ declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, num
|
|
|
303
338
|
*/
|
|
304
339
|
declare function computeVisibilityFromPositions(all: AllPositionsData, elevationMaskDeg?: number | number[]): VisibilityResult;
|
|
305
340
|
|
|
306
|
-
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).
|
|
@@ -181,11 +215,12 @@ declare function computeDop(satAzEls: {
|
|
|
181
215
|
prn?: string;
|
|
182
216
|
}[]): DopValues | null;
|
|
183
217
|
/**
|
|
184
|
-
* Find the best ephemeris for a given PRN at a given time
|
|
185
|
-
*
|
|
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.
|
|
186
221
|
* @param ephemerides Array of candidate ephemerides
|
|
187
222
|
* @param prn Satellite PRN identifier (e.g. "G01")
|
|
188
|
-
* @param timeMs Target time
|
|
223
|
+
* @param timeMs Target time, GPS-scale epoch milliseconds
|
|
189
224
|
*/
|
|
190
225
|
declare function selectEphemeris(ephemerides: Ephemeris[], prn: string, timeMs: number): Ephemeris | null;
|
|
191
226
|
/**
|
|
@@ -303,4 +338,4 @@ declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, num
|
|
|
303
338
|
*/
|
|
304
339
|
declare function computeVisibilityFromPositions(all: AllPositionsData, elevationMaskDeg?: number | number[]): VisibilityResult;
|
|
305
340
|
|
|
306
|
-
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;
|
|
@@ -452,20 +484,20 @@ function computeDop(satAzEls) {
|
|
|
452
484
|
const clocks = [...new Set(sats.map((s) => dopClock(s.prn)))];
|
|
453
485
|
const m = 3 + clocks.length;
|
|
454
486
|
if (n < Math.max(4, m)) return null;
|
|
455
|
-
const
|
|
487
|
+
const H3 = [];
|
|
456
488
|
for (const { az, el, prn } of sats) {
|
|
457
489
|
const cosEl = Math.cos(el);
|
|
458
490
|
const row = [cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el)];
|
|
459
491
|
const clock = dopClock(prn);
|
|
460
492
|
for (const c of clocks) row.push(c === clock ? 1 : 0);
|
|
461
|
-
|
|
493
|
+
H3.push(row);
|
|
462
494
|
}
|
|
463
495
|
const HtH = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
464
496
|
for (let i = 0; i < m; i++) {
|
|
465
497
|
for (let j = 0; j < m; j++) {
|
|
466
498
|
let sum = 0;
|
|
467
499
|
for (let k = 0; k < n; k++) {
|
|
468
|
-
sum +=
|
|
500
|
+
sum += H3[k][i] * H3[k][j];
|
|
469
501
|
}
|
|
470
502
|
HtH[i][j] = sum;
|
|
471
503
|
}
|
|
@@ -501,18 +533,7 @@ function computeSatPosition(eph, timeMs) {
|
|
|
501
533
|
return keplerPosition(eph, tow);
|
|
502
534
|
}
|
|
503
535
|
function selectBest(ephs, timeMs) {
|
|
504
|
-
|
|
505
|
-
let bestDt = Infinity;
|
|
506
|
-
for (const eph of ephs) {
|
|
507
|
-
const dt = Math.abs(timeMs - eph.tocDate.getTime());
|
|
508
|
-
const maxAge = eph.system === "R" || eph.system === "S" ? 18e5 : 4 * 36e5;
|
|
509
|
-
if (dt > maxAge) continue;
|
|
510
|
-
if (dt < bestDt) {
|
|
511
|
-
bestDt = dt;
|
|
512
|
-
best = eph;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
return best;
|
|
536
|
+
return nearestValidEphemeris(ephs, timeMs);
|
|
516
537
|
}
|
|
517
538
|
var GPS_EPOCH_MS = START_GPS_TIME.getTime();
|
|
518
539
|
var MS_PER_WEEK = 7 * 864e5;
|
|
@@ -1308,7 +1329,7 @@ function solveDgnss(rover, base, basePos, ephemerides, timeMs, opts = {}) {
|
|
|
1308
1329
|
let cov = null;
|
|
1309
1330
|
for (let iter = 0; iter < maxIterations; iter++) {
|
|
1310
1331
|
iterations = iter + 1;
|
|
1311
|
-
const
|
|
1332
|
+
const H3 = [];
|
|
1312
1333
|
const v = [];
|
|
1313
1334
|
const terms = /* @__PURE__ */ new Map();
|
|
1314
1335
|
const termOf = (g) => {
|
|
@@ -1324,11 +1345,11 @@ function solveDgnss(rover, base, basePos, ephemerides, timeMs, opts = {}) {
|
|
|
1324
1345
|
const tr = termOf(row.ref);
|
|
1325
1346
|
const pred = ts.rho - row.g.rhoB + ts.dTropo - (tr.rho - row.ref.rhoB + tr.dTropo);
|
|
1326
1347
|
v.push(row.z - pred);
|
|
1327
|
-
|
|
1348
|
+
H3.push([ts.u[0] - tr.u[0], ts.u[1] - tr.u[1], ts.u[2] - tr.u[2]]);
|
|
1328
1349
|
}
|
|
1329
|
-
const Ht = transpose(
|
|
1350
|
+
const Ht = transpose(H3);
|
|
1330
1351
|
const HtW = matMul(Ht, W);
|
|
1331
|
-
const N = matMul(HtW,
|
|
1352
|
+
const N = matMul(HtW, H3);
|
|
1332
1353
|
const b = matMul(
|
|
1333
1354
|
HtW,
|
|
1334
1355
|
v.map((s) => [s])
|
|
@@ -1344,7 +1365,7 @@ function solveDgnss(rover, base, basePos, ephemerides, timeMs, opts = {}) {
|
|
|
1344
1365
|
z += dx[2][0];
|
|
1345
1366
|
cov = Ninv;
|
|
1346
1367
|
rows.forEach((row, i) => {
|
|
1347
|
-
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]);
|
|
1348
1369
|
});
|
|
1349
1370
|
if (Math.hypot(dx[0][0], dx[1][0], dx[2][0]) < convergenceM) {
|
|
1350
1371
|
converged = true;
|
|
@@ -1738,19 +1759,19 @@ var RtkFloatEngine = class {
|
|
|
1738
1759
|
const PPrior = this.P;
|
|
1739
1760
|
let xi = [...this.x];
|
|
1740
1761
|
let K = [];
|
|
1741
|
-
let
|
|
1762
|
+
let H3 = [];
|
|
1742
1763
|
for (let it = 0; it < Math.max(o.updateIterations, 1); it++) {
|
|
1743
|
-
|
|
1764
|
+
H3 = [];
|
|
1744
1765
|
const v = [];
|
|
1745
1766
|
for (const row of rows) {
|
|
1746
1767
|
const { pred, h } = predict(row, xi);
|
|
1747
1768
|
let corr = 0;
|
|
1748
1769
|
for (let j = 0; j < n; j++) corr += h[j] * (xPrior[j] - xi[j]);
|
|
1749
1770
|
v.push(row.z - pred - corr);
|
|
1750
|
-
|
|
1771
|
+
H3.push(h);
|
|
1751
1772
|
}
|
|
1752
|
-
const Ht = transpose(
|
|
1753
|
-
const S = matMul(matMul(
|
|
1773
|
+
const Ht = transpose(H3);
|
|
1774
|
+
const S = matMul(matMul(H3, PPrior), Ht);
|
|
1754
1775
|
for (let i = 0; i < rows.length; i++)
|
|
1755
1776
|
for (let j = 0; j < rows.length; j++) S[i][j] += R[i][j];
|
|
1756
1777
|
const Sinv = matInv(S);
|
|
@@ -1766,7 +1787,7 @@ var RtkFloatEngine = class {
|
|
|
1766
1787
|
xi = xPrior.map((s, i) => s + dx[i][0]);
|
|
1767
1788
|
}
|
|
1768
1789
|
this.x = xi;
|
|
1769
|
-
const KH = matMul(K,
|
|
1790
|
+
const KH = matMul(K, H3);
|
|
1770
1791
|
const IKH = zeros(n, n);
|
|
1771
1792
|
for (let i = 0; i < n; i++)
|
|
1772
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,
|