gnss-js 1.55.0 → 1.57.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-U32IU7RO.js → chunk-BU6YC6VK.js} +30 -0
- package/dist/{chunk-ZPNMIUNZ.js → chunk-UHLUAU6H.js} +131 -9
- package/dist/index.cjs +169 -9
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +18 -2
- package/dist/positioning.cjs +30 -0
- package/dist/positioning.d.cts +20 -0
- package/dist/positioning.d.ts +20 -0
- package/dist/positioning.js +1 -1
- package/dist/sbf.cjs +139 -9
- package/dist/sbf.d.cts +112 -28
- package/dist/sbf.d.ts +112 -28
- package/dist/sbf.js +17 -1
- package/package.json +1 -1
|
@@ -1551,6 +1551,36 @@ var SbasProcessor = class {
|
|
|
1551
1551
|
}
|
|
1552
1552
|
return n;
|
|
1553
1553
|
}
|
|
1554
|
+
/**
|
|
1555
|
+
* Correction-coverage census at a GPS week/time — a diagnostic funnel over
|
|
1556
|
+
* the current state, explaining how many masked satellites are actually
|
|
1557
|
+
* correctable. Each stage subsumes the requirement of the previous one for a
|
|
1558
|
+
* full range/clock correction: a satellite is `corrected` only when it has
|
|
1559
|
+
* both a fresh fast correction and (for non-SBAS satellites) a fresh
|
|
1560
|
+
* long-term correction (exactly {@link satCorrection}'s gate). `ionoGrid` is
|
|
1561
|
+
* the total number of valid grid points — the additional requirement for the
|
|
1562
|
+
* *iono*-corrected subset a solver forms per pierce point.
|
|
1563
|
+
*
|
|
1564
|
+
* Use it to tell "no corrections applied" (mask empty / products stale) apart
|
|
1565
|
+
* from "corrections applied but the pierce points aren't grid-covered yet".
|
|
1566
|
+
*/
|
|
1567
|
+
coverage(week, tow) {
|
|
1568
|
+
const now = gpsSeconds(week, tow);
|
|
1569
|
+
let masked = 0;
|
|
1570
|
+
let fast = 0;
|
|
1571
|
+
let long = 0;
|
|
1572
|
+
let corrected = 0;
|
|
1573
|
+
for (const s of this.sats) {
|
|
1574
|
+
if (!s.prn) continue;
|
|
1575
|
+
masked++;
|
|
1576
|
+
if (s.fcorr && s.fcorr.t0s !== 0 && s.fcorr.udre < 15 && Math.abs(now - s.fcorr.t0s + this.tlat) <= MAXSBSAGEF)
|
|
1577
|
+
fast++;
|
|
1578
|
+
if (s.prn[0] === "S" || s.lcorr && s.lcorr.t0s !== 0 && Math.abs(now - s.lcorr.t0s) <= MAXSBSAGEL)
|
|
1579
|
+
long++;
|
|
1580
|
+
if (this.satCorrection(s.prn, week, tow)) corrected++;
|
|
1581
|
+
}
|
|
1582
|
+
return { masked, fast, long, corrected, ionoGrid: this.ionoGridPoints() };
|
|
1583
|
+
}
|
|
1554
1584
|
/**
|
|
1555
1585
|
* Satellite range/clock correction for a PRN at a GPS week/tow, or null if
|
|
1556
1586
|
* no valid (unexpired) long-term + fast correction is available. Add `dPos`
|
|
@@ -756,13 +756,42 @@ function parseSbfGloNav(data) {
|
|
|
756
756
|
return { ephemerides, badCrc, messages };
|
|
757
757
|
}
|
|
758
758
|
|
|
759
|
+
// src/navbits/sbas-l5.ts
|
|
760
|
+
var SBAS_L5_PREAMBLE_UW = 6056250;
|
|
761
|
+
function isSbasL1Preamble(msg) {
|
|
762
|
+
return msg[0] === 83 || msg[0] === 154 || msg[0] === 198;
|
|
763
|
+
}
|
|
764
|
+
function sbasL5MessageType(msg) {
|
|
765
|
+
return getBitU(msg, 4, 6);
|
|
766
|
+
}
|
|
767
|
+
var SBAS_L5_MT_NAMES = {
|
|
768
|
+
0: "Do Not Use (test)",
|
|
769
|
+
31: "SBAS satellite mask",
|
|
770
|
+
32: "Satellite clock-ephemeris corrections + covariance",
|
|
771
|
+
34: "Integrity (DFREI/DFRECI)",
|
|
772
|
+
35: "Integrity (DFREI/DFRECI)",
|
|
773
|
+
36: "Integrity (DFREI/DFRECI)",
|
|
774
|
+
37: "Degradation parameters + DFREI scale table",
|
|
775
|
+
39: "SBAS satellite clock/ephemeris/covariance-1",
|
|
776
|
+
40: "SBAS satellite clock/ephemeris/covariance-2",
|
|
777
|
+
42: "SNT-to-UTC offset",
|
|
778
|
+
47: "SBAS satellite almanacs",
|
|
779
|
+
62: "Reserved",
|
|
780
|
+
63: "Null message"
|
|
781
|
+
};
|
|
782
|
+
function sbasL5MessageName(type) {
|
|
783
|
+
return SBAS_L5_MT_NAMES[type] ?? (type >= 1 && type <= 61 ? "Spare" : `Type ${type}`);
|
|
784
|
+
}
|
|
785
|
+
function isSbasL5Correction(type) {
|
|
786
|
+
return type === 31 || type === 32 || type >= 34 && type <= 37 || type === 39 || type === 40 || type === 42 || type === 47;
|
|
787
|
+
}
|
|
788
|
+
|
|
759
789
|
// src/sbf/rawnav-sbas.ts
|
|
760
|
-
function
|
|
790
|
+
function readGeoMessage(view, b) {
|
|
761
791
|
const tow = view.getUint32(b + 8, true);
|
|
762
792
|
const wnc = view.getUint16(b + 12, true);
|
|
763
|
-
const
|
|
764
|
-
|
|
765
|
-
if (!prnStr || prnStr[0] !== "S") return {};
|
|
793
|
+
const prnStr = svidToPrn(view.getUint8(b + 14));
|
|
794
|
+
if (!prnStr || prnStr[0] !== "S") return null;
|
|
766
795
|
const msg = new Uint8Array(32);
|
|
767
796
|
for (let k = 0; k < 8; k++) {
|
|
768
797
|
const w = view.getUint32(b + 20 + 4 * k, true);
|
|
@@ -771,12 +800,29 @@ function feedGeoBlock(view, b, onSbasMessage) {
|
|
|
771
800
|
msg[4 * k + 2] = w >>> 8 & 255;
|
|
772
801
|
msg[4 * k + 3] = w & 255;
|
|
773
802
|
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
const
|
|
803
|
+
return { msg, prn: Number(prnStr.slice(1)) + 100, wnc, towSec: tow / 1e3 };
|
|
804
|
+
}
|
|
805
|
+
function feedGeoBlock(view, b, onSbasMessage) {
|
|
806
|
+
const g = readGeoMessage(view, b);
|
|
807
|
+
if (!g) return {};
|
|
808
|
+
if (!sbasCrcOk(g.msg)) return { badCrc: true };
|
|
809
|
+
onSbasMessage?.(g.msg, g.prn, g.wnc, g.towSec);
|
|
810
|
+
const eph = decodeSbasGeoNav(g.msg, g.prn, g.wnc, g.towSec);
|
|
778
811
|
return eph ? { eph } : {};
|
|
779
812
|
}
|
|
813
|
+
function feedGeoL5Block(view, b, onSbasMessage, onDfmcMessage) {
|
|
814
|
+
const g = readGeoMessage(view, b);
|
|
815
|
+
if (!g) return {};
|
|
816
|
+
if (!sbasCrcOk(g.msg)) return { badCrc: true };
|
|
817
|
+
if (isSbasL1Preamble(g.msg)) {
|
|
818
|
+
onSbasMessage?.(g.msg, g.prn, g.wnc, g.towSec);
|
|
819
|
+
const eph = decodeSbasGeoNav(g.msg, g.prn, g.wnc, g.towSec);
|
|
820
|
+
return eph ? { kind: "l1", eph } : { kind: "l1" };
|
|
821
|
+
}
|
|
822
|
+
const dfmcType = sbasL5MessageType(g.msg);
|
|
823
|
+
onDfmcMessage?.(g.msg, g.prn, g.wnc, g.towSec, dfmcType);
|
|
824
|
+
return { kind: "l5", dfmcType };
|
|
825
|
+
}
|
|
780
826
|
function parseSbfGeoNav(data, opts = {}) {
|
|
781
827
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
782
828
|
const ephemerides = [];
|
|
@@ -799,6 +845,47 @@ function parseSbfGeoNav(data, opts = {}) {
|
|
|
799
845
|
});
|
|
800
846
|
return { ephemerides, badCrc, messages };
|
|
801
847
|
}
|
|
848
|
+
function parseSbfGeoL5(data, opts = {}) {
|
|
849
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
850
|
+
const ephemerides = [];
|
|
851
|
+
const seen = /* @__PURE__ */ new Set();
|
|
852
|
+
const byType = {};
|
|
853
|
+
const dfmcPrns = /* @__PURE__ */ new Set();
|
|
854
|
+
let legacyMessages = 0;
|
|
855
|
+
let dfmcMessages = 0;
|
|
856
|
+
let badCrc = 0;
|
|
857
|
+
let messages = 0;
|
|
858
|
+
scanSbfFrames(data, view, (id, b, len) => {
|
|
859
|
+
if (id !== 4021 || len < 52) return;
|
|
860
|
+
messages++;
|
|
861
|
+
const r = feedGeoL5Block(view, b, opts.onSbasMessage, opts.onDfmcMessage);
|
|
862
|
+
if (r.badCrc) {
|
|
863
|
+
badCrc++;
|
|
864
|
+
} else if (r.kind === "l1") {
|
|
865
|
+
legacyMessages++;
|
|
866
|
+
if (r.eph) {
|
|
867
|
+
const key = `${r.eph.prn}|${r.eph.tocDate.getTime()}`;
|
|
868
|
+
if (!seen.has(key)) {
|
|
869
|
+
seen.add(key);
|
|
870
|
+
ephemerides.push(r.eph);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
} else if (r.kind === "l5" && r.dfmcType !== void 0) {
|
|
874
|
+
dfmcMessages++;
|
|
875
|
+
byType[r.dfmcType] = (byType[r.dfmcType] ?? 0) + 1;
|
|
876
|
+
const prn = view.getUint8(b + 14);
|
|
877
|
+
const s = svidToPrn(prn);
|
|
878
|
+
if (s) dfmcPrns.add(s);
|
|
879
|
+
}
|
|
880
|
+
});
|
|
881
|
+
return {
|
|
882
|
+
ephemerides,
|
|
883
|
+
legacyMessages,
|
|
884
|
+
dfmc: { byType, prns: [...dfmcPrns].sort(), messages: dfmcMessages },
|
|
885
|
+
badCrc,
|
|
886
|
+
messages
|
|
887
|
+
};
|
|
888
|
+
}
|
|
802
889
|
|
|
803
890
|
// src/sbf/navigation.ts
|
|
804
891
|
var F4_DNU4 = -2e10;
|
|
@@ -821,8 +908,11 @@ function decodeSbfNavigation(data, opts = {}) {
|
|
|
821
908
|
gloRaw: 0,
|
|
822
909
|
bdsRaw: 0,
|
|
823
910
|
sbasRaw: 0,
|
|
911
|
+
sbasL5Raw: 0,
|
|
824
912
|
badFrames: 0
|
|
825
913
|
};
|
|
914
|
+
const dfmcByType = {};
|
|
915
|
+
const dfmcPrns = /* @__PURE__ */ new Set();
|
|
826
916
|
const cnavAsm = newCnavAssemblers();
|
|
827
917
|
const galAsm = newGalAssemblers();
|
|
828
918
|
const gloAsm = new GloStringAssembler();
|
|
@@ -932,6 +1022,25 @@ function decodeSbfNavigation(data, opts = {}) {
|
|
|
932
1022
|
else if (r.badCrc) counts.badFrames++;
|
|
933
1023
|
return;
|
|
934
1024
|
}
|
|
1025
|
+
case 4021: {
|
|
1026
|
+
if (len < 52) return;
|
|
1027
|
+
counts.sbasL5Raw++;
|
|
1028
|
+
const r = feedGeoL5Block(
|
|
1029
|
+
view,
|
|
1030
|
+
b,
|
|
1031
|
+
opts.onSbasMessage,
|
|
1032
|
+
opts.onDfmcMessage
|
|
1033
|
+
);
|
|
1034
|
+
if (r.badCrc) counts.badFrames++;
|
|
1035
|
+
else if (r.kind === "l1") {
|
|
1036
|
+
if (r.eph) addEph(r.eph);
|
|
1037
|
+
} else if (r.kind === "l5" && r.dfmcType !== void 0) {
|
|
1038
|
+
dfmcByType[r.dfmcType] = (dfmcByType[r.dfmcType] ?? 0) + 1;
|
|
1039
|
+
const s = svidToPrn(view.getUint8(b + 14));
|
|
1040
|
+
if (s) dfmcPrns.add(s);
|
|
1041
|
+
}
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
935
1044
|
/* ---- iono / UTC ---- */
|
|
936
1045
|
case 5893:
|
|
937
1046
|
// GPSIon
|
|
@@ -956,7 +1065,12 @@ function decodeSbfNavigation(data, opts = {}) {
|
|
|
956
1065
|
return;
|
|
957
1066
|
}
|
|
958
1067
|
});
|
|
959
|
-
|
|
1068
|
+
const dfmc = {
|
|
1069
|
+
byType: dfmcByType,
|
|
1070
|
+
prns: [...dfmcPrns].sort(),
|
|
1071
|
+
messages: Object.values(dfmcByType).reduce((a, v) => a + v, 0)
|
|
1072
|
+
};
|
|
1073
|
+
return { ephemerides, cnav, ionoCorrections, leapSeconds, dfmc, counts };
|
|
960
1074
|
}
|
|
961
1075
|
|
|
962
1076
|
// src/navbits/rs255.ts
|
|
@@ -2163,8 +2277,16 @@ export {
|
|
|
2163
2277
|
parseSbfGalNav,
|
|
2164
2278
|
parseSbfBdsNav,
|
|
2165
2279
|
parseSbfGloNav,
|
|
2280
|
+
SBAS_L5_PREAMBLE_UW,
|
|
2281
|
+
isSbasL1Preamble,
|
|
2282
|
+
sbasL5MessageType,
|
|
2283
|
+
SBAS_L5_MT_NAMES,
|
|
2284
|
+
sbasL5MessageName,
|
|
2285
|
+
isSbasL5Correction,
|
|
2166
2286
|
feedGeoBlock,
|
|
2287
|
+
feedGeoL5Block,
|
|
2167
2288
|
parseSbfGeoNav,
|
|
2289
|
+
parseSbfGeoL5,
|
|
2168
2290
|
decodeSbfNavigation,
|
|
2169
2291
|
parseSbfHas,
|
|
2170
2292
|
parseSbfMeas
|
package/dist/index.cjs
CHANGED
|
@@ -84,6 +84,8 @@ __export(src_exports, {
|
|
|
84
84
|
RTCM3_MESSAGE_NAMES: () => RTCM3_MESSAGE_NAMES,
|
|
85
85
|
Rtcm3Decoder: () => Rtcm3Decoder,
|
|
86
86
|
RtkFloatEngine: () => RtkFloatEngine,
|
|
87
|
+
SBAS_L5_MT_NAMES: () => SBAS_L5_MT_NAMES,
|
|
88
|
+
SBAS_L5_PREAMBLE_UW: () => SBAS_L5_PREAMBLE_UW,
|
|
87
89
|
SECONDS_IN_DAY: () => SECONDS_IN_DAY,
|
|
88
90
|
SECONDS_IN_HOUR: () => SECONDS_IN_HOUR,
|
|
89
91
|
SECONDS_IN_MINUTE: () => SECONDS_IN_MINUTE,
|
|
@@ -157,6 +159,7 @@ __export(src_exports, {
|
|
|
157
159
|
euclidean3D: () => euclidean3D,
|
|
158
160
|
extractWidelaneArcs: () => extractWidelaneArcs,
|
|
159
161
|
feedGeoBlock: () => feedGeoBlock,
|
|
162
|
+
feedGeoL5Block: () => feedGeoL5Block,
|
|
160
163
|
fetchSourcetable: () => fetchSourcetable,
|
|
161
164
|
findSatBias: () => findSatBias,
|
|
162
165
|
fixPppPosition: () => fixPppPosition,
|
|
@@ -233,6 +236,8 @@ __export(src_exports, {
|
|
|
233
236
|
hdrLine: () => hdrLine,
|
|
234
237
|
horizonDistance: () => horizonDistance,
|
|
235
238
|
ionoFree: () => ionoFree,
|
|
239
|
+
isSbasL1Preamble: () => isSbasL1Preamble,
|
|
240
|
+
isSbasL5Correction: () => isSbasL5Correction,
|
|
236
241
|
keplerPosition: () => keplerPosition,
|
|
237
242
|
klobucharDelay: () => klobucharDelay,
|
|
238
243
|
lambdaReduction: () => lambdaReduction,
|
|
@@ -263,6 +268,7 @@ __export(src_exports, {
|
|
|
263
268
|
parseSbfBdsNav: () => parseSbfBdsNav,
|
|
264
269
|
parseSbfCnav: () => parseSbfCnav,
|
|
265
270
|
parseSbfGalNav: () => parseSbfGalNav,
|
|
271
|
+
parseSbfGeoL5: () => parseSbfGeoL5,
|
|
266
272
|
parseSbfGeoNav: () => parseSbfGeoNav,
|
|
267
273
|
parseSbfGloNav: () => parseSbfGloNav,
|
|
268
274
|
parseSbfGpsNav: () => parseSbfGpsNav,
|
|
@@ -297,6 +303,8 @@ __export(src_exports, {
|
|
|
297
303
|
rhumbLine: () => rhumbLine,
|
|
298
304
|
rtcm3Constellation: () => rtcm3Constellation,
|
|
299
305
|
satClockCorrection: () => satClockCorrection,
|
|
306
|
+
sbasL5MessageName: () => sbasL5MessageName,
|
|
307
|
+
sbasL5MessageType: () => sbasL5MessageType,
|
|
300
308
|
sbasProtectionLevels: () => sbasProtectionLevels,
|
|
301
309
|
sbfCrc16: () => crc16,
|
|
302
310
|
scanSbfFrames: () => scanSbfFrames,
|
|
@@ -7833,13 +7841,42 @@ function parseSbfGloNav(data) {
|
|
|
7833
7841
|
return { ephemerides, badCrc, messages };
|
|
7834
7842
|
}
|
|
7835
7843
|
|
|
7844
|
+
// src/navbits/sbas-l5.ts
|
|
7845
|
+
var SBAS_L5_PREAMBLE_UW = 6056250;
|
|
7846
|
+
function isSbasL1Preamble(msg) {
|
|
7847
|
+
return msg[0] === 83 || msg[0] === 154 || msg[0] === 198;
|
|
7848
|
+
}
|
|
7849
|
+
function sbasL5MessageType(msg) {
|
|
7850
|
+
return getBitU(msg, 4, 6);
|
|
7851
|
+
}
|
|
7852
|
+
var SBAS_L5_MT_NAMES = {
|
|
7853
|
+
0: "Do Not Use (test)",
|
|
7854
|
+
31: "SBAS satellite mask",
|
|
7855
|
+
32: "Satellite clock-ephemeris corrections + covariance",
|
|
7856
|
+
34: "Integrity (DFREI/DFRECI)",
|
|
7857
|
+
35: "Integrity (DFREI/DFRECI)",
|
|
7858
|
+
36: "Integrity (DFREI/DFRECI)",
|
|
7859
|
+
37: "Degradation parameters + DFREI scale table",
|
|
7860
|
+
39: "SBAS satellite clock/ephemeris/covariance-1",
|
|
7861
|
+
40: "SBAS satellite clock/ephemeris/covariance-2",
|
|
7862
|
+
42: "SNT-to-UTC offset",
|
|
7863
|
+
47: "SBAS satellite almanacs",
|
|
7864
|
+
62: "Reserved",
|
|
7865
|
+
63: "Null message"
|
|
7866
|
+
};
|
|
7867
|
+
function sbasL5MessageName(type) {
|
|
7868
|
+
return SBAS_L5_MT_NAMES[type] ?? (type >= 1 && type <= 61 ? "Spare" : `Type ${type}`);
|
|
7869
|
+
}
|
|
7870
|
+
function isSbasL5Correction(type) {
|
|
7871
|
+
return type === 31 || type === 32 || type >= 34 && type <= 37 || type === 39 || type === 40 || type === 42 || type === 47;
|
|
7872
|
+
}
|
|
7873
|
+
|
|
7836
7874
|
// src/sbf/rawnav-sbas.ts
|
|
7837
|
-
function
|
|
7875
|
+
function readGeoMessage(view, b) {
|
|
7838
7876
|
const tow = view.getUint32(b + 8, true);
|
|
7839
7877
|
const wnc = view.getUint16(b + 12, true);
|
|
7840
|
-
const
|
|
7841
|
-
|
|
7842
|
-
if (!prnStr || prnStr[0] !== "S") return {};
|
|
7878
|
+
const prnStr = svidToPrn(view.getUint8(b + 14));
|
|
7879
|
+
if (!prnStr || prnStr[0] !== "S") return null;
|
|
7843
7880
|
const msg = new Uint8Array(32);
|
|
7844
7881
|
for (let k = 0; k < 8; k++) {
|
|
7845
7882
|
const w = view.getUint32(b + 20 + 4 * k, true);
|
|
@@ -7848,12 +7885,29 @@ function feedGeoBlock(view, b, onSbasMessage) {
|
|
|
7848
7885
|
msg[4 * k + 2] = w >>> 8 & 255;
|
|
7849
7886
|
msg[4 * k + 3] = w & 255;
|
|
7850
7887
|
}
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
const
|
|
7888
|
+
return { msg, prn: Number(prnStr.slice(1)) + 100, wnc, towSec: tow / 1e3 };
|
|
7889
|
+
}
|
|
7890
|
+
function feedGeoBlock(view, b, onSbasMessage) {
|
|
7891
|
+
const g = readGeoMessage(view, b);
|
|
7892
|
+
if (!g) return {};
|
|
7893
|
+
if (!sbasCrcOk(g.msg)) return { badCrc: true };
|
|
7894
|
+
onSbasMessage?.(g.msg, g.prn, g.wnc, g.towSec);
|
|
7895
|
+
const eph = decodeSbasGeoNav(g.msg, g.prn, g.wnc, g.towSec);
|
|
7855
7896
|
return eph ? { eph } : {};
|
|
7856
7897
|
}
|
|
7898
|
+
function feedGeoL5Block(view, b, onSbasMessage, onDfmcMessage) {
|
|
7899
|
+
const g = readGeoMessage(view, b);
|
|
7900
|
+
if (!g) return {};
|
|
7901
|
+
if (!sbasCrcOk(g.msg)) return { badCrc: true };
|
|
7902
|
+
if (isSbasL1Preamble(g.msg)) {
|
|
7903
|
+
onSbasMessage?.(g.msg, g.prn, g.wnc, g.towSec);
|
|
7904
|
+
const eph = decodeSbasGeoNav(g.msg, g.prn, g.wnc, g.towSec);
|
|
7905
|
+
return eph ? { kind: "l1", eph } : { kind: "l1" };
|
|
7906
|
+
}
|
|
7907
|
+
const dfmcType = sbasL5MessageType(g.msg);
|
|
7908
|
+
onDfmcMessage?.(g.msg, g.prn, g.wnc, g.towSec, dfmcType);
|
|
7909
|
+
return { kind: "l5", dfmcType };
|
|
7910
|
+
}
|
|
7857
7911
|
function parseSbfGeoNav(data, opts = {}) {
|
|
7858
7912
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
7859
7913
|
const ephemerides = [];
|
|
@@ -7876,6 +7930,47 @@ function parseSbfGeoNav(data, opts = {}) {
|
|
|
7876
7930
|
});
|
|
7877
7931
|
return { ephemerides, badCrc, messages };
|
|
7878
7932
|
}
|
|
7933
|
+
function parseSbfGeoL5(data, opts = {}) {
|
|
7934
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
7935
|
+
const ephemerides = [];
|
|
7936
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7937
|
+
const byType = {};
|
|
7938
|
+
const dfmcPrns = /* @__PURE__ */ new Set();
|
|
7939
|
+
let legacyMessages = 0;
|
|
7940
|
+
let dfmcMessages = 0;
|
|
7941
|
+
let badCrc = 0;
|
|
7942
|
+
let messages = 0;
|
|
7943
|
+
scanSbfFrames(data, view, (id, b, len) => {
|
|
7944
|
+
if (id !== 4021 || len < 52) return;
|
|
7945
|
+
messages++;
|
|
7946
|
+
const r = feedGeoL5Block(view, b, opts.onSbasMessage, opts.onDfmcMessage);
|
|
7947
|
+
if (r.badCrc) {
|
|
7948
|
+
badCrc++;
|
|
7949
|
+
} else if (r.kind === "l1") {
|
|
7950
|
+
legacyMessages++;
|
|
7951
|
+
if (r.eph) {
|
|
7952
|
+
const key = `${r.eph.prn}|${r.eph.tocDate.getTime()}`;
|
|
7953
|
+
if (!seen.has(key)) {
|
|
7954
|
+
seen.add(key);
|
|
7955
|
+
ephemerides.push(r.eph);
|
|
7956
|
+
}
|
|
7957
|
+
}
|
|
7958
|
+
} else if (r.kind === "l5" && r.dfmcType !== void 0) {
|
|
7959
|
+
dfmcMessages++;
|
|
7960
|
+
byType[r.dfmcType] = (byType[r.dfmcType] ?? 0) + 1;
|
|
7961
|
+
const prn = view.getUint8(b + 14);
|
|
7962
|
+
const s = svidToPrn(prn);
|
|
7963
|
+
if (s) dfmcPrns.add(s);
|
|
7964
|
+
}
|
|
7965
|
+
});
|
|
7966
|
+
return {
|
|
7967
|
+
ephemerides,
|
|
7968
|
+
legacyMessages,
|
|
7969
|
+
dfmc: { byType, prns: [...dfmcPrns].sort(), messages: dfmcMessages },
|
|
7970
|
+
badCrc,
|
|
7971
|
+
messages
|
|
7972
|
+
};
|
|
7973
|
+
}
|
|
7879
7974
|
|
|
7880
7975
|
// src/sbf/navigation.ts
|
|
7881
7976
|
var F4_DNU4 = -2e10;
|
|
@@ -7898,8 +7993,11 @@ function decodeSbfNavigation(data, opts = {}) {
|
|
|
7898
7993
|
gloRaw: 0,
|
|
7899
7994
|
bdsRaw: 0,
|
|
7900
7995
|
sbasRaw: 0,
|
|
7996
|
+
sbasL5Raw: 0,
|
|
7901
7997
|
badFrames: 0
|
|
7902
7998
|
};
|
|
7999
|
+
const dfmcByType = {};
|
|
8000
|
+
const dfmcPrns = /* @__PURE__ */ new Set();
|
|
7903
8001
|
const cnavAsm = newCnavAssemblers();
|
|
7904
8002
|
const galAsm = newGalAssemblers();
|
|
7905
8003
|
const gloAsm = new GloStringAssembler();
|
|
@@ -8009,6 +8107,25 @@ function decodeSbfNavigation(data, opts = {}) {
|
|
|
8009
8107
|
else if (r.badCrc) counts.badFrames++;
|
|
8010
8108
|
return;
|
|
8011
8109
|
}
|
|
8110
|
+
case 4021: {
|
|
8111
|
+
if (len < 52) return;
|
|
8112
|
+
counts.sbasL5Raw++;
|
|
8113
|
+
const r = feedGeoL5Block(
|
|
8114
|
+
view,
|
|
8115
|
+
b,
|
|
8116
|
+
opts.onSbasMessage,
|
|
8117
|
+
opts.onDfmcMessage
|
|
8118
|
+
);
|
|
8119
|
+
if (r.badCrc) counts.badFrames++;
|
|
8120
|
+
else if (r.kind === "l1") {
|
|
8121
|
+
if (r.eph) addEph(r.eph);
|
|
8122
|
+
} else if (r.kind === "l5" && r.dfmcType !== void 0) {
|
|
8123
|
+
dfmcByType[r.dfmcType] = (dfmcByType[r.dfmcType] ?? 0) + 1;
|
|
8124
|
+
const s = svidToPrn(view.getUint8(b + 14));
|
|
8125
|
+
if (s) dfmcPrns.add(s);
|
|
8126
|
+
}
|
|
8127
|
+
return;
|
|
8128
|
+
}
|
|
8012
8129
|
/* ---- iono / UTC ---- */
|
|
8013
8130
|
case 5893:
|
|
8014
8131
|
// GPSIon
|
|
@@ -8033,7 +8150,12 @@ function decodeSbfNavigation(data, opts = {}) {
|
|
|
8033
8150
|
return;
|
|
8034
8151
|
}
|
|
8035
8152
|
});
|
|
8036
|
-
|
|
8153
|
+
const dfmc = {
|
|
8154
|
+
byType: dfmcByType,
|
|
8155
|
+
prns: [...dfmcPrns].sort(),
|
|
8156
|
+
messages: Object.values(dfmcByType).reduce((a, v) => a + v, 0)
|
|
8157
|
+
};
|
|
8158
|
+
return { ephemerides, cnav, ionoCorrections, leapSeconds, dfmc, counts };
|
|
8037
8159
|
}
|
|
8038
8160
|
|
|
8039
8161
|
// src/navbits/rs255.ts
|
|
@@ -13637,6 +13759,36 @@ var SbasProcessor = class {
|
|
|
13637
13759
|
}
|
|
13638
13760
|
return n;
|
|
13639
13761
|
}
|
|
13762
|
+
/**
|
|
13763
|
+
* Correction-coverage census at a GPS week/time — a diagnostic funnel over
|
|
13764
|
+
* the current state, explaining how many masked satellites are actually
|
|
13765
|
+
* correctable. Each stage subsumes the requirement of the previous one for a
|
|
13766
|
+
* full range/clock correction: a satellite is `corrected` only when it has
|
|
13767
|
+
* both a fresh fast correction and (for non-SBAS satellites) a fresh
|
|
13768
|
+
* long-term correction (exactly {@link satCorrection}'s gate). `ionoGrid` is
|
|
13769
|
+
* the total number of valid grid points — the additional requirement for the
|
|
13770
|
+
* *iono*-corrected subset a solver forms per pierce point.
|
|
13771
|
+
*
|
|
13772
|
+
* Use it to tell "no corrections applied" (mask empty / products stale) apart
|
|
13773
|
+
* from "corrections applied but the pierce points aren't grid-covered yet".
|
|
13774
|
+
*/
|
|
13775
|
+
coverage(week, tow) {
|
|
13776
|
+
const now = gpsSeconds(week, tow);
|
|
13777
|
+
let masked = 0;
|
|
13778
|
+
let fast = 0;
|
|
13779
|
+
let long = 0;
|
|
13780
|
+
let corrected = 0;
|
|
13781
|
+
for (const s of this.sats) {
|
|
13782
|
+
if (!s.prn) continue;
|
|
13783
|
+
masked++;
|
|
13784
|
+
if (s.fcorr && s.fcorr.t0s !== 0 && s.fcorr.udre < 15 && Math.abs(now - s.fcorr.t0s + this.tlat) <= MAXSBSAGEF)
|
|
13785
|
+
fast++;
|
|
13786
|
+
if (s.prn[0] === "S" || s.lcorr && s.lcorr.t0s !== 0 && Math.abs(now - s.lcorr.t0s) <= MAXSBSAGEL)
|
|
13787
|
+
long++;
|
|
13788
|
+
if (this.satCorrection(s.prn, week, tow)) corrected++;
|
|
13789
|
+
}
|
|
13790
|
+
return { masked, fast, long, corrected, ionoGrid: this.ionoGridPoints() };
|
|
13791
|
+
}
|
|
13640
13792
|
/**
|
|
13641
13793
|
* Satellite range/clock correction for a PRN at a GPS week/tow, or null if
|
|
13642
13794
|
* no valid (unexpired) long-term + fast correction is available. Add `dPos`
|
|
@@ -17751,6 +17903,8 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
17751
17903
|
RTCM3_MESSAGE_NAMES,
|
|
17752
17904
|
Rtcm3Decoder,
|
|
17753
17905
|
RtkFloatEngine,
|
|
17906
|
+
SBAS_L5_MT_NAMES,
|
|
17907
|
+
SBAS_L5_PREAMBLE_UW,
|
|
17754
17908
|
SECONDS_IN_DAY,
|
|
17755
17909
|
SECONDS_IN_HOUR,
|
|
17756
17910
|
SECONDS_IN_MINUTE,
|
|
@@ -17824,6 +17978,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
17824
17978
|
euclidean3D,
|
|
17825
17979
|
extractWidelaneArcs,
|
|
17826
17980
|
feedGeoBlock,
|
|
17981
|
+
feedGeoL5Block,
|
|
17827
17982
|
fetchSourcetable,
|
|
17828
17983
|
findSatBias,
|
|
17829
17984
|
fixPppPosition,
|
|
@@ -17900,6 +18055,8 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
17900
18055
|
hdrLine,
|
|
17901
18056
|
horizonDistance,
|
|
17902
18057
|
ionoFree,
|
|
18058
|
+
isSbasL1Preamble,
|
|
18059
|
+
isSbasL5Correction,
|
|
17903
18060
|
keplerPosition,
|
|
17904
18061
|
klobucharDelay,
|
|
17905
18062
|
lambdaReduction,
|
|
@@ -17930,6 +18087,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
17930
18087
|
parseSbfBdsNav,
|
|
17931
18088
|
parseSbfCnav,
|
|
17932
18089
|
parseSbfGalNav,
|
|
18090
|
+
parseSbfGeoL5,
|
|
17933
18091
|
parseSbfGeoNav,
|
|
17934
18092
|
parseSbfGloNav,
|
|
17935
18093
|
parseSbfGpsNav,
|
|
@@ -17964,6 +18122,8 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
17964
18122
|
rhumbLine,
|
|
17965
18123
|
rtcm3Constellation,
|
|
17966
18124
|
satClockCorrection,
|
|
18125
|
+
sbasL5MessageName,
|
|
18126
|
+
sbasL5MessageType,
|
|
17967
18127
|
sbasProtectionLevels,
|
|
17968
18128
|
sbfCrc16,
|
|
17969
18129
|
scanSbfFrames,
|
package/dist/index.d.cts
CHANGED
|
@@ -12,7 +12,7 @@ export { C as ClkFile, I as IonexGrid, S as Sp3File, a as Sp3Sample, c as clkBia
|
|
|
12
12
|
export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.cjs';
|
|
13
13
|
export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.cjs';
|
|
14
14
|
export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxPvtResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxPvt, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.cjs';
|
|
15
|
-
export { HasMessage, SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGeoNavResult, SbfGloNavResult, SbfGpsNavResult, SbfHasMessage, SbfHasResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfNavCounts, SbfNavigation, SbfParseResult, SbfPvt, SbfPvtResult, SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, sbfCrc16, scanSbfFrames } from './sbf.cjs';
|
|
15
|
+
export { DfmcCensus, DfmcMessageCb, GeoL5Result, HasMessage, SBAS_L5_MT_NAMES, SBAS_L5_PREAMBLE_UW, SbasMessageCb, SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGeoL5Result, SbfGeoNavResult, SbfGloNavResult, SbfGpsNavResult, SbfHasMessage, SbfHasResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfNavCounts, SbfNavigation, SbfParseResult, SbfPvt, SbfPvtResult, SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, feedGeoL5Block, isSbasL1Preamble, isSbasL5Correction, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoL5, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, sbasL5MessageName, sbasL5MessageType, sbfCrc16, scanSbfFrames } from './sbf.cjs';
|
|
16
16
|
export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, NovatelPvtResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelPvt, parseNovatelRange } from './novatel.cjs';
|
|
17
17
|
export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, TrimbleParseResult, parseTrimble, parseTrimbleNav, trimbleFrames } from './trimble.cjs';
|
|
18
18
|
export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export { C as ClkFile, I as IonexGrid, S as Sp3File, a as Sp3Sample, c as clkBia
|
|
|
12
12
|
export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.js';
|
|
13
13
|
export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.js';
|
|
14
14
|
export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxPvtResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxPvt, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.js';
|
|
15
|
-
export { HasMessage, SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGeoNavResult, SbfGloNavResult, SbfGpsNavResult, SbfHasMessage, SbfHasResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfNavCounts, SbfNavigation, SbfParseResult, SbfPvt, SbfPvtResult, SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, sbfCrc16, scanSbfFrames } from './sbf.js';
|
|
15
|
+
export { DfmcCensus, DfmcMessageCb, GeoL5Result, HasMessage, SBAS_L5_MT_NAMES, SBAS_L5_PREAMBLE_UW, SbasMessageCb, SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGeoL5Result, SbfGeoNavResult, SbfGloNavResult, SbfGpsNavResult, SbfHasMessage, SbfHasResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfNavCounts, SbfNavigation, SbfParseResult, SbfPvt, SbfPvtResult, SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, feedGeoL5Block, isSbasL1Preamble, isSbasL5Correction, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoL5, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, sbasL5MessageName, sbasL5MessageType, sbfCrc16, scanSbfFrames } from './sbf.js';
|
|
16
16
|
export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, NovatelPvtResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelPvt, parseNovatelRange } from './novatel.js';
|
|
17
17
|
export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, TrimbleParseResult, parseTrimble, parseTrimbleNav, trimbleFrames } from './trimble.js';
|
|
18
18
|
export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.js';
|
package/dist/index.js
CHANGED
|
@@ -53,13 +53,19 @@ import {
|
|
|
53
53
|
ubxFrames
|
|
54
54
|
} from "./chunk-MRC6LIPM.js";
|
|
55
55
|
import {
|
|
56
|
+
SBAS_L5_MT_NAMES,
|
|
57
|
+
SBAS_L5_PREAMBLE_UW,
|
|
56
58
|
crc16,
|
|
57
59
|
decodeSbfNavigation,
|
|
58
60
|
feedGeoBlock,
|
|
61
|
+
feedGeoL5Block,
|
|
62
|
+
isSbasL1Preamble,
|
|
63
|
+
isSbasL5Correction,
|
|
59
64
|
parseSbfAlmanac,
|
|
60
65
|
parseSbfBdsNav,
|
|
61
66
|
parseSbfCnav,
|
|
62
67
|
parseSbfGalNav,
|
|
68
|
+
parseSbfGeoL5,
|
|
63
69
|
parseSbfGeoNav,
|
|
64
70
|
parseSbfGloNav,
|
|
65
71
|
parseSbfGpsNav,
|
|
@@ -69,8 +75,10 @@ import {
|
|
|
69
75
|
parseSbfNav,
|
|
70
76
|
parseSbfPvt,
|
|
71
77
|
parseSbfReceiverSetup,
|
|
78
|
+
sbasL5MessageName,
|
|
79
|
+
sbasL5MessageType,
|
|
72
80
|
scanSbfFrames
|
|
73
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-UHLUAU6H.js";
|
|
74
82
|
import "./chunk-FA2UTLEQ.js";
|
|
75
83
|
import {
|
|
76
84
|
OEM4_HLEN,
|
|
@@ -168,7 +176,7 @@ import {
|
|
|
168
176
|
sunEcef,
|
|
169
177
|
toRtkEpoch,
|
|
170
178
|
wlWavelength
|
|
171
|
-
} from "./chunk-
|
|
179
|
+
} from "./chunk-BU6YC6VK.js";
|
|
172
180
|
import "./chunk-WQX354KD.js";
|
|
173
181
|
import {
|
|
174
182
|
almanacEpochMs,
|
|
@@ -424,6 +432,8 @@ export {
|
|
|
424
432
|
RTCM3_MESSAGE_NAMES,
|
|
425
433
|
Rtcm3Decoder,
|
|
426
434
|
RtkFloatEngine,
|
|
435
|
+
SBAS_L5_MT_NAMES,
|
|
436
|
+
SBAS_L5_PREAMBLE_UW,
|
|
427
437
|
SECONDS_IN_DAY,
|
|
428
438
|
SECONDS_IN_HOUR,
|
|
429
439
|
SECONDS_IN_MINUTE,
|
|
@@ -497,6 +507,7 @@ export {
|
|
|
497
507
|
euclidean3D,
|
|
498
508
|
extractWidelaneArcs,
|
|
499
509
|
feedGeoBlock,
|
|
510
|
+
feedGeoL5Block,
|
|
500
511
|
fetchSourcetable,
|
|
501
512
|
findSatBias,
|
|
502
513
|
fixPppPosition,
|
|
@@ -573,6 +584,8 @@ export {
|
|
|
573
584
|
hdrLine,
|
|
574
585
|
horizonDistance,
|
|
575
586
|
ionoFree,
|
|
587
|
+
isSbasL1Preamble,
|
|
588
|
+
isSbasL5Correction,
|
|
576
589
|
keplerPosition,
|
|
577
590
|
klobucharDelay,
|
|
578
591
|
lambdaReduction,
|
|
@@ -603,6 +616,7 @@ export {
|
|
|
603
616
|
parseSbfBdsNav,
|
|
604
617
|
parseSbfCnav,
|
|
605
618
|
parseSbfGalNav,
|
|
619
|
+
parseSbfGeoL5,
|
|
606
620
|
parseSbfGeoNav,
|
|
607
621
|
parseSbfGloNav,
|
|
608
622
|
parseSbfGpsNav,
|
|
@@ -637,6 +651,8 @@ export {
|
|
|
637
651
|
rhumbLine,
|
|
638
652
|
rtcm3Constellation,
|
|
639
653
|
satClockCorrection,
|
|
654
|
+
sbasL5MessageName,
|
|
655
|
+
sbasL5MessageType,
|
|
640
656
|
sbasProtectionLevels,
|
|
641
657
|
crc16 as sbfCrc16,
|
|
642
658
|
scanSbfFrames,
|
package/dist/positioning.cjs
CHANGED
|
@@ -2025,6 +2025,36 @@ var SbasProcessor = class {
|
|
|
2025
2025
|
}
|
|
2026
2026
|
return n;
|
|
2027
2027
|
}
|
|
2028
|
+
/**
|
|
2029
|
+
* Correction-coverage census at a GPS week/time — a diagnostic funnel over
|
|
2030
|
+
* the current state, explaining how many masked satellites are actually
|
|
2031
|
+
* correctable. Each stage subsumes the requirement of the previous one for a
|
|
2032
|
+
* full range/clock correction: a satellite is `corrected` only when it has
|
|
2033
|
+
* both a fresh fast correction and (for non-SBAS satellites) a fresh
|
|
2034
|
+
* long-term correction (exactly {@link satCorrection}'s gate). `ionoGrid` is
|
|
2035
|
+
* the total number of valid grid points — the additional requirement for the
|
|
2036
|
+
* *iono*-corrected subset a solver forms per pierce point.
|
|
2037
|
+
*
|
|
2038
|
+
* Use it to tell "no corrections applied" (mask empty / products stale) apart
|
|
2039
|
+
* from "corrections applied but the pierce points aren't grid-covered yet".
|
|
2040
|
+
*/
|
|
2041
|
+
coverage(week, tow) {
|
|
2042
|
+
const now = gpsSeconds(week, tow);
|
|
2043
|
+
let masked = 0;
|
|
2044
|
+
let fast = 0;
|
|
2045
|
+
let long = 0;
|
|
2046
|
+
let corrected = 0;
|
|
2047
|
+
for (const s of this.sats) {
|
|
2048
|
+
if (!s.prn) continue;
|
|
2049
|
+
masked++;
|
|
2050
|
+
if (s.fcorr && s.fcorr.t0s !== 0 && s.fcorr.udre < 15 && Math.abs(now - s.fcorr.t0s + this.tlat) <= MAXSBSAGEF)
|
|
2051
|
+
fast++;
|
|
2052
|
+
if (s.prn[0] === "S" || s.lcorr && s.lcorr.t0s !== 0 && Math.abs(now - s.lcorr.t0s) <= MAXSBSAGEL)
|
|
2053
|
+
long++;
|
|
2054
|
+
if (this.satCorrection(s.prn, week, tow)) corrected++;
|
|
2055
|
+
}
|
|
2056
|
+
return { masked, fast, long, corrected, ionoGrid: this.ionoGridPoints() };
|
|
2057
|
+
}
|
|
2028
2058
|
/**
|
|
2029
2059
|
* Satellite range/clock correction for a PRN at a GPS week/tow, or null if
|
|
2030
2060
|
* no valid (unexpired) long-term + fast correction is available. Add `dPos`
|