gnss-js 1.24.0 → 1.26.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/binex.cjs +799 -0
- package/dist/binex.d.cts +189 -0
- package/dist/binex.d.ts +189 -0
- package/dist/binex.js +19 -0
- package/dist/{chunk-T2ZMNRCY.js → chunk-4XGKCVE3.js} +73 -10
- package/dist/{chunk-VTX3VCL4.js → chunk-5AUK42AL.js} +4 -2
- package/dist/{chunk-WZDFZ76K.js → chunk-726LQBGM.js} +8 -148
- package/dist/{chunk-PZNVFCKJ.js → chunk-AFEDNWXI.js} +5 -3
- package/dist/chunk-CKRNXZHT.js +424 -0
- package/dist/{chunk-7RKLWE6R.js → chunk-F4CM6Q4F.js} +4 -2
- package/dist/{chunk-MCAVU3XL.js → chunk-FEOMYZEU.js} +5 -3
- package/dist/chunk-IQ5OIMQD.js +148 -0
- package/dist/chunk-OK4GGNOO.js +756 -0
- package/dist/{chunk-NOQAAUGY.js → chunk-WDUN4BWL.js} +4 -2
- package/dist/index.cjs +1273 -27
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +48 -17
- package/dist/ionex-DaW5x9nq.d.cts +23 -0
- package/dist/ionex-DaW5x9nq.d.ts +23 -0
- package/dist/novatel.js +3 -2
- package/dist/positioning.cjs +76 -10
- package/dist/positioning.d.cts +59 -3
- package/dist/positioning.d.ts +59 -3
- package/dist/positioning.js +7 -1
- package/dist/rinex.d.cts +2 -23
- package/dist/rinex.d.ts +2 -23
- package/dist/rinex.js +3 -2
- package/dist/sbf.js +4 -3
- package/dist/trimble.cjs +452 -0
- package/dist/trimble.d.cts +147 -0
- package/dist/trimble.d.ts +147 -0
- package/dist/trimble.js +10 -0
- package/dist/ubx.js +4 -3
- package/package.json +11 -1
package/dist/index.cjs
CHANGED
|
@@ -67,6 +67,7 @@ __export(src_exports, {
|
|
|
67
67
|
GLO_F2_BASE: () => GLO_F2_BASE,
|
|
68
68
|
GLO_F2_STEP: () => GLO_F2_STEP,
|
|
69
69
|
GLO_F3: () => GLO_F3,
|
|
70
|
+
IONO_L1_M_PER_TECU: () => IONO_L1_M_PER_TECU,
|
|
70
71
|
IonoAccumulator: () => IonoAccumulator,
|
|
71
72
|
MILLISECONDS_GPS_TAI: () => MILLISECONDS_GPS_TAI,
|
|
72
73
|
MILLISECONDS_IN_DAY: () => MILLISECONDS_IN_DAY,
|
|
@@ -110,6 +111,10 @@ __export(src_exports, {
|
|
|
110
111
|
analyzeQuality: () => analyzeQuality,
|
|
111
112
|
applyHelmert: () => applyHelmert,
|
|
112
113
|
applyIonoDcb: () => applyIonoDcb,
|
|
114
|
+
binexCrc16: () => binexCrc16,
|
|
115
|
+
binexCrc32: () => binexCrc32,
|
|
116
|
+
binexCsum8: () => binexCsum8,
|
|
117
|
+
binexRecords: () => binexRecords,
|
|
113
118
|
buildGloChannelMap: () => buildGloChannelMap,
|
|
114
119
|
buildObsIndices: () => buildObsIndices,
|
|
115
120
|
clampUnit: () => clampUnit,
|
|
@@ -130,6 +135,7 @@ __export(src_exports, {
|
|
|
130
135
|
crxDecompress: () => crxDecompress,
|
|
131
136
|
crxRepair: () => crxRepair,
|
|
132
137
|
dateToEpoch: () => dateToEpoch,
|
|
138
|
+
decodeBinexEph: () => decodeBinexEph,
|
|
133
139
|
decodeEphemeris: () => decodeEphemeris,
|
|
134
140
|
decodeMsmFull: () => decodeMsmFull,
|
|
135
141
|
deg2dms: () => deg2dms,
|
|
@@ -151,6 +157,7 @@ __export(src_exports, {
|
|
|
151
157
|
geodeticToUtm: () => geodeticToUtm,
|
|
152
158
|
getAer: () => getAer,
|
|
153
159
|
getBdsTime: () => getBdsTime,
|
|
160
|
+
getBnxi: () => getBnxi,
|
|
154
161
|
getDateFromBdsTime: () => getDateFromBdsTime,
|
|
155
162
|
getDateFromDayOfWeek: () => getDateFromDayOfWeek,
|
|
156
163
|
getDateFromDayOfYear: () => getDateFromDayOfYear,
|
|
@@ -202,6 +209,8 @@ __export(src_exports, {
|
|
|
202
209
|
getUtcDate: () => getUtcDate,
|
|
203
210
|
getWeekNumber: () => getWeekNumber,
|
|
204
211
|
getWeekOfYear: () => getWeekOfYear,
|
|
212
|
+
gimSlantIonoDelayL1: () => gimSlantIonoDelayL1,
|
|
213
|
+
gimVerticalTec: () => gimVerticalTec,
|
|
205
214
|
gloFreq: () => gloFreq,
|
|
206
215
|
glonassAlmanacEpochMs: () => glonassAlmanacEpochMs,
|
|
207
216
|
glonassAlmanacPosition: () => glonassAlmanacPosition,
|
|
@@ -222,6 +231,7 @@ __export(src_exports, {
|
|
|
222
231
|
padL: () => padL,
|
|
223
232
|
padR: () => padR,
|
|
224
233
|
parseAntex: () => parseAntex,
|
|
234
|
+
parseBinex: () => parseBinex,
|
|
225
235
|
parseCrxDataLine: () => parseCrxDataLine,
|
|
226
236
|
parseIonex: () => parseIonex,
|
|
227
237
|
parseNavFile: () => parseNavFile,
|
|
@@ -241,6 +251,8 @@ __export(src_exports, {
|
|
|
241
251
|
parseSinexBiasDcb: () => parseSinexBiasDcb,
|
|
242
252
|
parseSourcetable: () => parseSourcetable,
|
|
243
253
|
parseSp3: () => parseSp3,
|
|
254
|
+
parseTrimble: () => parseTrimble,
|
|
255
|
+
parseTrimbleNav: () => parseTrimbleNav,
|
|
244
256
|
parseUbxCnav: () => parseUbxCnav,
|
|
245
257
|
parseUbxIonoUtc: () => parseUbxIonoUtc,
|
|
246
258
|
parseUbxNav: () => parseUbxNav,
|
|
@@ -271,6 +283,7 @@ __export(src_exports, {
|
|
|
271
283
|
systemName: () => systemName,
|
|
272
284
|
toRtkEpoch: () => toRtkEpoch,
|
|
273
285
|
transformFrame: () => transformFrame,
|
|
286
|
+
trimbleFrames: () => trimbleFrames,
|
|
274
287
|
ubxFrames: () => ubxFrames,
|
|
275
288
|
updateStationMeta: () => updateStationMeta,
|
|
276
289
|
updateStreamStats: () => updateStreamStats,
|
|
@@ -6277,20 +6290,20 @@ var SIGNALS = {
|
|
|
6277
6290
|
// GLONASS L1OF, L2OF
|
|
6278
6291
|
};
|
|
6279
6292
|
function prnFor(gnssId, svId) {
|
|
6280
|
-
const
|
|
6293
|
+
const two7 = (n) => String(n).padStart(2, "0");
|
|
6281
6294
|
switch (gnssId) {
|
|
6282
6295
|
case 0:
|
|
6283
|
-
return svId >= 1 && svId <= 32 ? `G${
|
|
6296
|
+
return svId >= 1 && svId <= 32 ? `G${two7(svId)}` : null;
|
|
6284
6297
|
case 1:
|
|
6285
|
-
return svId >= 120 && svId <= 158 ? `S${
|
|
6298
|
+
return svId >= 120 && svId <= 158 ? `S${two7(svId - 100)}` : null;
|
|
6286
6299
|
case 2:
|
|
6287
|
-
return svId >= 1 && svId <= 36 ? `E${
|
|
6300
|
+
return svId >= 1 && svId <= 36 ? `E${two7(svId)}` : null;
|
|
6288
6301
|
case 3:
|
|
6289
|
-
return svId >= 1 && svId <= 63 ? `C${
|
|
6302
|
+
return svId >= 1 && svId <= 63 ? `C${two7(svId)}` : null;
|
|
6290
6303
|
case 5:
|
|
6291
|
-
return svId >= 1 && svId <= 10 ? `J${
|
|
6304
|
+
return svId >= 1 && svId <= 10 ? `J${two7(svId)}` : null;
|
|
6292
6305
|
case 6:
|
|
6293
|
-
return svId >= 1 && svId <= 32 ? `R${
|
|
6306
|
+
return svId >= 1 && svId <= 32 ? `R${two7(svId)}` : null;
|
|
6294
6307
|
default:
|
|
6295
6308
|
return null;
|
|
6296
6309
|
}
|
|
@@ -8677,20 +8690,1180 @@ function parseNovatelRange(data) {
|
|
|
8677
8690
|
return { epochs, messageCounts, obsCodes, badCrc };
|
|
8678
8691
|
}
|
|
8679
8692
|
|
|
8693
|
+
// src/trimble/frame.ts
|
|
8694
|
+
var STX = 2;
|
|
8695
|
+
var ETX = 3;
|
|
8696
|
+
var RAWDATA = 87;
|
|
8697
|
+
var RETSVDATA = 85;
|
|
8698
|
+
function* trimbleFrames(data, stats) {
|
|
8699
|
+
let i = 0;
|
|
8700
|
+
while (i + 6 <= data.length) {
|
|
8701
|
+
if (data[i] !== STX) {
|
|
8702
|
+
i++;
|
|
8703
|
+
continue;
|
|
8704
|
+
}
|
|
8705
|
+
const len = data[i + 3];
|
|
8706
|
+
const total = 4 + len + 2;
|
|
8707
|
+
if (i + total > data.length) {
|
|
8708
|
+
i++;
|
|
8709
|
+
continue;
|
|
8710
|
+
}
|
|
8711
|
+
if (data[i + total - 1] !== ETX) {
|
|
8712
|
+
i++;
|
|
8713
|
+
continue;
|
|
8714
|
+
}
|
|
8715
|
+
let cs = 0;
|
|
8716
|
+
for (let k = 1; k <= 3 + len; k++) cs = cs + data[i + k] & 255;
|
|
8717
|
+
if (cs !== data[i + 4 + len]) {
|
|
8718
|
+
stats.badChecksum++;
|
|
8719
|
+
i++;
|
|
8720
|
+
continue;
|
|
8721
|
+
}
|
|
8722
|
+
yield {
|
|
8723
|
+
start: i,
|
|
8724
|
+
status: data[i + 1],
|
|
8725
|
+
type: data[i + 2],
|
|
8726
|
+
len,
|
|
8727
|
+
payload: i + 4
|
|
8728
|
+
};
|
|
8729
|
+
i += total;
|
|
8730
|
+
}
|
|
8731
|
+
}
|
|
8732
|
+
|
|
8733
|
+
// src/trimble/nav.ts
|
|
8734
|
+
var GPS_EPOCH_MS13 = Date.UTC(1980, 0, 6);
|
|
8735
|
+
var SEC_PER_WEEK10 = 7 * 86400;
|
|
8736
|
+
var MS_PER_WEEK9 = SEC_PER_WEEK10 * 1e3;
|
|
8737
|
+
var GPS_PI2 = 3.1415926535898;
|
|
8738
|
+
var gpsMs3 = (week, sec) => GPS_EPOCH_MS13 + week * MS_PER_WEEK9 + sec * 1e3;
|
|
8739
|
+
var sowOf4 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK10;
|
|
8740
|
+
var SUB_GPS_EPHEMERIS = 1;
|
|
8741
|
+
var SUB_ION_UTC = 3;
|
|
8742
|
+
function decodeGpsEphemeris2(data, view, base) {
|
|
8743
|
+
const prn = data[base + 5];
|
|
8744
|
+
if (prn < 1 || prn > 32) return null;
|
|
8745
|
+
const week = view.getUint16(base + 6, false);
|
|
8746
|
+
const iode = data[base + 11];
|
|
8747
|
+
const toc = view.getInt32(base + 16, false);
|
|
8748
|
+
const toe = view.getUint32(base + 20, false);
|
|
8749
|
+
const tgd = view.getFloat64(base + 24, false);
|
|
8750
|
+
const af2 = view.getFloat64(base + 32, false);
|
|
8751
|
+
const af1 = view.getFloat64(base + 40, false);
|
|
8752
|
+
const af0 = view.getFloat64(base + 48, false);
|
|
8753
|
+
const crs = view.getFloat64(base + 56, false);
|
|
8754
|
+
const deltaN = view.getFloat64(base + 64, false) * GPS_PI2;
|
|
8755
|
+
const m0 = view.getFloat64(base + 72, false) * GPS_PI2;
|
|
8756
|
+
const cuc = view.getFloat64(base + 80, false) * GPS_PI2;
|
|
8757
|
+
const e = view.getFloat64(base + 88, false);
|
|
8758
|
+
const cus = view.getFloat64(base + 96, false) * GPS_PI2;
|
|
8759
|
+
const sqrtA = view.getFloat64(base + 104, false);
|
|
8760
|
+
const cic = view.getFloat64(base + 112, false) * GPS_PI2;
|
|
8761
|
+
const omega0 = view.getFloat64(base + 120, false) * GPS_PI2;
|
|
8762
|
+
const cis = view.getFloat64(base + 128, false) * GPS_PI2;
|
|
8763
|
+
const i0 = view.getFloat64(base + 136, false) * GPS_PI2;
|
|
8764
|
+
const crc = view.getFloat64(base + 144, false);
|
|
8765
|
+
const omega = view.getFloat64(base + 152, false) * GPS_PI2;
|
|
8766
|
+
const omegaDot = view.getFloat64(base + 160, false) * GPS_PI2;
|
|
8767
|
+
const idot = view.getFloat64(base + 168, false) * GPS_PI2;
|
|
8768
|
+
const flags = view.getUint32(base + 176, false);
|
|
8769
|
+
return {
|
|
8770
|
+
system: "G",
|
|
8771
|
+
prn: `G${String(prn).padStart(2, "0")}`,
|
|
8772
|
+
toc: sowOf4(gpsMs3(week, toc)),
|
|
8773
|
+
tocDate: new Date(gpsMs3(week, toc)),
|
|
8774
|
+
af0,
|
|
8775
|
+
af1,
|
|
8776
|
+
af2,
|
|
8777
|
+
iode,
|
|
8778
|
+
crs,
|
|
8779
|
+
deltaN,
|
|
8780
|
+
m0,
|
|
8781
|
+
cuc,
|
|
8782
|
+
e,
|
|
8783
|
+
cus,
|
|
8784
|
+
sqrtA,
|
|
8785
|
+
toe,
|
|
8786
|
+
cic,
|
|
8787
|
+
omega0,
|
|
8788
|
+
cis,
|
|
8789
|
+
i0,
|
|
8790
|
+
crc,
|
|
8791
|
+
omega,
|
|
8792
|
+
omegaDot,
|
|
8793
|
+
idot,
|
|
8794
|
+
week,
|
|
8795
|
+
svHealth: flags >>> 4 & 127,
|
|
8796
|
+
tgd
|
|
8797
|
+
};
|
|
8798
|
+
}
|
|
8799
|
+
function parseTrimbleNav(data) {
|
|
8800
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
8801
|
+
const stats = { badChecksum: 0 };
|
|
8802
|
+
const ephemerides = [];
|
|
8803
|
+
const ionoCorrections = {};
|
|
8804
|
+
const retsvCounts = {};
|
|
8805
|
+
let leapSeconds = null;
|
|
8806
|
+
const lastIode = /* @__PURE__ */ new Map();
|
|
8807
|
+
for (const f of trimbleFrames(data, stats)) {
|
|
8808
|
+
if (f.type !== RETSVDATA) continue;
|
|
8809
|
+
const sub = data[f.payload];
|
|
8810
|
+
retsvCounts[sub] = (retsvCounts[sub] ?? 0) + 1;
|
|
8811
|
+
if (sub === SUB_GPS_EPHEMERIS && f.len >= 178) {
|
|
8812
|
+
const eph = decodeGpsEphemeris2(data, view, f.start);
|
|
8813
|
+
if (!eph) continue;
|
|
8814
|
+
if (lastIode.get(eph.prn) === eph.iode) continue;
|
|
8815
|
+
lastIode.set(eph.prn, eph.iode);
|
|
8816
|
+
ephemerides.push(eph);
|
|
8817
|
+
} else if (sub === SUB_ION_UTC && f.len >= 125) {
|
|
8818
|
+
const p = f.start;
|
|
8819
|
+
const alpha = [];
|
|
8820
|
+
const beta = [];
|
|
8821
|
+
for (let i = 0; i < 4; i++) {
|
|
8822
|
+
alpha.push(view.getFloat64(p + 6 + i * 8, false));
|
|
8823
|
+
beta.push(view.getFloat64(p + 38 + i * 8, false));
|
|
8824
|
+
}
|
|
8825
|
+
ionoCorrections["GPSA"] = alpha;
|
|
8826
|
+
ionoCorrections["GPSB"] = beta;
|
|
8827
|
+
leapSeconds = Math.trunc(view.getFloat64(p + 94, false));
|
|
8828
|
+
}
|
|
8829
|
+
}
|
|
8830
|
+
return {
|
|
8831
|
+
ephemerides,
|
|
8832
|
+
ionoCorrections,
|
|
8833
|
+
leapSeconds,
|
|
8834
|
+
retsvCounts,
|
|
8835
|
+
badChecksum: stats.badChecksum
|
|
8836
|
+
};
|
|
8837
|
+
}
|
|
8838
|
+
|
|
8839
|
+
// src/trimble/index.ts
|
|
8840
|
+
var GPS_EPOCH_MS14 = Date.UTC(1980, 0, 6);
|
|
8841
|
+
var MS_PER_WEEK10 = 7 * 864e5;
|
|
8842
|
+
var REC_TYPE_27 = 6;
|
|
8843
|
+
var SYS = {
|
|
8844
|
+
0: "G",
|
|
8845
|
+
// GPS
|
|
8846
|
+
1: "S",
|
|
8847
|
+
// SBAS
|
|
8848
|
+
2: "R",
|
|
8849
|
+
// GLONASS
|
|
8850
|
+
3: "E",
|
|
8851
|
+
// Galileo
|
|
8852
|
+
4: "J",
|
|
8853
|
+
// QZSS
|
|
8854
|
+
5: "C",
|
|
8855
|
+
// BeiDou (pre-ICD numbering)
|
|
8856
|
+
7: "C",
|
|
8857
|
+
// BeiDou (ICD numbering)
|
|
8858
|
+
9: "I",
|
|
8859
|
+
// NavIC / IRNSS
|
|
8860
|
+
10: "C"
|
|
8861
|
+
// BeiDou
|
|
8862
|
+
};
|
|
8863
|
+
var CODES = {
|
|
8864
|
+
"G0-0": "1C",
|
|
8865
|
+
"G0-20": "1L",
|
|
8866
|
+
"G1-2": "2W",
|
|
8867
|
+
"G1-5": "2L",
|
|
8868
|
+
"G2-6": "5I",
|
|
8869
|
+
"G2-7": "5Q",
|
|
8870
|
+
"G2-8": "5X",
|
|
8871
|
+
"R0-0": "1C",
|
|
8872
|
+
"R0-1": "1P",
|
|
8873
|
+
"R1-0": "2C",
|
|
8874
|
+
"R1-1": "2P",
|
|
8875
|
+
"E0-23": "1C",
|
|
8876
|
+
"E2-11": "5Q",
|
|
8877
|
+
"E3-11": "7Q",
|
|
8878
|
+
"E4-14": "8Q",
|
|
8879
|
+
"E5-36": "6C",
|
|
8880
|
+
"C0-20": "1P",
|
|
8881
|
+
"C2-8": "5P",
|
|
8882
|
+
"C3-6": "7D",
|
|
8883
|
+
"C6-26": "2I",
|
|
8884
|
+
"C7-29": "6I",
|
|
8885
|
+
"S0-0": "1C",
|
|
8886
|
+
"S2-6": "5I",
|
|
8887
|
+
"J0-0": "1C"
|
|
8888
|
+
};
|
|
8889
|
+
var BAND_DIGIT = {
|
|
8890
|
+
0: "1",
|
|
8891
|
+
// L1 / E1 / B1C (1575.42)
|
|
8892
|
+
1: "2",
|
|
8893
|
+
// L2 / G2 (1227.6)
|
|
8894
|
+
2: "5",
|
|
8895
|
+
// L5 / E5a (1176.45)
|
|
8896
|
+
3: "7",
|
|
8897
|
+
// E5b / B2b (1207.14)
|
|
8898
|
+
4: "8",
|
|
8899
|
+
// E5 AltBOC (1191.795)
|
|
8900
|
+
5: "6",
|
|
8901
|
+
// E6 (1278.75)
|
|
8902
|
+
6: "2",
|
|
8903
|
+
// B1I (1561.098)
|
|
8904
|
+
7: "6",
|
|
8905
|
+
// B3I (1268.52)
|
|
8906
|
+
8: "1",
|
|
8907
|
+
// BeiDou E1 (1589.742)
|
|
8908
|
+
9: "3",
|
|
8909
|
+
// GLONASS G3 CDMA (1202.025)
|
|
8910
|
+
11: "9"
|
|
8911
|
+
// NavIC S-band (2492.028)
|
|
8912
|
+
};
|
|
8913
|
+
function rinexCode(sys, band, track) {
|
|
8914
|
+
const key = `${sys}${band}-${track}`;
|
|
8915
|
+
return CODES[key] ?? `${BAND_DIGIT[band] ?? "?"}X`;
|
|
8916
|
+
}
|
|
8917
|
+
function rinexPrn(sys, svid) {
|
|
8918
|
+
let n = svid;
|
|
8919
|
+
if (sys === "S")
|
|
8920
|
+
n = svid - 100;
|
|
8921
|
+
else if (sys === "J" && svid >= 193) n = svid - 192;
|
|
8922
|
+
return `${sys}${String(n).padStart(2, "0")}`;
|
|
8923
|
+
}
|
|
8924
|
+
var readS16 = (dv, o) => dv.getInt16(o, false);
|
|
8925
|
+
function readS24(d, o) {
|
|
8926
|
+
const v = d[o] << 16 | d[o + 1] << 8 | d[o + 2];
|
|
8927
|
+
return v & 8388608 ? v - 16777216 : v;
|
|
8928
|
+
}
|
|
8929
|
+
function readS48(d, dv, o) {
|
|
8930
|
+
const hi = d[o] << 8 | d[o + 1];
|
|
8931
|
+
const lo = dv.getUint32(o + 2, false);
|
|
8932
|
+
const v = hi * 4294967296 + lo;
|
|
8933
|
+
return hi & 32768 ? v - 281474976710656 : v;
|
|
8934
|
+
}
|
|
8935
|
+
function parseTrimble(data) {
|
|
8936
|
+
const stats = { badChecksum: 0 };
|
|
8937
|
+
const epochs = [];
|
|
8938
|
+
const obsCodes = {};
|
|
8939
|
+
const recordCounts = {};
|
|
8940
|
+
const retsvCounts = {};
|
|
8941
|
+
let pages = [];
|
|
8942
|
+
let msgReply = -1;
|
|
8943
|
+
let lastPage = 0;
|
|
8944
|
+
let msgPages = 0;
|
|
8945
|
+
let epoch = null;
|
|
8946
|
+
const finalize = () => {
|
|
8947
|
+
if (epoch) decodeEpoch(epoch, epochs, obsCodes);
|
|
8948
|
+
epoch = null;
|
|
8949
|
+
};
|
|
8950
|
+
const onMessage = (content, reply) => {
|
|
8951
|
+
if (epoch && reply === epoch.reply) {
|
|
8952
|
+
epoch.chunks.push(content);
|
|
8953
|
+
return;
|
|
8954
|
+
}
|
|
8955
|
+
finalize();
|
|
8956
|
+
if (content.length < 12) return;
|
|
8957
|
+
const dv = new DataView(
|
|
8958
|
+
content.buffer,
|
|
8959
|
+
content.byteOffset,
|
|
8960
|
+
content.byteLength
|
|
8961
|
+
);
|
|
8962
|
+
const headerLen = content[0];
|
|
8963
|
+
const week = dv.getUint16(1, false);
|
|
8964
|
+
const towMs = dv.getUint32(3, false);
|
|
8965
|
+
const nsv = content[10];
|
|
8966
|
+
const eflags = content[11];
|
|
8967
|
+
if (week < 1024 || week > 4096 || headerLen < 12 || nsv === 0) return;
|
|
8968
|
+
let svStart = headerLen;
|
|
8969
|
+
if (eflags & 32 && svStart < content.length) svStart += content[svStart];
|
|
8970
|
+
epoch = {
|
|
8971
|
+
reply,
|
|
8972
|
+
week,
|
|
8973
|
+
towMs,
|
|
8974
|
+
nsv,
|
|
8975
|
+
chunks: [content.subarray(svStart)]
|
|
8976
|
+
};
|
|
8977
|
+
};
|
|
8978
|
+
const completeMessage = () => {
|
|
8979
|
+
const total = pages.reduce((a, c) => a + c.length, 0);
|
|
8980
|
+
const content = new Uint8Array(total);
|
|
8981
|
+
let o = 0;
|
|
8982
|
+
for (const c of pages) {
|
|
8983
|
+
content.set(c, o);
|
|
8984
|
+
o += c.length;
|
|
8985
|
+
}
|
|
8986
|
+
const reply = msgReply;
|
|
8987
|
+
pages = [];
|
|
8988
|
+
onMessage(content, reply);
|
|
8989
|
+
};
|
|
8990
|
+
for (const f of trimbleFrames(data, stats)) {
|
|
8991
|
+
if (f.type !== RAWDATA) {
|
|
8992
|
+
if (f.type === 85) {
|
|
8993
|
+
const sub = data[f.payload];
|
|
8994
|
+
retsvCounts[sub] = (retsvCounts[sub] ?? 0) + 1;
|
|
8995
|
+
}
|
|
8996
|
+
continue;
|
|
8997
|
+
}
|
|
8998
|
+
const recType = data[f.payload];
|
|
8999
|
+
recordCounts[recType] = (recordCounts[recType] ?? 0) + 1;
|
|
9000
|
+
if (recType !== REC_TYPE_27) continue;
|
|
9001
|
+
const pageByte = data[f.payload + 1];
|
|
9002
|
+
const page = pageByte >> 4;
|
|
9003
|
+
const pagesTotal = pageByte & 15;
|
|
9004
|
+
const reply = data[f.payload + 2];
|
|
9005
|
+
const content = data.subarray(f.payload + 4, f.payload + f.len);
|
|
9006
|
+
if (page === 1) {
|
|
9007
|
+
pages = [content];
|
|
9008
|
+
msgReply = reply;
|
|
9009
|
+
msgPages = pagesTotal;
|
|
9010
|
+
lastPage = 1;
|
|
9011
|
+
} else if (reply === msgReply && page === lastPage + 1) {
|
|
9012
|
+
pages.push(content);
|
|
9013
|
+
lastPage = page;
|
|
9014
|
+
} else {
|
|
9015
|
+
pages = [];
|
|
9016
|
+
continue;
|
|
9017
|
+
}
|
|
9018
|
+
if (lastPage === msgPages) completeMessage();
|
|
9019
|
+
}
|
|
9020
|
+
finalize();
|
|
9021
|
+
return {
|
|
9022
|
+
epochs,
|
|
9023
|
+
obsCodes,
|
|
9024
|
+
recordCounts,
|
|
9025
|
+
retsvCounts,
|
|
9026
|
+
badChecksum: stats.badChecksum
|
|
9027
|
+
};
|
|
9028
|
+
}
|
|
9029
|
+
function decodeEpoch(epoch, epochs, obsCodes) {
|
|
9030
|
+
const total = epoch.chunks.reduce((a, c) => a + c.length, 0);
|
|
9031
|
+
const M = new Uint8Array(total);
|
|
9032
|
+
let o = 0;
|
|
9033
|
+
for (const c of epoch.chunks) {
|
|
9034
|
+
M.set(c, o);
|
|
9035
|
+
o += c.length;
|
|
9036
|
+
}
|
|
9037
|
+
const dv = new DataView(M.buffer, M.byteOffset, M.byteLength);
|
|
9038
|
+
const timeMs = GPS_EPOCH_MS14 + epoch.week * MS_PER_WEEK10 + epoch.towMs;
|
|
9039
|
+
const meas = [];
|
|
9040
|
+
let q = 0;
|
|
9041
|
+
for (let sv = 0; sv < epoch.nsv && q + 8 <= M.length; sv++) {
|
|
9042
|
+
const svLen = M[q];
|
|
9043
|
+
if (svLen < 8 || q + svLen > M.length) break;
|
|
9044
|
+
const svid = M[q + 1];
|
|
9045
|
+
const sys = SYS[M[q + 2] & 63];
|
|
9046
|
+
const chan = M[q + 3] << 24 >> 24;
|
|
9047
|
+
const nblk = M[q + 4];
|
|
9048
|
+
const prn = sys ? rinexPrn(sys, svid) : null;
|
|
9049
|
+
const gloChannel = sys === "R" ? chan : null;
|
|
9050
|
+
let r = q + svLen;
|
|
9051
|
+
let pr0 = 0;
|
|
9052
|
+
for (let b = 0; b < nblk; b++) {
|
|
9053
|
+
if (r + 5 > M.length) break;
|
|
9054
|
+
const mLen = M[r];
|
|
9055
|
+
if (mLen < 5 || r + mLen > M.length) break;
|
|
9056
|
+
const band = M[r + 1];
|
|
9057
|
+
const track = M[r + 2];
|
|
9058
|
+
const cn0 = dv.getUint16(r + 3, false) / 10;
|
|
9059
|
+
let p = r + 5;
|
|
9060
|
+
let pr;
|
|
9061
|
+
if (b === 0) {
|
|
9062
|
+
const scale = sys === "S" || sys === "J" ? 64 : 128;
|
|
9063
|
+
pr = dv.getUint32(p, false) / scale;
|
|
9064
|
+
p += 4;
|
|
9065
|
+
pr0 = pr;
|
|
9066
|
+
} else {
|
|
9067
|
+
pr = pr0 + readS16(dv, p) / 256;
|
|
9068
|
+
p += 2;
|
|
9069
|
+
}
|
|
9070
|
+
const cp = -readS48(M, dv, p) / 32768;
|
|
9071
|
+
p += 6;
|
|
9072
|
+
const cycleSlipCount = M[p];
|
|
9073
|
+
p += 1;
|
|
9074
|
+
const mf = M[p];
|
|
9075
|
+
p += 1;
|
|
9076
|
+
let mf2 = 0;
|
|
9077
|
+
if (mf & 128) {
|
|
9078
|
+
mf2 = M[p];
|
|
9079
|
+
p += 1;
|
|
9080
|
+
let f = mf2;
|
|
9081
|
+
while (f & 128) {
|
|
9082
|
+
f = M[p];
|
|
9083
|
+
p += 1;
|
|
9084
|
+
}
|
|
9085
|
+
}
|
|
9086
|
+
if (mf2 & 1) p += 1;
|
|
9087
|
+
let doppler = null;
|
|
9088
|
+
if (mf & 4) doppler = readS24(M, p) / 256;
|
|
9089
|
+
if (prn && sys) {
|
|
9090
|
+
const code = rinexCode(sys, band, track);
|
|
9091
|
+
meas.push({
|
|
9092
|
+
prn,
|
|
9093
|
+
code,
|
|
9094
|
+
pr: mf & 2 ? pr : null,
|
|
9095
|
+
cp: mf & 1 ? cp : null,
|
|
9096
|
+
doppler: mf & 1 ? doppler : null,
|
|
9097
|
+
cn0,
|
|
9098
|
+
cycleSlipCount,
|
|
9099
|
+
cycleSlip: (mf & 8) !== 0,
|
|
9100
|
+
gloChannel
|
|
9101
|
+
});
|
|
9102
|
+
const list = obsCodes[sys] ??= [];
|
|
9103
|
+
if (!list.includes(code)) list.push(code);
|
|
9104
|
+
}
|
|
9105
|
+
r += mLen;
|
|
9106
|
+
}
|
|
9107
|
+
q = r;
|
|
9108
|
+
}
|
|
9109
|
+
epochs.push({ timeMs, meas });
|
|
9110
|
+
}
|
|
9111
|
+
|
|
9112
|
+
// src/binex/frame.ts
|
|
9113
|
+
var CRC16_TABLE = (() => {
|
|
9114
|
+
const t = new Uint16Array(256);
|
|
9115
|
+
for (let n = 0; n < 256; n++) {
|
|
9116
|
+
let c = n << 8;
|
|
9117
|
+
for (let k = 0; k < 8; k++)
|
|
9118
|
+
c = c & 32768 ? (c << 1 ^ 4129) & 65535 : c << 1 & 65535;
|
|
9119
|
+
t[n] = c;
|
|
9120
|
+
}
|
|
9121
|
+
return t;
|
|
9122
|
+
})();
|
|
9123
|
+
function binexCrc16(data, start, end) {
|
|
9124
|
+
let crc = 0;
|
|
9125
|
+
for (let i = start; i < end; i++)
|
|
9126
|
+
crc = (crc << 8 ^ CRC16_TABLE[(crc >> 8 ^ data[i]) & 255]) & 65535;
|
|
9127
|
+
return crc;
|
|
9128
|
+
}
|
|
9129
|
+
var CRC32_TABLE = (() => {
|
|
9130
|
+
const t = new Uint32Array(256);
|
|
9131
|
+
for (let n = 0; n < 256; n++) {
|
|
9132
|
+
let c = n << 24;
|
|
9133
|
+
for (let k = 0; k < 8; k++)
|
|
9134
|
+
c = c & 2147483648 ? c << 1 ^ 79764919 : c << 1;
|
|
9135
|
+
t[n] = c >>> 0;
|
|
9136
|
+
}
|
|
9137
|
+
return t;
|
|
9138
|
+
})();
|
|
9139
|
+
function binexCrc32(data, start, end) {
|
|
9140
|
+
let crc = 0;
|
|
9141
|
+
for (let i = start; i < end; i++)
|
|
9142
|
+
crc = (crc << 8 ^ CRC32_TABLE[(crc >>> 24 ^ data[i]) & 255]) >>> 0;
|
|
9143
|
+
return crc >>> 0;
|
|
9144
|
+
}
|
|
9145
|
+
function binexCsum8(data, start, end) {
|
|
9146
|
+
let cs = 0;
|
|
9147
|
+
for (let i = start; i < end; i++) cs ^= data[i];
|
|
9148
|
+
return cs & 255;
|
|
9149
|
+
}
|
|
9150
|
+
function getBnxi(data, pos) {
|
|
9151
|
+
let value = 0;
|
|
9152
|
+
for (let i = 0; i < 3; i++) {
|
|
9153
|
+
const b = data[pos + i] ?? 0;
|
|
9154
|
+
value = value * 128 + (b & 127);
|
|
9155
|
+
if (!(b & 128)) return { value, size: i + 1 };
|
|
9156
|
+
}
|
|
9157
|
+
value = value * 256 + (data[pos + 3] ?? 0);
|
|
9158
|
+
return { value, size: 4 };
|
|
9159
|
+
}
|
|
9160
|
+
var SYNC = /* @__PURE__ */ new Map([
|
|
9161
|
+
[226, { littleEndian: false, enhanced: false }],
|
|
9162
|
+
[194, { littleEndian: true, enhanced: false }],
|
|
9163
|
+
[232, { littleEndian: false, enhanced: true }],
|
|
9164
|
+
[200, { littleEndian: true, enhanced: true }]
|
|
9165
|
+
]);
|
|
9166
|
+
function csumWidth(covered, enhanced) {
|
|
9167
|
+
if (enhanced) {
|
|
9168
|
+
if (covered < 128) return 2;
|
|
9169
|
+
if (covered < 1048576) return 4;
|
|
9170
|
+
return 16;
|
|
9171
|
+
}
|
|
9172
|
+
if (covered < 128) return 1;
|
|
9173
|
+
if (covered < 4096) return 2;
|
|
9174
|
+
if (covered < 1048576) return 4;
|
|
9175
|
+
return 16;
|
|
9176
|
+
}
|
|
9177
|
+
function checksumOk(data, view, covStart, covEnd, width) {
|
|
9178
|
+
switch (width) {
|
|
9179
|
+
case 1:
|
|
9180
|
+
return binexCsum8(data, covStart, covEnd) === (data[covEnd] ?? -1);
|
|
9181
|
+
case 2:
|
|
9182
|
+
return binexCrc16(data, covStart, covEnd) === view.getUint16(covEnd);
|
|
9183
|
+
case 4:
|
|
9184
|
+
return binexCrc32(data, covStart, covEnd) === view.getUint32(covEnd);
|
|
9185
|
+
default:
|
|
9186
|
+
return false;
|
|
9187
|
+
}
|
|
9188
|
+
}
|
|
9189
|
+
function* binexRecords(data, view, stats) {
|
|
9190
|
+
let i = 0;
|
|
9191
|
+
while (i + 2 <= data.length) {
|
|
9192
|
+
const sync = SYNC.get(data[i]);
|
|
9193
|
+
if (!sync) {
|
|
9194
|
+
i++;
|
|
9195
|
+
continue;
|
|
9196
|
+
}
|
|
9197
|
+
const id = data[i + 1];
|
|
9198
|
+
const { value: len, size: lenH } = getBnxi(data, i + 2);
|
|
9199
|
+
const body = i + 2 + lenH;
|
|
9200
|
+
const covStart = i + 1;
|
|
9201
|
+
const covEnd = body + len;
|
|
9202
|
+
const covered = covEnd - covStart;
|
|
9203
|
+
const width = csumWidth(covered, sync.enhanced);
|
|
9204
|
+
if (width === 16 || covEnd + width > data.length) {
|
|
9205
|
+
i++;
|
|
9206
|
+
continue;
|
|
9207
|
+
}
|
|
9208
|
+
if (!checksumOk(data, view, covStart, covEnd, width)) {
|
|
9209
|
+
stats.badCrc++;
|
|
9210
|
+
i++;
|
|
9211
|
+
continue;
|
|
9212
|
+
}
|
|
9213
|
+
yield { id, start: i, body, len, ...sync };
|
|
9214
|
+
i = covEnd + width;
|
|
9215
|
+
}
|
|
9216
|
+
}
|
|
9217
|
+
|
|
9218
|
+
// src/binex/nav.ts
|
|
9219
|
+
var GPS_EPOCH_MS15 = Date.UTC(1980, 0, 6);
|
|
9220
|
+
var GLO_DAY0_MS = Date.UTC(1980, 0, 1);
|
|
9221
|
+
var BDT_EPOCH_MS4 = Date.UTC(2006, 0, 1);
|
|
9222
|
+
var SEC_PER_WEEK11 = 7 * 86400;
|
|
9223
|
+
var MS_PER_WEEK11 = SEC_PER_WEEK11 * 1e3;
|
|
9224
|
+
var SC2RAD = GPS_PI;
|
|
9225
|
+
var gpsMs4 = (week, sec) => GPS_EPOCH_MS15 + week * MS_PER_WEEK11 + sec * 1e3;
|
|
9226
|
+
var sowOf5 = (dateMs) => (dateMs / 1e3 % SEC_PER_WEEK11 + SEC_PER_WEEK11) % SEC_PER_WEEK11;
|
|
9227
|
+
var two5 = (n) => String(n).padStart(2, "0");
|
|
9228
|
+
var Reader = class {
|
|
9229
|
+
constructor(view, start, le) {
|
|
9230
|
+
this.view = view;
|
|
9231
|
+
this.le = le;
|
|
9232
|
+
this.p = start;
|
|
9233
|
+
}
|
|
9234
|
+
p;
|
|
9235
|
+
u1() {
|
|
9236
|
+
return this.view.getUint8(this.p++);
|
|
9237
|
+
}
|
|
9238
|
+
i1() {
|
|
9239
|
+
return this.view.getInt8(this.p++);
|
|
9240
|
+
}
|
|
9241
|
+
u2() {
|
|
9242
|
+
const v = this.view.getUint16(this.p, this.le);
|
|
9243
|
+
this.p += 2;
|
|
9244
|
+
return v;
|
|
9245
|
+
}
|
|
9246
|
+
i4() {
|
|
9247
|
+
const v = this.view.getInt32(this.p, this.le);
|
|
9248
|
+
this.p += 4;
|
|
9249
|
+
return v;
|
|
9250
|
+
}
|
|
9251
|
+
u4() {
|
|
9252
|
+
const v = this.view.getUint32(this.p, this.le);
|
|
9253
|
+
this.p += 4;
|
|
9254
|
+
return v;
|
|
9255
|
+
}
|
|
9256
|
+
r4() {
|
|
9257
|
+
const v = this.view.getFloat32(this.p, this.le);
|
|
9258
|
+
this.p += 4;
|
|
9259
|
+
return v;
|
|
9260
|
+
}
|
|
9261
|
+
r8() {
|
|
9262
|
+
const v = this.view.getFloat64(this.p, this.le);
|
|
9263
|
+
this.p += 8;
|
|
9264
|
+
return v;
|
|
9265
|
+
}
|
|
9266
|
+
};
|
|
9267
|
+
function readKeplerCore(r) {
|
|
9268
|
+
const deltaN = r.r4() * SC2RAD;
|
|
9269
|
+
const m0 = r.r8();
|
|
9270
|
+
const e = r.r8();
|
|
9271
|
+
const sqrtA = r.r8();
|
|
9272
|
+
const cic = r.r4();
|
|
9273
|
+
const crc = r.r4();
|
|
9274
|
+
const cis = r.r4();
|
|
9275
|
+
const crs = r.r4();
|
|
9276
|
+
const cuc = r.r4();
|
|
9277
|
+
const cus = r.r4();
|
|
9278
|
+
const omega0 = r.r8();
|
|
9279
|
+
const omega = r.r8();
|
|
9280
|
+
const i0 = r.r8();
|
|
9281
|
+
const omegaDot = r.r4() * SC2RAD;
|
|
9282
|
+
const idot = r.r4() * SC2RAD;
|
|
9283
|
+
return {
|
|
9284
|
+
deltaN,
|
|
9285
|
+
m0,
|
|
9286
|
+
e,
|
|
9287
|
+
sqrtA,
|
|
9288
|
+
cic,
|
|
9289
|
+
crc,
|
|
9290
|
+
cis,
|
|
9291
|
+
crs,
|
|
9292
|
+
cuc,
|
|
9293
|
+
cus,
|
|
9294
|
+
omega0,
|
|
9295
|
+
omega,
|
|
9296
|
+
i0,
|
|
9297
|
+
omegaDot,
|
|
9298
|
+
idot
|
|
9299
|
+
};
|
|
9300
|
+
}
|
|
9301
|
+
function decodeGpsQzss(view, p, le, sys) {
|
|
9302
|
+
const r = new Reader(view, p, le);
|
|
9303
|
+
const prnRaw = r.u1() + (sys === "G" ? 1 : 0);
|
|
9304
|
+
const prn = sys === "G" ? prnRaw : prnRaw - 192;
|
|
9305
|
+
if (sys === "G" && (prn < 1 || prn > 32)) return null;
|
|
9306
|
+
if (sys === "J" && (prn < 1 || prn > 10)) return null;
|
|
9307
|
+
const week = r.u2();
|
|
9308
|
+
r.i4();
|
|
9309
|
+
const toes = r.i4();
|
|
9310
|
+
const tgd = r.r4();
|
|
9311
|
+
r.i4();
|
|
9312
|
+
const af2 = r.r4();
|
|
9313
|
+
const af1 = r.r4();
|
|
9314
|
+
const af0 = r.r4();
|
|
9315
|
+
const iode = r.i4();
|
|
9316
|
+
const core = readKeplerCore(r);
|
|
9317
|
+
r.r4();
|
|
9318
|
+
const svHealth = r.u2();
|
|
9319
|
+
const tocDate = new Date(gpsMs4(week, toes));
|
|
9320
|
+
return {
|
|
9321
|
+
system: sys,
|
|
9322
|
+
prn: `${sys}${two5(prn)}`,
|
|
9323
|
+
toc: sowOf5(tocDate.getTime()),
|
|
9324
|
+
tocDate,
|
|
9325
|
+
af0,
|
|
9326
|
+
af1,
|
|
9327
|
+
af2,
|
|
9328
|
+
iode,
|
|
9329
|
+
...core,
|
|
9330
|
+
toe: toes,
|
|
9331
|
+
week,
|
|
9332
|
+
svHealth,
|
|
9333
|
+
tgd
|
|
9334
|
+
};
|
|
9335
|
+
}
|
|
9336
|
+
function decodeGalileo(view, p, le) {
|
|
9337
|
+
const r = new Reader(view, p, le);
|
|
9338
|
+
const prn = r.u1() + 1;
|
|
9339
|
+
if (prn < 1 || prn > 36) return null;
|
|
9340
|
+
const week = r.u2();
|
|
9341
|
+
r.i4();
|
|
9342
|
+
const toes = r.i4();
|
|
9343
|
+
const tgd = r.r4();
|
|
9344
|
+
r.r4();
|
|
9345
|
+
const iode = r.i4();
|
|
9346
|
+
const af2 = r.r4();
|
|
9347
|
+
const af1 = r.r4();
|
|
9348
|
+
const af0 = r.r4();
|
|
9349
|
+
const core = readKeplerCore(r);
|
|
9350
|
+
r.r4();
|
|
9351
|
+
const svHealth = r.u2();
|
|
9352
|
+
const tocDate = new Date(gpsMs4(week, toes));
|
|
9353
|
+
return {
|
|
9354
|
+
system: "E",
|
|
9355
|
+
prn: `E${two5(prn)}`,
|
|
9356
|
+
toc: sowOf5(tocDate.getTime()),
|
|
9357
|
+
tocDate,
|
|
9358
|
+
af0,
|
|
9359
|
+
af1,
|
|
9360
|
+
af2,
|
|
9361
|
+
iode,
|
|
9362
|
+
...core,
|
|
9363
|
+
toe: toes,
|
|
9364
|
+
week,
|
|
9365
|
+
svHealth,
|
|
9366
|
+
tgd
|
|
9367
|
+
};
|
|
9368
|
+
}
|
|
9369
|
+
function bdsTgd(tgd) {
|
|
9370
|
+
tgd &= 1023;
|
|
9371
|
+
return tgd & 512 ? -1e-10 * (~tgd & 511) : 1e-10 * (tgd & 511);
|
|
9372
|
+
}
|
|
9373
|
+
function decodeBeidou(view, p, le) {
|
|
9374
|
+
const r = new Reader(view, p, le);
|
|
9375
|
+
const prn = r.u1();
|
|
9376
|
+
if (prn < 1 || prn > 63) return null;
|
|
9377
|
+
const week = r.u2();
|
|
9378
|
+
r.i4();
|
|
9379
|
+
r.i4();
|
|
9380
|
+
const toes = r.i4();
|
|
9381
|
+
const af2 = r.r4();
|
|
9382
|
+
const af1 = r.r4();
|
|
9383
|
+
const af0 = r.r4();
|
|
9384
|
+
const core = readKeplerCore(r);
|
|
9385
|
+
const flag1 = r.u2();
|
|
9386
|
+
const flag2 = r.u4();
|
|
9387
|
+
const iode = flag1 >> 6 & 31;
|
|
9388
|
+
const svHealth = flag1 & 1;
|
|
9389
|
+
const tgd = bdsTgd(flag2 >> 4);
|
|
9390
|
+
const tocDate = new Date(BDT_EPOCH_MS4 + week * MS_PER_WEEK11 + toes * 1e3);
|
|
9391
|
+
return {
|
|
9392
|
+
system: "C",
|
|
9393
|
+
prn: `C${two5(prn)}`,
|
|
9394
|
+
toc: sowOf5(tocDate.getTime()),
|
|
9395
|
+
tocDate,
|
|
9396
|
+
af0,
|
|
9397
|
+
af1,
|
|
9398
|
+
af2,
|
|
9399
|
+
iode,
|
|
9400
|
+
...core,
|
|
9401
|
+
toe: toes,
|
|
9402
|
+
week,
|
|
9403
|
+
// RINEX BDS week field is the BDT week
|
|
9404
|
+
svHealth,
|
|
9405
|
+
tgd
|
|
9406
|
+
};
|
|
9407
|
+
}
|
|
9408
|
+
function decodeGlonass(view, p, le) {
|
|
9409
|
+
const r = new Reader(view, p, le);
|
|
9410
|
+
const slot = r.u1() + 1;
|
|
9411
|
+
if (slot < 1 || slot > 27) return null;
|
|
9412
|
+
const day = r.u2();
|
|
9413
|
+
const tod = r.u4();
|
|
9414
|
+
const tauN = r.r8();
|
|
9415
|
+
const gammaN = r.r8();
|
|
9416
|
+
const tof = r.u4();
|
|
9417
|
+
const x = r.r8();
|
|
9418
|
+
const xDot = r.r8();
|
|
9419
|
+
const xAcc = r.r8();
|
|
9420
|
+
const y = r.r8();
|
|
9421
|
+
const yDot = r.r8();
|
|
9422
|
+
const yAcc = r.r8();
|
|
9423
|
+
const z = r.r8();
|
|
9424
|
+
const zDot = r.r8();
|
|
9425
|
+
const zAcc = r.r8();
|
|
9426
|
+
const health = r.u1() & 1;
|
|
9427
|
+
const freqNum = r.i1();
|
|
9428
|
+
const tocDate = new Date(
|
|
9429
|
+
GLO_DAY0_MS + (day - 1) * 864e5 + (tod - 10800) * 1e3
|
|
9430
|
+
);
|
|
9431
|
+
return {
|
|
9432
|
+
system: "R",
|
|
9433
|
+
prn: `R${two5(slot)}`,
|
|
9434
|
+
tocDate,
|
|
9435
|
+
tauN,
|
|
9436
|
+
gammaN,
|
|
9437
|
+
messageFrameTime: tof,
|
|
9438
|
+
x,
|
|
9439
|
+
y,
|
|
9440
|
+
z,
|
|
9441
|
+
xDot,
|
|
9442
|
+
yDot,
|
|
9443
|
+
zDot,
|
|
9444
|
+
xAcc,
|
|
9445
|
+
yAcc,
|
|
9446
|
+
zAcc,
|
|
9447
|
+
health,
|
|
9448
|
+
freqNum
|
|
9449
|
+
};
|
|
9450
|
+
}
|
|
9451
|
+
function decodeSbas(view, p, le) {
|
|
9452
|
+
const r = new Reader(view, p, le);
|
|
9453
|
+
const prn = r.u1();
|
|
9454
|
+
const week = r.u2();
|
|
9455
|
+
const tow = r.u4();
|
|
9456
|
+
const af0 = r.r8();
|
|
9457
|
+
const af1 = r.r4();
|
|
9458
|
+
const toe = r.u4();
|
|
9459
|
+
const x = r.r8();
|
|
9460
|
+
const xDot = r.r8();
|
|
9461
|
+
const xAcc = r.r8();
|
|
9462
|
+
const y = r.r8();
|
|
9463
|
+
const yDot = r.r8();
|
|
9464
|
+
const yAcc = r.r8();
|
|
9465
|
+
const z = r.r8();
|
|
9466
|
+
const zDot = r.r8();
|
|
9467
|
+
const zAcc = r.r8();
|
|
9468
|
+
const health = r.u1();
|
|
9469
|
+
if (prn < 120 || prn > 158) return null;
|
|
9470
|
+
return {
|
|
9471
|
+
system: "S",
|
|
9472
|
+
prn: `S${two5(prn - 100)}`,
|
|
9473
|
+
tocDate: new Date(gpsMs4(week, toe)),
|
|
9474
|
+
tauN: af0,
|
|
9475
|
+
gammaN: af1,
|
|
9476
|
+
messageFrameTime: tow,
|
|
9477
|
+
x,
|
|
9478
|
+
y,
|
|
9479
|
+
z,
|
|
9480
|
+
xDot,
|
|
9481
|
+
yDot,
|
|
9482
|
+
zDot,
|
|
9483
|
+
xAcc,
|
|
9484
|
+
yAcc,
|
|
9485
|
+
zAcc,
|
|
9486
|
+
health,
|
|
9487
|
+
freqNum: 0
|
|
9488
|
+
};
|
|
9489
|
+
}
|
|
9490
|
+
function decodeBinexEph(view, body, len, le) {
|
|
9491
|
+
const sub = view.getUint8(body);
|
|
9492
|
+
const p = body + 1;
|
|
9493
|
+
const n = len - 1;
|
|
9494
|
+
switch (sub) {
|
|
9495
|
+
case 1:
|
|
9496
|
+
return n >= 127 ? decodeGpsQzss(view, p, le, "G") : null;
|
|
9497
|
+
case 2:
|
|
9498
|
+
return n >= 119 ? decodeGlonass(view, p, le) : null;
|
|
9499
|
+
case 3:
|
|
9500
|
+
return n >= 98 ? decodeSbas(view, p, le) : null;
|
|
9501
|
+
case 4:
|
|
9502
|
+
return n >= 127 ? decodeGalileo(view, p, le) : null;
|
|
9503
|
+
case 5:
|
|
9504
|
+
return n >= 117 ? decodeBeidou(view, p, le) : null;
|
|
9505
|
+
case 6:
|
|
9506
|
+
return n >= 127 ? decodeGpsQzss(view, p, le, "J") : null;
|
|
9507
|
+
default:
|
|
9508
|
+
return null;
|
|
9509
|
+
}
|
|
9510
|
+
}
|
|
9511
|
+
|
|
9512
|
+
// src/binex/index.ts
|
|
9513
|
+
var GPS_EPOCH_MS16 = Date.UTC(1980, 0, 6);
|
|
9514
|
+
var CLIGHT2 = 299792458;
|
|
9515
|
+
var OBS_CODES = {
|
|
9516
|
+
0: [
|
|
9517
|
+
"1C",
|
|
9518
|
+
"1C",
|
|
9519
|
+
"1P",
|
|
9520
|
+
"1W",
|
|
9521
|
+
"1Y",
|
|
9522
|
+
"1M",
|
|
9523
|
+
"1X",
|
|
9524
|
+
"1N",
|
|
9525
|
+
"",
|
|
9526
|
+
"",
|
|
9527
|
+
"2W",
|
|
9528
|
+
"2C",
|
|
9529
|
+
"2D",
|
|
9530
|
+
"2S",
|
|
9531
|
+
"2L",
|
|
9532
|
+
"2X",
|
|
9533
|
+
"2P",
|
|
9534
|
+
"2W",
|
|
9535
|
+
"2Y",
|
|
9536
|
+
"2M",
|
|
9537
|
+
"2N",
|
|
9538
|
+
"",
|
|
9539
|
+
"",
|
|
9540
|
+
"5X",
|
|
9541
|
+
"5I",
|
|
9542
|
+
"5Q",
|
|
9543
|
+
"5X"
|
|
9544
|
+
],
|
|
9545
|
+
// GPS
|
|
9546
|
+
1: [
|
|
9547
|
+
"1C",
|
|
9548
|
+
"1C",
|
|
9549
|
+
"1P",
|
|
9550
|
+
"",
|
|
9551
|
+
"",
|
|
9552
|
+
"",
|
|
9553
|
+
"",
|
|
9554
|
+
"",
|
|
9555
|
+
"",
|
|
9556
|
+
"",
|
|
9557
|
+
"2C",
|
|
9558
|
+
"2C",
|
|
9559
|
+
"2P",
|
|
9560
|
+
"3X",
|
|
9561
|
+
"3I",
|
|
9562
|
+
"3Q",
|
|
9563
|
+
"3X"
|
|
9564
|
+
],
|
|
9565
|
+
// GLONASS
|
|
9566
|
+
3: [
|
|
9567
|
+
"1C",
|
|
9568
|
+
"1A",
|
|
9569
|
+
"1B",
|
|
9570
|
+
"1C",
|
|
9571
|
+
"1X",
|
|
9572
|
+
"1Z",
|
|
9573
|
+
"5X",
|
|
9574
|
+
"5I",
|
|
9575
|
+
"5Q",
|
|
9576
|
+
"5X",
|
|
9577
|
+
"7X",
|
|
9578
|
+
"7I",
|
|
9579
|
+
"7Q",
|
|
9580
|
+
"7X",
|
|
9581
|
+
"8X",
|
|
9582
|
+
"8I",
|
|
9583
|
+
"8Q",
|
|
9584
|
+
"8X",
|
|
9585
|
+
"6X",
|
|
9586
|
+
"6A",
|
|
9587
|
+
"6B",
|
|
9588
|
+
"6C",
|
|
9589
|
+
"6X",
|
|
9590
|
+
"6Z"
|
|
9591
|
+
],
|
|
9592
|
+
// Galileo
|
|
9593
|
+
2: ["1C", "1C", "", "", "", "", "5X", "5I", "5Q", "5X"],
|
|
9594
|
+
// SBAS
|
|
9595
|
+
4: [
|
|
9596
|
+
"2X",
|
|
9597
|
+
"2I",
|
|
9598
|
+
"2Q",
|
|
9599
|
+
"2X",
|
|
9600
|
+
"7X",
|
|
9601
|
+
"7I",
|
|
9602
|
+
"7Q",
|
|
9603
|
+
"7X",
|
|
9604
|
+
"6X",
|
|
9605
|
+
"6I",
|
|
9606
|
+
"6Q",
|
|
9607
|
+
"6X",
|
|
9608
|
+
"1X",
|
|
9609
|
+
"1S",
|
|
9610
|
+
"1L",
|
|
9611
|
+
"1X"
|
|
9612
|
+
],
|
|
9613
|
+
// BeiDou
|
|
9614
|
+
5: [
|
|
9615
|
+
"1C",
|
|
9616
|
+
"1C",
|
|
9617
|
+
"1S",
|
|
9618
|
+
"1L",
|
|
9619
|
+
"1X",
|
|
9620
|
+
"",
|
|
9621
|
+
"",
|
|
9622
|
+
"2X",
|
|
9623
|
+
"2S",
|
|
9624
|
+
"2L",
|
|
9625
|
+
"2X",
|
|
9626
|
+
"",
|
|
9627
|
+
"",
|
|
9628
|
+
"5X",
|
|
9629
|
+
"5I",
|
|
9630
|
+
"5Q",
|
|
9631
|
+
"5X",
|
|
9632
|
+
"",
|
|
9633
|
+
"",
|
|
9634
|
+
"6X",
|
|
9635
|
+
"6S",
|
|
9636
|
+
"6L",
|
|
9637
|
+
"6X",
|
|
9638
|
+
"",
|
|
9639
|
+
"",
|
|
9640
|
+
"",
|
|
9641
|
+
"",
|
|
9642
|
+
"",
|
|
9643
|
+
"",
|
|
9644
|
+
"",
|
|
9645
|
+
"1Z"
|
|
9646
|
+
]
|
|
9647
|
+
// QZSS
|
|
9648
|
+
};
|
|
9649
|
+
var two6 = (n) => String(n).padStart(2, "0");
|
|
9650
|
+
function obsPrn(sys, prn) {
|
|
9651
|
+
switch (sys) {
|
|
9652
|
+
case 0:
|
|
9653
|
+
return prn >= 1 && prn <= 32 ? `G${two6(prn)}` : null;
|
|
9654
|
+
case 1:
|
|
9655
|
+
return prn >= 1 && prn <= 27 ? `R${two6(prn)}` : null;
|
|
9656
|
+
case 2:
|
|
9657
|
+
return prn >= 120 && prn <= 158 ? `S${two6(prn - 100)}` : null;
|
|
9658
|
+
case 3:
|
|
9659
|
+
return prn >= 1 && prn <= 36 ? `E${two6(prn)}` : null;
|
|
9660
|
+
case 4:
|
|
9661
|
+
return prn >= 1 && prn <= 63 ? `C${two6(prn)}` : null;
|
|
9662
|
+
case 5:
|
|
9663
|
+
if (prn >= 193 && prn <= 202) return `J${two6(prn - 192)}`;
|
|
9664
|
+
return prn >= 1 && prn <= 10 ? `J${two6(prn)}` : null;
|
|
9665
|
+
default:
|
|
9666
|
+
return null;
|
|
9667
|
+
}
|
|
9668
|
+
}
|
|
9669
|
+
function carrierFreq3(sys, code, fcn) {
|
|
9670
|
+
const band = code.charCodeAt(0) - 48;
|
|
9671
|
+
switch (sys) {
|
|
9672
|
+
case "G":
|
|
9673
|
+
case "J":
|
|
9674
|
+
if (band === 1) return 157542e4;
|
|
9675
|
+
if (band === 2) return 12276e5;
|
|
9676
|
+
if (band === 5) return 117645e4;
|
|
9677
|
+
if (band === 6) return 127875e4;
|
|
9678
|
+
return 0;
|
|
9679
|
+
case "R":
|
|
9680
|
+
if (band === 1) return fcn >= -7 ? 1602e6 + fcn * 562500 : 0;
|
|
9681
|
+
if (band === 2) return fcn >= -7 ? 1246e6 + fcn * 437500 : 0;
|
|
9682
|
+
if (band === 3) return 1202025e3;
|
|
9683
|
+
return 0;
|
|
9684
|
+
case "E":
|
|
9685
|
+
if (band === 1) return 157542e4;
|
|
9686
|
+
if (band === 5) return 117645e4;
|
|
9687
|
+
if (band === 6) return 127875e4;
|
|
9688
|
+
if (band === 7) return 120714e4;
|
|
9689
|
+
if (band === 8) return 1191795e3;
|
|
9690
|
+
return 0;
|
|
9691
|
+
case "C":
|
|
9692
|
+
if (band === 1) return 157542e4;
|
|
9693
|
+
if (band === 2) return 1561098e3;
|
|
9694
|
+
if (band === 5) return 117645e4;
|
|
9695
|
+
if (band === 6) return 126852e4;
|
|
9696
|
+
if (band === 7) return 120714e4;
|
|
9697
|
+
if (band === 8) return 1191795e3;
|
|
9698
|
+
return 0;
|
|
9699
|
+
case "S":
|
|
9700
|
+
if (band === 1) return 157542e4;
|
|
9701
|
+
if (band === 5) return 117645e4;
|
|
9702
|
+
return 0;
|
|
9703
|
+
default:
|
|
9704
|
+
return 0;
|
|
9705
|
+
}
|
|
9706
|
+
}
|
|
9707
|
+
var FCN_UNKNOWN = -100;
|
|
9708
|
+
function decodeObsSat(data, start, nobs, sys) {
|
|
9709
|
+
let p = start;
|
|
9710
|
+
let fcn = FCN_UNKNOWN;
|
|
9711
|
+
const obs = [];
|
|
9712
|
+
const block0Flags = [0, 0, 0, 0];
|
|
9713
|
+
let refRange = 0;
|
|
9714
|
+
for (let b = 0; b < nobs; b++) {
|
|
9715
|
+
const flags = b === 0 ? block0Flags : block0Flags.slice();
|
|
9716
|
+
const b0 = data[p++];
|
|
9717
|
+
const code = b0 & 31;
|
|
9718
|
+
const slip = (b0 >> 5 & 1) === 1;
|
|
9719
|
+
let more = b0 >> 7 & 1;
|
|
9720
|
+
while (more) {
|
|
9721
|
+
const fb = data[p++];
|
|
9722
|
+
flags[fb & 3] = fb & 127;
|
|
9723
|
+
more = fb & 128;
|
|
9724
|
+
}
|
|
9725
|
+
if (sys === 1 && flags[2] > 0 && (code === 1 || code === 2 || code === 11 || code === 12)) {
|
|
9726
|
+
fcn = getBitS(Uint8Array.of(flags[2]), 2, 4);
|
|
9727
|
+
}
|
|
9728
|
+
const acc = flags[0] & 32 ? 1e-4 : 2e-5;
|
|
9729
|
+
let cn0 = data[p++] * 0.4;
|
|
9730
|
+
let range;
|
|
9731
|
+
if (b === 0) {
|
|
9732
|
+
cn0 += getBitS(data, p * 8, 2) * 0.1;
|
|
9733
|
+
range = getBitU(data, p * 8 + 2, 38) * 1e-3;
|
|
9734
|
+
p += 5;
|
|
9735
|
+
refRange = range;
|
|
9736
|
+
} else if (flags[0] & 64) {
|
|
9737
|
+
cn0 += getBitS(data, p * 8, 2) * 0.1;
|
|
9738
|
+
range = refRange + getBitS(data, p * 8 + 4, 20) * 1e-3;
|
|
9739
|
+
p += 3;
|
|
9740
|
+
} else {
|
|
9741
|
+
range = refRange + getBitS(data, p * 8, 16) * 1e-3;
|
|
9742
|
+
p += 2;
|
|
9743
|
+
}
|
|
9744
|
+
let phase;
|
|
9745
|
+
if (flags[0] & 64) {
|
|
9746
|
+
phase = range + getBitS(data, p * 8, 24) * acc;
|
|
9747
|
+
p += 3;
|
|
9748
|
+
} else {
|
|
9749
|
+
cn0 += getBitS(data, p * 8, 2) * 0.1;
|
|
9750
|
+
phase = range + getBitS(data, p * 8 + 2, 22) * acc;
|
|
9751
|
+
p += 3;
|
|
9752
|
+
}
|
|
9753
|
+
let doppler = null;
|
|
9754
|
+
if (flags[0] & 4) {
|
|
9755
|
+
doppler = getBitS(data, p * 8, 24) / 256;
|
|
9756
|
+
p += 3;
|
|
9757
|
+
}
|
|
9758
|
+
if (flags[0] & 8) {
|
|
9759
|
+
p += flags[0] & 16 ? 2 : 1;
|
|
9760
|
+
}
|
|
9761
|
+
obs.push({ code, slip, pr: range, phase, cn0, doppler });
|
|
9762
|
+
}
|
|
9763
|
+
return { obs, fcn, next: p };
|
|
9764
|
+
}
|
|
9765
|
+
function decodeObsRecord(data, view, body, len, obsCodes) {
|
|
9766
|
+
let p = body + 1;
|
|
9767
|
+
const min = view.getUint32(p);
|
|
9768
|
+
p += 4;
|
|
9769
|
+
const msec = view.getUint16(p);
|
|
9770
|
+
p += 2;
|
|
9771
|
+
const timeMs = GPS_EPOCH_MS16 + min * 6e4 + msec;
|
|
9772
|
+
const flag = data[p++];
|
|
9773
|
+
const nsat = (flag & 63) + 1;
|
|
9774
|
+
if (flag & 128) p += 3;
|
|
9775
|
+
if (flag & 64) {
|
|
9776
|
+
const nsys = getBitU(data, p * 8, 4);
|
|
9777
|
+
p += 1;
|
|
9778
|
+
p += nsys * 4;
|
|
9779
|
+
}
|
|
9780
|
+
const end = body + len;
|
|
9781
|
+
const meas = [];
|
|
9782
|
+
for (let i = 0; i < nsat && p < end; i++) {
|
|
9783
|
+
const prn = data[p++];
|
|
9784
|
+
const b = data[p++];
|
|
9785
|
+
const nobs = b >> 4 & 7;
|
|
9786
|
+
const sys = b & 15;
|
|
9787
|
+
const sat = obsPrn(sys, prn);
|
|
9788
|
+
const { obs, fcn, next } = decodeObsSat(data, p, nobs, sys);
|
|
9789
|
+
p = next;
|
|
9790
|
+
if (p > end) return null;
|
|
9791
|
+
if (!sat) continue;
|
|
9792
|
+
const table = OBS_CODES[sys];
|
|
9793
|
+
const sysL = sat[0];
|
|
9794
|
+
for (const o of obs) {
|
|
9795
|
+
const code = table?.[o.code & 63] ?? "";
|
|
9796
|
+
if (!code) continue;
|
|
9797
|
+
const freq = carrierFreq3(sysL, code, fcn);
|
|
9798
|
+
meas.push({
|
|
9799
|
+
prn: sat,
|
|
9800
|
+
code,
|
|
9801
|
+
pr: o.pr,
|
|
9802
|
+
cp: freq > 0 ? o.phase * freq / CLIGHT2 : null,
|
|
9803
|
+
doppler: o.doppler,
|
|
9804
|
+
cn0: o.cn0,
|
|
9805
|
+
slip: o.slip
|
|
9806
|
+
});
|
|
9807
|
+
const codes = obsCodes[sysL] ??= [];
|
|
9808
|
+
if (!codes.includes(code)) codes.push(code);
|
|
9809
|
+
}
|
|
9810
|
+
}
|
|
9811
|
+
return { timeMs, meas };
|
|
9812
|
+
}
|
|
9813
|
+
function parseBinex(data) {
|
|
9814
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
9815
|
+
const epochs = [];
|
|
9816
|
+
const ephemerides = [];
|
|
9817
|
+
const messageCounts = {};
|
|
9818
|
+
const obsCodes = {};
|
|
9819
|
+
const stats = { badCrc: 0 };
|
|
9820
|
+
const lastKep = /* @__PURE__ */ new Map();
|
|
9821
|
+
const lastState = /* @__PURE__ */ new Map();
|
|
9822
|
+
const hex = (n) => `0x${n.toString(16).padStart(2, "0")}`;
|
|
9823
|
+
for (const rec of binexRecords(data, view, stats)) {
|
|
9824
|
+
const sub = rec.len > 0 ? data[rec.body] : 0;
|
|
9825
|
+
const key = rec.id === 1 || rec.id === 127 ? `${hex(rec.id)}-${sub.toString(16).padStart(2, "0")}` : hex(rec.id);
|
|
9826
|
+
messageCounts[key] = (messageCounts[key] ?? 0) + 1;
|
|
9827
|
+
if (rec.id === 127 && sub === 5 && rec.len >= 8 && !rec.littleEndian) {
|
|
9828
|
+
const epoch = decodeObsRecord(data, view, rec.body, rec.len, obsCodes);
|
|
9829
|
+
if (epoch) epochs.push(epoch);
|
|
9830
|
+
} else if (rec.id === 1 && rec.len >= 2) {
|
|
9831
|
+
const eph = decodeBinexEph(view, rec.body, rec.len, rec.littleEndian);
|
|
9832
|
+
if (!eph) continue;
|
|
9833
|
+
if ("iode" in eph) {
|
|
9834
|
+
const prev = lastKep.get(eph.prn);
|
|
9835
|
+
if (prev && prev.iode === eph.iode && prev.toe === eph.toe && prev.tocDate.getTime() === eph.tocDate.getTime()) {
|
|
9836
|
+
continue;
|
|
9837
|
+
}
|
|
9838
|
+
lastKep.set(eph.prn, eph);
|
|
9839
|
+
ephemerides.push(eph);
|
|
9840
|
+
} else {
|
|
9841
|
+
const prev = lastState.get(eph.prn);
|
|
9842
|
+
if (prev && Math.abs(prev.tocDate.getTime() - eph.tocDate.getTime()) < 1e3 && prev.health === eph.health) {
|
|
9843
|
+
continue;
|
|
9844
|
+
}
|
|
9845
|
+
lastState.set(eph.prn, eph);
|
|
9846
|
+
ephemerides.push(eph);
|
|
9847
|
+
}
|
|
9848
|
+
}
|
|
9849
|
+
}
|
|
9850
|
+
return { epochs, ephemerides, messageCounts, obsCodes, badCrc: stats.badCrc };
|
|
9851
|
+
}
|
|
9852
|
+
|
|
8680
9853
|
// src/orbit/almanac.ts
|
|
8681
9854
|
var GM_GPS = 3986005e8;
|
|
8682
9855
|
var GM_GAL = 3986004418e5;
|
|
8683
9856
|
var GM_BDS = 3986004418e5;
|
|
8684
|
-
var
|
|
8685
|
-
var
|
|
9857
|
+
var GPS_EPOCH_MS17 = Date.UTC(1980, 0, 6);
|
|
9858
|
+
var BDT_EPOCH_MS5 = Date.UTC(2006, 0, 1);
|
|
8686
9859
|
var WEEK_MS = 6048e5;
|
|
8687
9860
|
var BDT_MINUS_GPST_MS = 14e3;
|
|
8688
9861
|
var BDS_GEO_PRNS = /* @__PURE__ */ new Set([1, 2, 3, 4, 5, 59, 60, 61, 62, 63]);
|
|
8689
9862
|
function almanacEpochMs(alm) {
|
|
8690
9863
|
if (alm.system === "C") {
|
|
8691
|
-
return
|
|
9864
|
+
return BDT_EPOCH_MS5 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3 + BDT_MINUS_GPST_MS;
|
|
8692
9865
|
}
|
|
8693
|
-
return
|
|
9866
|
+
return GPS_EPOCH_MS17 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3;
|
|
8694
9867
|
}
|
|
8695
9868
|
function almanacSatPosition(alm, timeMs) {
|
|
8696
9869
|
const GM = alm.system === "E" ? GM_GAL : alm.system === "C" ? GM_BDS : GM_GPS;
|
|
@@ -9199,10 +10372,10 @@ function selectBest(ephs, timeMs) {
|
|
|
9199
10372
|
}
|
|
9200
10373
|
return best;
|
|
9201
10374
|
}
|
|
9202
|
-
var
|
|
9203
|
-
var
|
|
10375
|
+
var GPS_EPOCH_MS18 = START_GPS_TIME.getTime();
|
|
10376
|
+
var MS_PER_WEEK12 = 7 * 864e5;
|
|
9204
10377
|
var BDS_EPOCH_MS = START_BDS_TIME.getTime();
|
|
9205
|
-
var GAL_EPOCH_MS =
|
|
10378
|
+
var GAL_EPOCH_MS = GPS_EPOCH_MS18 + 1024 * MS_PER_WEEK12;
|
|
9206
10379
|
function ephInfoToEphemeris(info) {
|
|
9207
10380
|
const sys = info.prn.charAt(0);
|
|
9208
10381
|
if (sys === "R") {
|
|
@@ -9253,11 +10426,11 @@ function ephInfoToEphemeris(info) {
|
|
|
9253
10426
|
} else if (sys === "E") {
|
|
9254
10427
|
epochMs = GAL_EPOCH_MS;
|
|
9255
10428
|
} else {
|
|
9256
|
-
epochMs =
|
|
9257
|
-
const weeksNow = (info.lastReceived -
|
|
10429
|
+
epochMs = GPS_EPOCH_MS18;
|
|
10430
|
+
const weeksNow = (info.lastReceived - GPS_EPOCH_MS18) / MS_PER_WEEK12;
|
|
9258
10431
|
week += 1024 * Math.round((weeksNow - week) / 1024);
|
|
9259
10432
|
}
|
|
9260
|
-
const tocDate = new Date(epochMs + week *
|
|
10433
|
+
const tocDate = new Date(epochMs + week * MS_PER_WEEK12 + tocSec * 1e3);
|
|
9261
10434
|
return {
|
|
9262
10435
|
system: sys,
|
|
9263
10436
|
prn: info.prn,
|
|
@@ -9682,6 +10855,51 @@ function klobucharDelay(coeffs, latRad, lonRad, azRad, elRad, gpsTowSec) {
|
|
|
9682
10855
|
return F * (5e-9 + amp * (1 - x2 / 2 + x2 * x2 / 24));
|
|
9683
10856
|
}
|
|
9684
10857
|
|
|
10858
|
+
// src/positioning/gim.ts
|
|
10859
|
+
var R_E = 6371e3;
|
|
10860
|
+
var H_ION = 45e4;
|
|
10861
|
+
var F_L1 = 157542e4;
|
|
10862
|
+
var IONO_L1_M_PER_TECU = 403e15 / (F_L1 * F_L1);
|
|
10863
|
+
function tecAtMap(grid, mapIdx, latDeg, lonDeg) {
|
|
10864
|
+
const m = grid.maps[mapIdx];
|
|
10865
|
+
const { lats, lons } = grid;
|
|
10866
|
+
const w = lons.length;
|
|
10867
|
+
const fi = (latDeg - lats[0]) / (lats[lats.length - 1] - lats[0]) * (lats.length - 1);
|
|
10868
|
+
const fj = (lonDeg - lons[0]) / (lons[w - 1] - lons[0]) * (w - 1);
|
|
10869
|
+
const i0 = Math.max(0, Math.min(lats.length - 2, Math.floor(fi)));
|
|
10870
|
+
const j0 = Math.max(0, Math.min(w - 2, Math.floor(fj)));
|
|
10871
|
+
const di = Math.max(0, Math.min(1, fi - i0));
|
|
10872
|
+
const dj = Math.max(0, Math.min(1, fj - j0));
|
|
10873
|
+
return m[i0 * w + j0] * (1 - di) * (1 - dj) + m[i0 * w + j0 + 1] * (1 - di) * dj + m[(i0 + 1) * w + j0] * di * (1 - dj) + m[(i0 + 1) * w + j0 + 1] * di * dj;
|
|
10874
|
+
}
|
|
10875
|
+
function gimVerticalTec(grid, timeMs, latDeg, lonDeg) {
|
|
10876
|
+
const e = grid.epochs;
|
|
10877
|
+
if (e.length === 0 || timeMs < e[0] || timeMs > e[e.length - 1]) return null;
|
|
10878
|
+
let i = 0;
|
|
10879
|
+
while (i < e.length - 2 && e[i + 1] <= timeMs) i++;
|
|
10880
|
+
const span = e[i + 1] - e[i];
|
|
10881
|
+
const f = span > 0 ? (timeMs - e[i]) / span : 0;
|
|
10882
|
+
const a = tecAtMap(grid, i, latDeg, lonDeg);
|
|
10883
|
+
const b = tecAtMap(grid, i + 1, latDeg, lonDeg);
|
|
10884
|
+
if (!Number.isFinite(a) || !Number.isFinite(b)) return null;
|
|
10885
|
+
return a * (1 - f) + b * f;
|
|
10886
|
+
}
|
|
10887
|
+
function gimSlantIonoDelayL1(grid, latRad, lonRad, azRad, elRad, timeMs) {
|
|
10888
|
+
if (elRad <= 0) return null;
|
|
10889
|
+
const sinZp = R_E / (R_E + H_ION) * Math.cos(elRad);
|
|
10890
|
+
const mapping = 1 / Math.sqrt(1 - sinZp * sinZp);
|
|
10891
|
+
const psi = Math.PI / 2 - elRad - Math.asin(sinZp);
|
|
10892
|
+
const latI = Math.asin(
|
|
10893
|
+
Math.sin(latRad) * Math.cos(psi) + Math.cos(latRad) * Math.sin(psi) * Math.cos(azRad)
|
|
10894
|
+
);
|
|
10895
|
+
const lonI = lonRad + Math.asin(Math.sin(psi) * Math.sin(azRad) / Math.cos(latI));
|
|
10896
|
+
const latDeg = latI * 180 / Math.PI;
|
|
10897
|
+
const lonDeg = ((lonI * 180 / Math.PI + 540) % 360 + 360) % 360 - 180;
|
|
10898
|
+
const vtec = gimVerticalTec(grid, timeMs, latDeg, lonDeg);
|
|
10899
|
+
if (vtec === null) return null;
|
|
10900
|
+
return IONO_L1_M_PER_TECU * vtec * mapping;
|
|
10901
|
+
}
|
|
10902
|
+
|
|
9685
10903
|
// src/positioning/lambda.ts
|
|
9686
10904
|
var LOOPMAX = 1e4;
|
|
9687
10905
|
var ROUND = (x) => Math.floor(x + 0.5);
|
|
@@ -10723,10 +11941,17 @@ var PRIMARY_FREQ_HZ = {
|
|
|
10723
11941
|
C: 1561098e3,
|
|
10724
11942
|
R: 1602e6
|
|
10725
11943
|
};
|
|
10726
|
-
var
|
|
10727
|
-
function tropoDelay2(elevationRad) {
|
|
10728
|
-
|
|
10729
|
-
|
|
11944
|
+
var F_L12 = 157542e4;
|
|
11945
|
+
function tropoDelay2(elevationRad, latRad, heightM) {
|
|
11946
|
+
if (elevationRad <= 0) return 0;
|
|
11947
|
+
const h = heightM < 0 ? 0 : heightM > 1e4 ? 1e4 : heightM;
|
|
11948
|
+
const humi = 0.7;
|
|
11949
|
+
const pres = 1013.25 * Math.pow(1 - 22557e-9 * h, 5.2568);
|
|
11950
|
+
const temp = 15 - 65e-4 * h + 273.16;
|
|
11951
|
+
const e = 6.108 * humi * Math.exp((17.15 * temp - 4684) / (temp - 38.45));
|
|
11952
|
+
const zhd = 22768e-7 * pres / (1 - 266e-5 * Math.cos(2 * latRad) - 28e-5 * (h / 1e3));
|
|
11953
|
+
const zwd = 2277e-6 * (1255 / temp + 0.05) * e;
|
|
11954
|
+
return (zhd + zwd) / Math.sin(elevationRad);
|
|
10730
11955
|
}
|
|
10731
11956
|
function sagnac2(pos, travelTimeS) {
|
|
10732
11957
|
const theta = OMEGA_E * travelTimeS;
|
|
@@ -10759,7 +11984,8 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
|
|
|
10759
11984
|
maxIterations = 15,
|
|
10760
11985
|
convergenceM = 1e-4,
|
|
10761
11986
|
tgd = true,
|
|
10762
|
-
iono
|
|
11987
|
+
iono,
|
|
11988
|
+
gim
|
|
10763
11989
|
} = opts;
|
|
10764
11990
|
const gpsTow = (timeMs - GPS_EPOCH_MS_SPP) / 1e3 % 604800;
|
|
10765
11991
|
const all = [...pseudoranges.keys()].filter((p) => ephemerides.has(p));
|
|
@@ -10786,7 +12012,7 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
|
|
|
10786
12012
|
let rows = 0;
|
|
10787
12013
|
for (const k of Object.keys(residuals2)) delete residuals2[k];
|
|
10788
12014
|
const positionSaneIter = x2 * x2 + y2 * y2 + z2 * z2 > 1e12;
|
|
10789
|
-
const [rxLat, rxLon] = positionSaneIter ? ecefToGeodetic(x2, y2, z2) : [0, 0];
|
|
12015
|
+
const [rxLat, rxLon, rxHgt] = positionSaneIter ? ecefToGeodetic(x2, y2, z2) : [0, 0, 0];
|
|
10790
12016
|
for (const prn of prns) {
|
|
10791
12017
|
const psr = pseudoranges.get(prn);
|
|
10792
12018
|
const eph = ephemerides.get(prn);
|
|
@@ -10816,11 +12042,18 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
|
|
|
10816
12042
|
const sinEl = Math.max(Math.sin(elev), 0.1);
|
|
10817
12043
|
weight = sinEl * sinEl;
|
|
10818
12044
|
}
|
|
10819
|
-
const tropo = troposphere && positionSane ? tropoDelay2(elev) : 0;
|
|
12045
|
+
const tropo = troposphere && positionSane ? tropoDelay2(elev, rxLat, rxHgt) : 0;
|
|
10820
12046
|
let ionoM = 0;
|
|
10821
|
-
if (iono && positionSane) {
|
|
10822
|
-
|
|
10823
|
-
|
|
12047
|
+
if ((gim || iono) && positionSane) {
|
|
12048
|
+
let l1M = null;
|
|
12049
|
+
if (gim) l1M = gimSlantIonoDelayL1(gim, rxLat, rxLon, azim, elev, timeMs);
|
|
12050
|
+
if (l1M === null && iono) {
|
|
12051
|
+
l1M = C_LIGHT * klobucharDelay(iono, rxLat, rxLon, azim, elev, gpsTow);
|
|
12052
|
+
}
|
|
12053
|
+
if (l1M !== null) {
|
|
12054
|
+
const f = PRIMARY_FREQ_HZ[sys] ?? F_L12;
|
|
12055
|
+
ionoM = l1M * (F_L12 / f * (F_L12 / f));
|
|
12056
|
+
}
|
|
10824
12057
|
}
|
|
10825
12058
|
const predicted = rho + clk - C_LIGHT * dts + tropo + ionoM;
|
|
10826
12059
|
const v = psr - predicted;
|
|
@@ -13207,6 +14440,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
13207
14440
|
GLO_F2_BASE,
|
|
13208
14441
|
GLO_F2_STEP,
|
|
13209
14442
|
GLO_F3,
|
|
14443
|
+
IONO_L1_M_PER_TECU,
|
|
13210
14444
|
IonoAccumulator,
|
|
13211
14445
|
MILLISECONDS_GPS_TAI,
|
|
13212
14446
|
MILLISECONDS_IN_DAY,
|
|
@@ -13250,6 +14484,10 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
13250
14484
|
analyzeQuality,
|
|
13251
14485
|
applyHelmert,
|
|
13252
14486
|
applyIonoDcb,
|
|
14487
|
+
binexCrc16,
|
|
14488
|
+
binexCrc32,
|
|
14489
|
+
binexCsum8,
|
|
14490
|
+
binexRecords,
|
|
13253
14491
|
buildGloChannelMap,
|
|
13254
14492
|
buildObsIndices,
|
|
13255
14493
|
clampUnit,
|
|
@@ -13270,6 +14508,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
13270
14508
|
crxDecompress,
|
|
13271
14509
|
crxRepair,
|
|
13272
14510
|
dateToEpoch,
|
|
14511
|
+
decodeBinexEph,
|
|
13273
14512
|
decodeEphemeris,
|
|
13274
14513
|
decodeMsmFull,
|
|
13275
14514
|
deg2dms,
|
|
@@ -13291,6 +14530,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
13291
14530
|
geodeticToUtm,
|
|
13292
14531
|
getAer,
|
|
13293
14532
|
getBdsTime,
|
|
14533
|
+
getBnxi,
|
|
13294
14534
|
getDateFromBdsTime,
|
|
13295
14535
|
getDateFromDayOfWeek,
|
|
13296
14536
|
getDateFromDayOfYear,
|
|
@@ -13342,6 +14582,8 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
13342
14582
|
getUtcDate,
|
|
13343
14583
|
getWeekNumber,
|
|
13344
14584
|
getWeekOfYear,
|
|
14585
|
+
gimSlantIonoDelayL1,
|
|
14586
|
+
gimVerticalTec,
|
|
13345
14587
|
gloFreq,
|
|
13346
14588
|
glonassAlmanacEpochMs,
|
|
13347
14589
|
glonassAlmanacPosition,
|
|
@@ -13362,6 +14604,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
13362
14604
|
padL,
|
|
13363
14605
|
padR,
|
|
13364
14606
|
parseAntex,
|
|
14607
|
+
parseBinex,
|
|
13365
14608
|
parseCrxDataLine,
|
|
13366
14609
|
parseIonex,
|
|
13367
14610
|
parseNavFile,
|
|
@@ -13381,6 +14624,8 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
13381
14624
|
parseSinexBiasDcb,
|
|
13382
14625
|
parseSourcetable,
|
|
13383
14626
|
parseSp3,
|
|
14627
|
+
parseTrimble,
|
|
14628
|
+
parseTrimbleNav,
|
|
13384
14629
|
parseUbxCnav,
|
|
13385
14630
|
parseUbxIonoUtc,
|
|
13386
14631
|
parseUbxNav,
|
|
@@ -13411,6 +14656,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
13411
14656
|
systemName,
|
|
13412
14657
|
toRtkEpoch,
|
|
13413
14658
|
transformFrame,
|
|
14659
|
+
trimbleFrames,
|
|
13414
14660
|
ubxFrames,
|
|
13415
14661
|
updateStationMeta,
|
|
13416
14662
|
updateStreamStats,
|