gnss-js 1.15.0 → 1.17.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-I4UV45NT.js → chunk-7QR2KPDU.js} +197 -148
- package/dist/chunk-IG5CDNDS.js +245 -0
- package/dist/chunk-REYOYF7O.js +147 -0
- package/dist/{chunk-BEQSEJMU.js → chunk-ZNCQNHNI.js} +36 -0
- package/dist/index.cjs +532 -181
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +18 -5
- package/dist/novatel.cjs +187 -11
- package/dist/novatel.d.cts +36 -13
- package/dist/novatel.d.ts +36 -13
- package/dist/novatel.js +2 -1
- package/dist/sbf.cjs +41 -2
- package/dist/sbf.d.cts +58 -1
- package/dist/sbf.d.ts +58 -1
- package/dist/sbf.js +9 -3
- package/dist/ubx.cjs +297 -29
- package/dist/ubx.d.cts +121 -1
- package/dist/ubx.d.ts +121 -1
- package/dist/ubx.js +10 -3
- package/package.json +1 -1
- package/dist/chunk-5IXK25MX.js +0 -116
package/dist/index.cjs
CHANGED
|
@@ -222,11 +222,14 @@ __export(src_exports, {
|
|
|
222
222
|
parseNovatelRange: () => parseNovatelRange,
|
|
223
223
|
parseRinexStream: () => parseRinexStream,
|
|
224
224
|
parseSbfAlmanac: () => parseSbfAlmanac,
|
|
225
|
+
parseSbfIonoUtc: () => parseSbfIonoUtc,
|
|
225
226
|
parseSbfMeas: () => parseSbfMeas,
|
|
226
227
|
parseSbfNav: () => parseSbfNav,
|
|
227
228
|
parseSinexBiasDcb: () => parseSinexBiasDcb,
|
|
228
229
|
parseSourcetable: () => parseSourcetable,
|
|
229
230
|
parseSp3: () => parseSp3,
|
|
231
|
+
parseUbxIonoUtc: () => parseUbxIonoUtc,
|
|
232
|
+
parseUbxNav: () => parseUbxNav,
|
|
230
233
|
parseUbxRawx: () => parseUbxRawx,
|
|
231
234
|
phiAltBOC: () => phiAltBOC,
|
|
232
235
|
phiBOCc: () => phiBOCc,
|
|
@@ -240,6 +243,8 @@ __export(src_exports, {
|
|
|
240
243
|
rhumbLine: () => rhumbLine,
|
|
241
244
|
rtcm3Constellation: () => rtcm3Constellation,
|
|
242
245
|
satClockCorrection: () => satClockCorrection,
|
|
246
|
+
sbfCrc16: () => crc16,
|
|
247
|
+
scanSbfFrames: () => scanSbfFrames,
|
|
243
248
|
selectEphemeris: () => selectEphemeris,
|
|
244
249
|
setGloFreqNumber: () => setGloFreqNumber,
|
|
245
250
|
setRtcm3DebugHandler: () => setRtcm3DebugHandler,
|
|
@@ -249,6 +254,7 @@ __export(src_exports, {
|
|
|
249
254
|
systemCmp: () => systemCmp,
|
|
250
255
|
systemName: () => systemName,
|
|
251
256
|
transformFrame: () => transformFrame,
|
|
257
|
+
ubxFrames: () => ubxFrames,
|
|
252
258
|
updateStationMeta: () => updateStationMeta,
|
|
253
259
|
updateStreamStats: () => updateStreamStats,
|
|
254
260
|
verifyChecksum: () => verifyChecksum,
|
|
@@ -4598,8 +4604,288 @@ function updateStreamStats(stats, frames, rawBytes) {
|
|
|
4598
4604
|
}
|
|
4599
4605
|
}
|
|
4600
4606
|
|
|
4601
|
-
// src/ubx/
|
|
4607
|
+
// src/ubx/frame.ts
|
|
4608
|
+
function* ubxFrames(data, stats = { badChecksums: 0 }) {
|
|
4609
|
+
let i = 0;
|
|
4610
|
+
while (i + 8 <= data.length) {
|
|
4611
|
+
if (data[i] !== 181 || data[i + 1] !== 98) {
|
|
4612
|
+
i++;
|
|
4613
|
+
continue;
|
|
4614
|
+
}
|
|
4615
|
+
const len = data[i + 4] | data[i + 5] << 8;
|
|
4616
|
+
const end = i + 6 + len + 2;
|
|
4617
|
+
if (end > data.length) break;
|
|
4618
|
+
let ckA = 0;
|
|
4619
|
+
let ckB = 0;
|
|
4620
|
+
for (let j = i + 2; j < i + 6 + len; j++) {
|
|
4621
|
+
ckA = ckA + data[j] & 255;
|
|
4622
|
+
ckB = ckB + ckA & 255;
|
|
4623
|
+
}
|
|
4624
|
+
if (ckA !== data[i + 6 + len] || ckB !== data[i + 7 + len]) {
|
|
4625
|
+
stats.badChecksums++;
|
|
4626
|
+
i++;
|
|
4627
|
+
continue;
|
|
4628
|
+
}
|
|
4629
|
+
yield {
|
|
4630
|
+
msgClass: data[i + 2],
|
|
4631
|
+
msgId: data[i + 3],
|
|
4632
|
+
payload: data.subarray(i + 6, i + 6 + len),
|
|
4633
|
+
payloadStart: i + 6
|
|
4634
|
+
};
|
|
4635
|
+
i = end;
|
|
4636
|
+
}
|
|
4637
|
+
}
|
|
4638
|
+
|
|
4639
|
+
// src/navbits/index.ts
|
|
4640
|
+
var GPS_PI = 3.1415926535898;
|
|
4602
4641
|
var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
|
|
4642
|
+
var SEC_PER_WEEK = 7 * 86400;
|
|
4643
|
+
function getBitU(buff, pos, len) {
|
|
4644
|
+
let bits = 0;
|
|
4645
|
+
for (let i = pos; i < pos + len; i++) {
|
|
4646
|
+
bits = bits * 2 + (buff[i >> 3] >> 7 - (i & 7) & 1);
|
|
4647
|
+
}
|
|
4648
|
+
return bits;
|
|
4649
|
+
}
|
|
4650
|
+
function getBitS(buff, pos, len) {
|
|
4651
|
+
const bits = getBitU(buff, pos, len);
|
|
4652
|
+
if (len <= 0 || bits < 2 ** (len - 1)) return bits;
|
|
4653
|
+
return bits - 2 ** len;
|
|
4654
|
+
}
|
|
4655
|
+
function setBitU(buff, pos, len, data) {
|
|
4656
|
+
let mask = 2 ** (len - 1);
|
|
4657
|
+
for (let i = pos; i < pos + len; i++, mask /= 2) {
|
|
4658
|
+
if (data >= mask) {
|
|
4659
|
+
buff[i >> 3] |= 1 << 7 - (i & 7);
|
|
4660
|
+
data -= mask;
|
|
4661
|
+
} else {
|
|
4662
|
+
buff[i >> 3] &= ~(1 << 7 - (i & 7));
|
|
4663
|
+
}
|
|
4664
|
+
}
|
|
4665
|
+
}
|
|
4666
|
+
function decodeGpsLnavFrame(subframes, opts = {}) {
|
|
4667
|
+
if (subframes.length < 90) return null;
|
|
4668
|
+
const b = subframes;
|
|
4669
|
+
let i = 24;
|
|
4670
|
+
const tow1 = getBitU(b, i, 17) * 6;
|
|
4671
|
+
i += 17 + 2;
|
|
4672
|
+
const id1 = getBitU(b, i, 3);
|
|
4673
|
+
i += 3 + 2;
|
|
4674
|
+
const week10 = getBitU(b, i, 10);
|
|
4675
|
+
i += 10;
|
|
4676
|
+
i += 2;
|
|
4677
|
+
i += 4;
|
|
4678
|
+
const svHealth = getBitU(b, i, 6);
|
|
4679
|
+
i += 6;
|
|
4680
|
+
const iodc0 = getBitU(b, i, 2);
|
|
4681
|
+
i += 2;
|
|
4682
|
+
i += 1 + 87;
|
|
4683
|
+
const tgdRaw = getBitS(b, i, 8);
|
|
4684
|
+
i += 8;
|
|
4685
|
+
const iodc1 = getBitU(b, i, 8);
|
|
4686
|
+
i += 8;
|
|
4687
|
+
const tocSec = getBitU(b, i, 16) * 16;
|
|
4688
|
+
i += 16;
|
|
4689
|
+
const af2 = getBitS(b, i, 8) * 2 ** -55;
|
|
4690
|
+
i += 8;
|
|
4691
|
+
const af1 = getBitS(b, i, 16) * 2 ** -43;
|
|
4692
|
+
i += 16;
|
|
4693
|
+
const af0 = getBitS(b, i, 22) * 2 ** -31;
|
|
4694
|
+
i = 240 + 24;
|
|
4695
|
+
i += 17 + 2;
|
|
4696
|
+
const id2 = getBitU(b, i, 3);
|
|
4697
|
+
i += 3 + 2;
|
|
4698
|
+
const iode = getBitU(b, i, 8);
|
|
4699
|
+
i += 8;
|
|
4700
|
+
const crs = getBitS(b, i, 16) * 2 ** -5;
|
|
4701
|
+
i += 16;
|
|
4702
|
+
const deltaN = getBitS(b, i, 16) * 2 ** -43 * GPS_PI;
|
|
4703
|
+
i += 16;
|
|
4704
|
+
const m0 = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
4705
|
+
i += 32;
|
|
4706
|
+
const cuc = getBitS(b, i, 16) * 2 ** -29;
|
|
4707
|
+
i += 16;
|
|
4708
|
+
const e = getBitU(b, i, 32) * 2 ** -33;
|
|
4709
|
+
i += 32;
|
|
4710
|
+
const cus = getBitS(b, i, 16) * 2 ** -29;
|
|
4711
|
+
i += 16;
|
|
4712
|
+
const sqrtA = getBitU(b, i, 32) * 2 ** -19;
|
|
4713
|
+
i += 32;
|
|
4714
|
+
const toes = getBitU(b, i, 16) * 16;
|
|
4715
|
+
i = 480 + 24;
|
|
4716
|
+
i += 17 + 2;
|
|
4717
|
+
const id3 = getBitU(b, i, 3);
|
|
4718
|
+
i += 3 + 2;
|
|
4719
|
+
const cic = getBitS(b, i, 16) * 2 ** -29;
|
|
4720
|
+
i += 16;
|
|
4721
|
+
const omega0 = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
4722
|
+
i += 32;
|
|
4723
|
+
const cis = getBitS(b, i, 16) * 2 ** -29;
|
|
4724
|
+
i += 16;
|
|
4725
|
+
const i0 = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
4726
|
+
i += 32;
|
|
4727
|
+
const crc = getBitS(b, i, 16) * 2 ** -5;
|
|
4728
|
+
i += 16;
|
|
4729
|
+
const omega = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
4730
|
+
i += 32;
|
|
4731
|
+
const omegaDot = getBitS(b, i, 24) * 2 ** -43 * GPS_PI;
|
|
4732
|
+
i += 24;
|
|
4733
|
+
const iode3 = getBitU(b, i, 8);
|
|
4734
|
+
i += 8;
|
|
4735
|
+
const idot = getBitS(b, i, 14) * 2 ** -43 * GPS_PI;
|
|
4736
|
+
const iodc = iodc0 * 256 + iodc1;
|
|
4737
|
+
if (id1 !== 1 || id2 !== 2 || id3 !== 3) return null;
|
|
4738
|
+
if (iode3 !== iode || iode !== (iodc & 255)) return null;
|
|
4739
|
+
const ref = opts.refWeek ?? Math.floor((Date.now() - GPS_EPOCH_MS) / 1e3 / SEC_PER_WEEK);
|
|
4740
|
+
let week = week10 + 1024 * Math.round((ref - week10) / 1024);
|
|
4741
|
+
if (toes < tow1 - 302400) week++;
|
|
4742
|
+
else if (toes > tow1 + 302400) week--;
|
|
4743
|
+
const prn = opts.prn ?? "G00";
|
|
4744
|
+
const tocDate = new Date(
|
|
4745
|
+
GPS_EPOCH_MS + (week * SEC_PER_WEEK + tocSec) * 1e3
|
|
4746
|
+
);
|
|
4747
|
+
return {
|
|
4748
|
+
system: prn[0] === "J" ? "J" : "G",
|
|
4749
|
+
prn,
|
|
4750
|
+
tocDate,
|
|
4751
|
+
// Same seconds-of-week convention as parseNavFile (rinex/nav.ts).
|
|
4752
|
+
toc: tocDate.getTime() / 1e3 % SEC_PER_WEEK,
|
|
4753
|
+
af0,
|
|
4754
|
+
af1,
|
|
4755
|
+
af2,
|
|
4756
|
+
iode,
|
|
4757
|
+
crs,
|
|
4758
|
+
deltaN,
|
|
4759
|
+
m0,
|
|
4760
|
+
cuc,
|
|
4761
|
+
e,
|
|
4762
|
+
cus,
|
|
4763
|
+
sqrtA,
|
|
4764
|
+
toe: toes,
|
|
4765
|
+
cic,
|
|
4766
|
+
omega0,
|
|
4767
|
+
cis,
|
|
4768
|
+
i0,
|
|
4769
|
+
crc,
|
|
4770
|
+
omega,
|
|
4771
|
+
omegaDot,
|
|
4772
|
+
idot,
|
|
4773
|
+
week,
|
|
4774
|
+
svHealth,
|
|
4775
|
+
tgd: tgdRaw === -128 ? 0 : tgdRaw * 2 ** -31
|
|
4776
|
+
// IS-GPS-200: -128 reserved
|
|
4777
|
+
};
|
|
4778
|
+
}
|
|
4779
|
+
|
|
4780
|
+
// src/ubx/nav.ts
|
|
4781
|
+
var PREAMB_CNAV = 139;
|
|
4782
|
+
function readLnavSubframe(view, f) {
|
|
4783
|
+
const p = f.payload;
|
|
4784
|
+
if (p.length < 8) return null;
|
|
4785
|
+
const gnssId = p[0];
|
|
4786
|
+
const svId = p[1];
|
|
4787
|
+
let prn;
|
|
4788
|
+
if (gnssId === 0 && svId >= 1 && svId <= 32) {
|
|
4789
|
+
prn = `G${String(svId).padStart(2, "0")}`;
|
|
4790
|
+
} else if (gnssId === 5 && svId >= 1 && svId <= 10) {
|
|
4791
|
+
if (p.length === 44) return null;
|
|
4792
|
+
prn = `J${String(svId).padStart(2, "0")}`;
|
|
4793
|
+
} else {
|
|
4794
|
+
return null;
|
|
4795
|
+
}
|
|
4796
|
+
if (p.length < 8 + 40) return null;
|
|
4797
|
+
const base = f.payloadStart + 8;
|
|
4798
|
+
if (view.getUint32(base, true) >>> 24 === PREAMB_CNAV) return null;
|
|
4799
|
+
const buff = new Uint8Array(30);
|
|
4800
|
+
for (let k = 0; k < 10; k++) {
|
|
4801
|
+
const dwrd = view.getUint32(base + 4 * k, true);
|
|
4802
|
+
setBitU(buff, 24 * k, 24, dwrd >>> 6 & 16777215);
|
|
4803
|
+
}
|
|
4804
|
+
return { prn, gnssId, svId, buff, id: getBitU(buff, 43, 3) };
|
|
4805
|
+
}
|
|
4806
|
+
function parseUbxNav(data, opts = {}) {
|
|
4807
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
4808
|
+
const ephemerides = [];
|
|
4809
|
+
let badParity = 0;
|
|
4810
|
+
let refWeek = opts.refWeek;
|
|
4811
|
+
if (refWeek === void 0) {
|
|
4812
|
+
for (const f of ubxFrames(data)) {
|
|
4813
|
+
if (f.msgClass === 2 && f.msgId === 21 && f.payload.length >= 16) {
|
|
4814
|
+
const week = view.getUint16(f.payloadStart + 8, true);
|
|
4815
|
+
if (week > 0) {
|
|
4816
|
+
refWeek = week;
|
|
4817
|
+
break;
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
4821
|
+
}
|
|
4822
|
+
if (refWeek === void 0) return { ephemerides, badParity };
|
|
4823
|
+
const subframes = /* @__PURE__ */ new Map();
|
|
4824
|
+
const last = /* @__PURE__ */ new Map();
|
|
4825
|
+
for (const f of ubxFrames(data)) {
|
|
4826
|
+
if (f.msgClass !== 2 || f.msgId !== 19) continue;
|
|
4827
|
+
const lnav = readLnavSubframe(view, f);
|
|
4828
|
+
if (!lnav) continue;
|
|
4829
|
+
const { prn, gnssId, svId, buff, id } = lnav;
|
|
4830
|
+
if (id < 1 || id > 5) {
|
|
4831
|
+
badParity++;
|
|
4832
|
+
continue;
|
|
4833
|
+
}
|
|
4834
|
+
if (id > 3) continue;
|
|
4835
|
+
const key = gnssId * 256 + svId;
|
|
4836
|
+
let sf = subframes.get(key);
|
|
4837
|
+
if (!sf) {
|
|
4838
|
+
sf = { buf: new Uint8Array(90), have: 0 };
|
|
4839
|
+
subframes.set(key, sf);
|
|
4840
|
+
}
|
|
4841
|
+
sf.buf.set(buff, (id - 1) * 30);
|
|
4842
|
+
sf.have |= 1 << id - 1;
|
|
4843
|
+
if (id !== 3 || sf.have !== 7) continue;
|
|
4844
|
+
const eph = decodeGpsLnavFrame(sf.buf, { prn, refWeek });
|
|
4845
|
+
if (!eph) {
|
|
4846
|
+
badParity++;
|
|
4847
|
+
continue;
|
|
4848
|
+
}
|
|
4849
|
+
const prev = last.get(prn);
|
|
4850
|
+
if (prev && prev.iode === eph.iode && prev.tocDate.getTime() === eph.tocDate.getTime()) {
|
|
4851
|
+
continue;
|
|
4852
|
+
}
|
|
4853
|
+
last.set(prn, eph);
|
|
4854
|
+
ephemerides.push(eph);
|
|
4855
|
+
}
|
|
4856
|
+
return { ephemerides, badParity };
|
|
4857
|
+
}
|
|
4858
|
+
|
|
4859
|
+
// src/ubx/iono.ts
|
|
4860
|
+
function parseUbxIonoUtc(data) {
|
|
4861
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
4862
|
+
const ionoCorrections = {};
|
|
4863
|
+
let leapSeconds = null;
|
|
4864
|
+
for (const f of ubxFrames(data)) {
|
|
4865
|
+
if (f.msgClass !== 2 || f.msgId !== 19) continue;
|
|
4866
|
+
const sf = readLnavSubframe(view, f);
|
|
4867
|
+
if (!sf || sf.gnssId !== 0 || sf.id !== 4) continue;
|
|
4868
|
+
const b = sf.buff;
|
|
4869
|
+
if (getBitU(b, 48, 2) !== 1 || getBitU(b, 50, 6) !== 56) continue;
|
|
4870
|
+
ionoCorrections["GPSA"] = [
|
|
4871
|
+
getBitS(b, 56, 8) * 2 ** -30,
|
|
4872
|
+
getBitS(b, 64, 8) * 2 ** -27,
|
|
4873
|
+
getBitS(b, 72, 8) * 2 ** -24,
|
|
4874
|
+
getBitS(b, 80, 8) * 2 ** -24
|
|
4875
|
+
];
|
|
4876
|
+
ionoCorrections["GPSB"] = [
|
|
4877
|
+
getBitS(b, 88, 8) * 2 ** 11,
|
|
4878
|
+
getBitS(b, 96, 8) * 2 ** 14,
|
|
4879
|
+
getBitS(b, 104, 8) * 2 ** 16,
|
|
4880
|
+
getBitS(b, 112, 8) * 2 ** 16
|
|
4881
|
+
];
|
|
4882
|
+
leapSeconds = getBitS(b, 192, 8);
|
|
4883
|
+
}
|
|
4884
|
+
return { ionoCorrections, leapSeconds };
|
|
4885
|
+
}
|
|
4886
|
+
|
|
4887
|
+
// src/ubx/index.ts
|
|
4888
|
+
var GPS_EPOCH_MS2 = Date.UTC(1980, 0, 6);
|
|
4603
4889
|
var MS_PER_WEEK2 = 7 * 864e5;
|
|
4604
4890
|
var SIGNALS = {
|
|
4605
4891
|
0: { 0: ["G", "1C"], 3: ["G", "2X"], 4: ["G", "2X"] },
|
|
@@ -4639,33 +4925,14 @@ function parseUbxRawx(data) {
|
|
|
4639
4925
|
const epochs = [];
|
|
4640
4926
|
const messageCounts = {};
|
|
4641
4927
|
const obsCodes = {};
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
i++;
|
|
4647
|
-
continue;
|
|
4648
|
-
}
|
|
4649
|
-
const cls = data[i + 2];
|
|
4650
|
-
const id = data[i + 3];
|
|
4651
|
-
const len = data[i + 4] | data[i + 5] << 8;
|
|
4652
|
-
const end = i + 6 + len + 2;
|
|
4653
|
-
if (end > data.length) break;
|
|
4654
|
-
let ckA = 0;
|
|
4655
|
-
let ckB = 0;
|
|
4656
|
-
for (let j = i + 2; j < i + 6 + len; j++) {
|
|
4657
|
-
ckA = ckA + data[j] & 255;
|
|
4658
|
-
ckB = ckB + ckA & 255;
|
|
4659
|
-
}
|
|
4660
|
-
if (ckA !== data[i + 6 + len] || ckB !== data[i + 7 + len]) {
|
|
4661
|
-
badChecksums++;
|
|
4662
|
-
i++;
|
|
4663
|
-
continue;
|
|
4664
|
-
}
|
|
4928
|
+
const stats = { badChecksums: 0 };
|
|
4929
|
+
for (const frame of ubxFrames(data, stats)) {
|
|
4930
|
+
const { msgClass: cls, msgId: id } = frame;
|
|
4931
|
+
const len = frame.payload.length;
|
|
4665
4932
|
const key = `${cls.toString(16).padStart(2, "0")}-${id.toString(16).padStart(2, "0")}`;
|
|
4666
4933
|
messageCounts[key] = (messageCounts[key] ?? 0) + 1;
|
|
4667
4934
|
if (cls === 2 && id === 21 && len >= 16) {
|
|
4668
|
-
const p =
|
|
4935
|
+
const p = frame.payloadStart;
|
|
4669
4936
|
const rcvTow = view.getFloat64(p, true);
|
|
4670
4937
|
const week = view.getUint16(p + 8, true);
|
|
4671
4938
|
const leapS = view.getInt8(p + 10);
|
|
@@ -4701,14 +4968,13 @@ function parseUbxRawx(data) {
|
|
|
4701
4968
|
if (!codes.includes(sig[1])) codes.push(sig[1]);
|
|
4702
4969
|
}
|
|
4703
4970
|
epochs.push({
|
|
4704
|
-
timeMs:
|
|
4971
|
+
timeMs: GPS_EPOCH_MS2 + week * MS_PER_WEEK2 + Math.round(rcvTow * 1e3),
|
|
4705
4972
|
leapS: leapValid ? leapS : null,
|
|
4706
4973
|
meas
|
|
4707
4974
|
});
|
|
4708
4975
|
}
|
|
4709
|
-
i = end;
|
|
4710
4976
|
}
|
|
4711
|
-
return { epochs, messageCounts, obsCodes, badChecksums };
|
|
4977
|
+
return { epochs, messageCounts, obsCodes, badChecksums: stats.badChecksums };
|
|
4712
4978
|
}
|
|
4713
4979
|
|
|
4714
4980
|
// src/sbf/frame.ts
|
|
@@ -4773,10 +5039,10 @@ function svidToPrn(svid) {
|
|
|
4773
5039
|
|
|
4774
5040
|
// src/sbf/nav.ts
|
|
4775
5041
|
var PI2 = Math.PI;
|
|
4776
|
-
var
|
|
5042
|
+
var GPS_EPOCH_MS3 = Date.UTC(1980, 0, 6);
|
|
4777
5043
|
var BDT_EPOCH_MS = Date.UTC(2006, 0, 1);
|
|
4778
|
-
var
|
|
4779
|
-
var MS_PER_WEEK3 =
|
|
5044
|
+
var SEC_PER_WEEK2 = 7 * 86400;
|
|
5045
|
+
var MS_PER_WEEK3 = SEC_PER_WEEK2 * 1e3;
|
|
4780
5046
|
var F4_DNU = -2e10;
|
|
4781
5047
|
var U4_DNU = 4294967295;
|
|
4782
5048
|
function adjustWeek(refWeek, wn, mod) {
|
|
@@ -4785,8 +5051,8 @@ function adjustWeek(refWeek, wn, mod) {
|
|
|
4785
5051
|
if (offset < -(mod / 2 - 1)) offset += mod;
|
|
4786
5052
|
return refWeek - offset;
|
|
4787
5053
|
}
|
|
4788
|
-
var gpsMs = (week, sec) =>
|
|
4789
|
-
var sowOf = (dateMs) => dateMs / 1e3 %
|
|
5054
|
+
var gpsMs = (week, sec) => GPS_EPOCH_MS3 + week * MS_PER_WEEK3 + sec * 1e3;
|
|
5055
|
+
var sowOf = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK2;
|
|
4790
5056
|
function decodeGpsQzsNav(view, b, sys) {
|
|
4791
5057
|
const svid = view.getUint8(b + 14);
|
|
4792
5058
|
const prn = sys === "G" ? svid : svid - 180;
|
|
@@ -4935,7 +5201,7 @@ function decodeGloNav(view, b) {
|
|
|
4935
5201
|
const tocDate = new Date(toeGpsMs - leapMs);
|
|
4936
5202
|
const tofGpsMs = gpsMs(wnc, 0) + view.getUint32(b + 8, true);
|
|
4937
5203
|
const tofLeapMs = getGpsLeap(new Date(tofGpsMs)) * 1e3;
|
|
4938
|
-
const messageFrameTime = (tofGpsMs - tofLeapMs -
|
|
5204
|
+
const messageFrameTime = (tofGpsMs - tofLeapMs - GPS_EPOCH_MS3) / 1e3 % SEC_PER_WEEK2;
|
|
4939
5205
|
return {
|
|
4940
5206
|
system: "R",
|
|
4941
5207
|
prn,
|
|
@@ -5080,9 +5346,42 @@ function parseSbfAlmanac(data) {
|
|
|
5080
5346
|
return { almanacs, badCrc };
|
|
5081
5347
|
}
|
|
5082
5348
|
|
|
5349
|
+
// src/sbf/iono.ts
|
|
5350
|
+
var F4_DNU2 = -2e10;
|
|
5351
|
+
function parseSbfIonoUtc(data) {
|
|
5352
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
5353
|
+
const ionoCorrections = {};
|
|
5354
|
+
let leapSeconds = null;
|
|
5355
|
+
const f4s = (b, n) => {
|
|
5356
|
+
const out = [];
|
|
5357
|
+
for (let k = 0; k < n; k++) {
|
|
5358
|
+
const v = view.getFloat32(b + 4 * k, true);
|
|
5359
|
+
if (v === F4_DNU2) return null;
|
|
5360
|
+
out.push(v);
|
|
5361
|
+
}
|
|
5362
|
+
return out;
|
|
5363
|
+
};
|
|
5364
|
+
scanSbfFrames(data, view, (id, b, len) => {
|
|
5365
|
+
if ((id === 5893 || id === 4120) && len >= 48) {
|
|
5366
|
+
const alpha = f4s(b + 16, 4);
|
|
5367
|
+
const beta = f4s(b + 32, 4);
|
|
5368
|
+
if (!alpha || !beta) return;
|
|
5369
|
+
const sys = id === 5893 ? "GPS" : "BDS";
|
|
5370
|
+
ionoCorrections[`${sys}A`] = alpha;
|
|
5371
|
+
ionoCorrections[`${sys}B`] = beta;
|
|
5372
|
+
} else if (id === 4030 && len >= 28) {
|
|
5373
|
+
const ai = f4s(b + 16, 3);
|
|
5374
|
+
if (ai) ionoCorrections["GAL"] = ai;
|
|
5375
|
+
} else if (id === 5894 && len >= 37) {
|
|
5376
|
+
leapSeconds = view.getInt8(b + 33);
|
|
5377
|
+
}
|
|
5378
|
+
});
|
|
5379
|
+
return { ionoCorrections, leapSeconds };
|
|
5380
|
+
}
|
|
5381
|
+
|
|
5083
5382
|
// src/sbf/index.ts
|
|
5084
5383
|
var CLIGHT = 299792458;
|
|
5085
|
-
var
|
|
5384
|
+
var GPS_EPOCH_MS4 = Date.UTC(1980, 0, 6);
|
|
5086
5385
|
var MS_PER_WEEK4 = 7 * 864e5;
|
|
5087
5386
|
var M3_SYS = ["G", "R", "E", "C", "S", "J", "I"];
|
|
5088
5387
|
var M3_PR_BASE = [19e6, 19e6, 22e6, 2e7, 34e6, 34e6, 34e6];
|
|
@@ -5736,7 +6035,7 @@ function parseSbfMeas(data) {
|
|
|
5736
6035
|
const tow = view.getUint32(i + 8, true);
|
|
5737
6036
|
const wnc = view.getUint16(i + 12, true);
|
|
5738
6037
|
if (tow !== 4294967295 && wnc !== 65535) {
|
|
5739
|
-
ensureEpoch(
|
|
6038
|
+
ensureEpoch(GPS_EPOCH_MS4 + wnc * MS_PER_WEEK4 + tow);
|
|
5740
6039
|
if (id === 4109) decodeMeas3Ranges(i, tow);
|
|
5741
6040
|
else if (id === 4110) decodeMeas3CN0(i, len);
|
|
5742
6041
|
else if (id === 4111) decodeMeas3Doppler(i, len);
|
|
@@ -5792,142 +6091,27 @@ function* oem4Frames(data, view, stats) {
|
|
|
5792
6091
|
}
|
|
5793
6092
|
}
|
|
5794
6093
|
|
|
5795
|
-
// src/navbits/index.ts
|
|
5796
|
-
var GPS_PI = 3.1415926535898;
|
|
5797
|
-
var GPS_EPOCH_MS4 = Date.UTC(1980, 0, 6);
|
|
5798
|
-
var SEC_PER_WEEK2 = 7 * 86400;
|
|
5799
|
-
function getBitU(buff, pos, len) {
|
|
5800
|
-
let bits = 0;
|
|
5801
|
-
for (let i = pos; i < pos + len; i++) {
|
|
5802
|
-
bits = bits * 2 + (buff[i >> 3] >> 7 - (i & 7) & 1);
|
|
5803
|
-
}
|
|
5804
|
-
return bits;
|
|
5805
|
-
}
|
|
5806
|
-
function getBitS(buff, pos, len) {
|
|
5807
|
-
const bits = getBitU(buff, pos, len);
|
|
5808
|
-
if (len <= 0 || bits < 2 ** (len - 1)) return bits;
|
|
5809
|
-
return bits - 2 ** len;
|
|
5810
|
-
}
|
|
5811
|
-
function decodeGpsLnavFrame(subframes, opts = {}) {
|
|
5812
|
-
if (subframes.length < 90) return null;
|
|
5813
|
-
const b = subframes;
|
|
5814
|
-
let i = 24;
|
|
5815
|
-
const tow1 = getBitU(b, i, 17) * 6;
|
|
5816
|
-
i += 17 + 2;
|
|
5817
|
-
const id1 = getBitU(b, i, 3);
|
|
5818
|
-
i += 3 + 2;
|
|
5819
|
-
const week10 = getBitU(b, i, 10);
|
|
5820
|
-
i += 10;
|
|
5821
|
-
i += 2;
|
|
5822
|
-
i += 4;
|
|
5823
|
-
const svHealth = getBitU(b, i, 6);
|
|
5824
|
-
i += 6;
|
|
5825
|
-
const iodc0 = getBitU(b, i, 2);
|
|
5826
|
-
i += 2;
|
|
5827
|
-
i += 1 + 87;
|
|
5828
|
-
const tgdRaw = getBitS(b, i, 8);
|
|
5829
|
-
i += 8;
|
|
5830
|
-
const iodc1 = getBitU(b, i, 8);
|
|
5831
|
-
i += 8;
|
|
5832
|
-
const tocSec = getBitU(b, i, 16) * 16;
|
|
5833
|
-
i += 16;
|
|
5834
|
-
const af2 = getBitS(b, i, 8) * 2 ** -55;
|
|
5835
|
-
i += 8;
|
|
5836
|
-
const af1 = getBitS(b, i, 16) * 2 ** -43;
|
|
5837
|
-
i += 16;
|
|
5838
|
-
const af0 = getBitS(b, i, 22) * 2 ** -31;
|
|
5839
|
-
i = 240 + 24;
|
|
5840
|
-
i += 17 + 2;
|
|
5841
|
-
const id2 = getBitU(b, i, 3);
|
|
5842
|
-
i += 3 + 2;
|
|
5843
|
-
const iode = getBitU(b, i, 8);
|
|
5844
|
-
i += 8;
|
|
5845
|
-
const crs = getBitS(b, i, 16) * 2 ** -5;
|
|
5846
|
-
i += 16;
|
|
5847
|
-
const deltaN = getBitS(b, i, 16) * 2 ** -43 * GPS_PI;
|
|
5848
|
-
i += 16;
|
|
5849
|
-
const m0 = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
5850
|
-
i += 32;
|
|
5851
|
-
const cuc = getBitS(b, i, 16) * 2 ** -29;
|
|
5852
|
-
i += 16;
|
|
5853
|
-
const e = getBitU(b, i, 32) * 2 ** -33;
|
|
5854
|
-
i += 32;
|
|
5855
|
-
const cus = getBitS(b, i, 16) * 2 ** -29;
|
|
5856
|
-
i += 16;
|
|
5857
|
-
const sqrtA = getBitU(b, i, 32) * 2 ** -19;
|
|
5858
|
-
i += 32;
|
|
5859
|
-
const toes = getBitU(b, i, 16) * 16;
|
|
5860
|
-
i = 480 + 24;
|
|
5861
|
-
i += 17 + 2;
|
|
5862
|
-
const id3 = getBitU(b, i, 3);
|
|
5863
|
-
i += 3 + 2;
|
|
5864
|
-
const cic = getBitS(b, i, 16) * 2 ** -29;
|
|
5865
|
-
i += 16;
|
|
5866
|
-
const omega0 = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
5867
|
-
i += 32;
|
|
5868
|
-
const cis = getBitS(b, i, 16) * 2 ** -29;
|
|
5869
|
-
i += 16;
|
|
5870
|
-
const i0 = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
5871
|
-
i += 32;
|
|
5872
|
-
const crc = getBitS(b, i, 16) * 2 ** -5;
|
|
5873
|
-
i += 16;
|
|
5874
|
-
const omega = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
5875
|
-
i += 32;
|
|
5876
|
-
const omegaDot = getBitS(b, i, 24) * 2 ** -43 * GPS_PI;
|
|
5877
|
-
i += 24;
|
|
5878
|
-
const iode3 = getBitU(b, i, 8);
|
|
5879
|
-
i += 8;
|
|
5880
|
-
const idot = getBitS(b, i, 14) * 2 ** -43 * GPS_PI;
|
|
5881
|
-
const iodc = iodc0 * 256 + iodc1;
|
|
5882
|
-
if (id1 !== 1 || id2 !== 2 || id3 !== 3) return null;
|
|
5883
|
-
if (iode3 !== iode || iode !== (iodc & 255)) return null;
|
|
5884
|
-
const ref = opts.refWeek ?? Math.floor((Date.now() - GPS_EPOCH_MS4) / 1e3 / SEC_PER_WEEK2);
|
|
5885
|
-
let week = week10 + 1024 * Math.round((ref - week10) / 1024);
|
|
5886
|
-
if (toes < tow1 - 302400) week++;
|
|
5887
|
-
else if (toes > tow1 + 302400) week--;
|
|
5888
|
-
const prn = opts.prn ?? "G00";
|
|
5889
|
-
const tocDate = new Date(
|
|
5890
|
-
GPS_EPOCH_MS4 + (week * SEC_PER_WEEK2 + tocSec) * 1e3
|
|
5891
|
-
);
|
|
5892
|
-
return {
|
|
5893
|
-
system: prn[0] === "J" ? "J" : "G",
|
|
5894
|
-
prn,
|
|
5895
|
-
tocDate,
|
|
5896
|
-
// Same seconds-of-week convention as parseNavFile (rinex/nav.ts).
|
|
5897
|
-
toc: tocDate.getTime() / 1e3 % SEC_PER_WEEK2,
|
|
5898
|
-
af0,
|
|
5899
|
-
af1,
|
|
5900
|
-
af2,
|
|
5901
|
-
iode,
|
|
5902
|
-
crs,
|
|
5903
|
-
deltaN,
|
|
5904
|
-
m0,
|
|
5905
|
-
cuc,
|
|
5906
|
-
e,
|
|
5907
|
-
cus,
|
|
5908
|
-
sqrtA,
|
|
5909
|
-
toe: toes,
|
|
5910
|
-
cic,
|
|
5911
|
-
omega0,
|
|
5912
|
-
cis,
|
|
5913
|
-
i0,
|
|
5914
|
-
crc,
|
|
5915
|
-
omega,
|
|
5916
|
-
omegaDot,
|
|
5917
|
-
idot,
|
|
5918
|
-
week,
|
|
5919
|
-
svHealth,
|
|
5920
|
-
tgd: tgdRaw === -128 ? 0 : tgdRaw * 2 ** -31
|
|
5921
|
-
// IS-GPS-200: -128 reserved
|
|
5922
|
-
};
|
|
5923
|
-
}
|
|
5924
|
-
|
|
5925
6094
|
// src/novatel/nav.ts
|
|
6095
|
+
var ID_IONUTC = 8;
|
|
5926
6096
|
var ID_RAWEPHEM = 41;
|
|
5927
6097
|
var ID_GLOEPHEMERIS = 723;
|
|
6098
|
+
var ID_GALEPHEMERIS = 1122;
|
|
6099
|
+
var ID_QZSSEPHEMERIS = 1336;
|
|
6100
|
+
var ID_BDSEPHEMERIS = 1696;
|
|
5928
6101
|
var GPS_EPOCH_MS5 = Date.UTC(1980, 0, 6);
|
|
6102
|
+
var BDT_EPOCH_MS2 = Date.UTC(2006, 0, 1);
|
|
5929
6103
|
var SEC_PER_WEEK3 = 7 * 86400;
|
|
5930
6104
|
var SEC_PER_DAY = 86400;
|
|
6105
|
+
var MS_PER_WEEK5 = SEC_PER_WEEK3 * 1e3;
|
|
6106
|
+
var gpsMs2 = (week, sec) => GPS_EPOCH_MS5 + week * MS_PER_WEEK5 + sec * 1e3;
|
|
6107
|
+
var sowOf2 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK3;
|
|
6108
|
+
function nearWeekMs(refMs, sow) {
|
|
6109
|
+
const refWeek = Math.floor((refMs - GPS_EPOCH_MS5) / MS_PER_WEEK5);
|
|
6110
|
+
let ms = gpsMs2(refWeek, sow);
|
|
6111
|
+
if (ms < refMs - MS_PER_WEEK5 / 2) ms += MS_PER_WEEK5;
|
|
6112
|
+
else if (ms > refMs + MS_PER_WEEK5 / 2) ms -= MS_PER_WEEK5;
|
|
6113
|
+
return ms;
|
|
6114
|
+
}
|
|
5931
6115
|
function decodeRawEphem(data, view, p) {
|
|
5932
6116
|
const prn = view.getUint32(p, true);
|
|
5933
6117
|
if (prn < 1 || prn > 32) return null;
|
|
@@ -5973,23 +6157,184 @@ function decodeGloEphemeris(view, p) {
|
|
|
5973
6157
|
freqNum
|
|
5974
6158
|
};
|
|
5975
6159
|
}
|
|
6160
|
+
function decodeGalEphemeris(view, p, headerMs) {
|
|
6161
|
+
const prn = view.getUint32(p, true);
|
|
6162
|
+
if (prn < 1 || prn > 36) return null;
|
|
6163
|
+
const fnav = (view.getUint32(p + 4, true) & 1) !== 0;
|
|
6164
|
+
const svhE1b = view.getUint8(p + 12) & 3;
|
|
6165
|
+
const svhE5a = view.getUint8(p + 13) & 3;
|
|
6166
|
+
const svhE5b = view.getUint8(p + 14) & 3;
|
|
6167
|
+
const dvsE1b = view.getUint8(p + 15) & 1;
|
|
6168
|
+
const dvsE5a = view.getUint8(p + 16) & 1;
|
|
6169
|
+
const dvsE5b = view.getUint8(p + 17) & 1;
|
|
6170
|
+
const iodNav = view.getUint32(p + 20, true);
|
|
6171
|
+
const toes = view.getUint32(p + 24, true);
|
|
6172
|
+
const c = fnav ? p + 148 : p + 176;
|
|
6173
|
+
const tocs = view.getUint32(c, true);
|
|
6174
|
+
const toeMs = nearWeekMs(headerMs, toes);
|
|
6175
|
+
const tocDate = new Date(nearWeekMs(headerMs, tocs));
|
|
6176
|
+
return {
|
|
6177
|
+
fnav,
|
|
6178
|
+
eph: {
|
|
6179
|
+
system: "E",
|
|
6180
|
+
prn: `E${String(prn).padStart(2, "0")}`,
|
|
6181
|
+
toc: sowOf2(tocDate.getTime()),
|
|
6182
|
+
tocDate,
|
|
6183
|
+
af0: view.getFloat64(c + 4, true),
|
|
6184
|
+
af1: view.getFloat64(c + 12, true),
|
|
6185
|
+
af2: view.getFloat64(c + 20, true),
|
|
6186
|
+
iode: iodNav,
|
|
6187
|
+
crs: view.getFloat64(p + 92, true),
|
|
6188
|
+
deltaN: view.getFloat64(p + 36, true),
|
|
6189
|
+
m0: view.getFloat64(p + 44, true),
|
|
6190
|
+
cuc: view.getFloat64(p + 68, true),
|
|
6191
|
+
e: view.getFloat64(p + 52, true),
|
|
6192
|
+
cus: view.getFloat64(p + 76, true),
|
|
6193
|
+
sqrtA: view.getFloat64(p + 28, true),
|
|
6194
|
+
toe: toes,
|
|
6195
|
+
cic: view.getFloat64(p + 100, true),
|
|
6196
|
+
omega0: view.getFloat64(p + 132, true),
|
|
6197
|
+
cis: view.getFloat64(p + 108, true),
|
|
6198
|
+
i0: view.getFloat64(p + 116, true),
|
|
6199
|
+
crc: view.getFloat64(p + 84, true),
|
|
6200
|
+
omega: view.getFloat64(p + 60, true),
|
|
6201
|
+
omegaDot: view.getFloat64(p + 140, true),
|
|
6202
|
+
idot: view.getFloat64(p + 124, true),
|
|
6203
|
+
week: Math.floor((toeMs - GPS_EPOCH_MS5) / MS_PER_WEEK5),
|
|
6204
|
+
// RINEX Galileo SVH bit layout (E1B DVS/HS in bits 0-2, E5a in
|
|
6205
|
+
// 3-5, E5b in 6-8) — same packing as RTKLIB.
|
|
6206
|
+
svHealth: svhE5b << 7 | dvsE5b << 6 | svhE5a << 4 | dvsE5a << 3 | svhE1b << 1 | dvsE1b,
|
|
6207
|
+
tgd: view.getFloat64(p + 204, true)
|
|
6208
|
+
// BGD E5a/E1 (RINEX slot)
|
|
6209
|
+
}
|
|
6210
|
+
};
|
|
6211
|
+
}
|
|
6212
|
+
function decodeBdsEphemeris2(view, p) {
|
|
6213
|
+
const prn = view.getUint32(p, true);
|
|
6214
|
+
if (prn < 1 || prn > 63) return null;
|
|
6215
|
+
const week = view.getUint32(p + 4, true);
|
|
6216
|
+
const health = view.getUint32(p + 16, true) & 1;
|
|
6217
|
+
const tgd1 = view.getFloat64(p + 20, true);
|
|
6218
|
+
const tocs = view.getUint32(p + 40, true);
|
|
6219
|
+
const toes = view.getUint32(p + 72, true);
|
|
6220
|
+
const tocDate = new Date(BDT_EPOCH_MS2 + week * MS_PER_WEEK5 + tocs * 1e3);
|
|
6221
|
+
return {
|
|
6222
|
+
system: "C",
|
|
6223
|
+
prn: `C${String(prn).padStart(2, "0")}`,
|
|
6224
|
+
toc: sowOf2(tocDate.getTime()),
|
|
6225
|
+
tocDate,
|
|
6226
|
+
af0: view.getFloat64(p + 44, true),
|
|
6227
|
+
af1: view.getFloat64(p + 52, true),
|
|
6228
|
+
af2: view.getFloat64(p + 60, true),
|
|
6229
|
+
iode: view.getUint32(p + 68, true),
|
|
6230
|
+
// AODE
|
|
6231
|
+
crs: view.getFloat64(p + 172, true),
|
|
6232
|
+
deltaN: view.getFloat64(p + 100, true),
|
|
6233
|
+
m0: view.getFloat64(p + 108, true),
|
|
6234
|
+
cuc: view.getFloat64(p + 148, true),
|
|
6235
|
+
e: view.getFloat64(p + 84, true),
|
|
6236
|
+
cus: view.getFloat64(p + 156, true),
|
|
6237
|
+
sqrtA: view.getFloat64(p + 76, true),
|
|
6238
|
+
toe: toes,
|
|
6239
|
+
cic: view.getFloat64(p + 180, true),
|
|
6240
|
+
omega0: view.getFloat64(p + 116, true),
|
|
6241
|
+
cis: view.getFloat64(p + 188, true),
|
|
6242
|
+
i0: view.getFloat64(p + 132, true),
|
|
6243
|
+
crc: view.getFloat64(p + 164, true),
|
|
6244
|
+
omega: view.getFloat64(p + 92, true),
|
|
6245
|
+
omegaDot: view.getFloat64(p + 124, true),
|
|
6246
|
+
idot: view.getFloat64(p + 140, true),
|
|
6247
|
+
week,
|
|
6248
|
+
// RINEX BDS week field is the BDT week
|
|
6249
|
+
svHealth: health,
|
|
6250
|
+
tgd: tgd1
|
|
6251
|
+
// TGD1 (B1) — RINEX slot
|
|
6252
|
+
};
|
|
6253
|
+
}
|
|
6254
|
+
function decodeQzssEphemeris2(view, p) {
|
|
6255
|
+
const prn = view.getUint32(p, true);
|
|
6256
|
+
if (prn < 193 || prn > 202) return null;
|
|
6257
|
+
const health = view.getUint32(p + 12, true) & 63;
|
|
6258
|
+
const iode1 = view.getUint32(p + 16, true);
|
|
6259
|
+
const week = view.getUint32(p + 24, true);
|
|
6260
|
+
const toes = view.getFloat64(p + 32, true);
|
|
6261
|
+
const toeMs = gpsMs2(week, toes);
|
|
6262
|
+
const tocs = view.getFloat64(p + 164, true);
|
|
6263
|
+
const tocDate = new Date(nearWeekMs(toeMs, tocs));
|
|
6264
|
+
return {
|
|
6265
|
+
system: "J",
|
|
6266
|
+
prn: `J${String(prn - 192).padStart(2, "0")}`,
|
|
6267
|
+
toc: sowOf2(tocDate.getTime()),
|
|
6268
|
+
tocDate,
|
|
6269
|
+
af0: view.getFloat64(p + 180, true),
|
|
6270
|
+
af1: view.getFloat64(p + 188, true),
|
|
6271
|
+
af2: view.getFloat64(p + 196, true),
|
|
6272
|
+
iode: iode1,
|
|
6273
|
+
crs: view.getFloat64(p + 104, true),
|
|
6274
|
+
deltaN: view.getFloat64(p + 48, true),
|
|
6275
|
+
m0: view.getFloat64(p + 56, true),
|
|
6276
|
+
cuc: view.getFloat64(p + 80, true),
|
|
6277
|
+
e: view.getFloat64(p + 64, true),
|
|
6278
|
+
cus: view.getFloat64(p + 88, true),
|
|
6279
|
+
sqrtA: Math.sqrt(view.getFloat64(p + 40, true)),
|
|
6280
|
+
toe: toes,
|
|
6281
|
+
cic: view.getFloat64(p + 112, true),
|
|
6282
|
+
omega0: view.getFloat64(p + 144, true),
|
|
6283
|
+
cis: view.getFloat64(p + 120, true),
|
|
6284
|
+
i0: view.getFloat64(p + 128, true),
|
|
6285
|
+
crc: view.getFloat64(p + 96, true),
|
|
6286
|
+
omega: view.getFloat64(p + 72, true),
|
|
6287
|
+
omegaDot: view.getFloat64(p + 152, true),
|
|
6288
|
+
idot: view.getFloat64(p + 136, true),
|
|
6289
|
+
week,
|
|
6290
|
+
svHealth: health,
|
|
6291
|
+
tgd: view.getFloat64(p + 172, true)
|
|
6292
|
+
};
|
|
6293
|
+
}
|
|
5976
6294
|
function parseNovatelNav(data) {
|
|
5977
6295
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
5978
6296
|
const stats = { badCrc: 0 };
|
|
5979
6297
|
const ephemerides = [];
|
|
5980
|
-
const
|
|
6298
|
+
const ionoCorrections = {};
|
|
6299
|
+
let leapSeconds = null;
|
|
6300
|
+
const lastKep = /* @__PURE__ */ new Map();
|
|
5981
6301
|
const lastGlo = /* @__PURE__ */ new Map();
|
|
6302
|
+
const pushKepler = (key, eph) => {
|
|
6303
|
+
const prev = lastKep.get(key);
|
|
6304
|
+
if (prev && prev.iode === eph.iode && prev.toe === eph.toe && prev.tocDate.getTime() === eph.tocDate.getTime()) {
|
|
6305
|
+
return;
|
|
6306
|
+
}
|
|
6307
|
+
lastKep.set(key, eph);
|
|
6308
|
+
ephemerides.push(eph);
|
|
6309
|
+
};
|
|
5982
6310
|
for (const frame of oem4Frames(data, view, stats)) {
|
|
5983
6311
|
if (!frame.binary) continue;
|
|
5984
6312
|
if (frame.id === ID_RAWEPHEM && frame.msgLen >= 102) {
|
|
5985
6313
|
const eph = decodeRawEphem(data, view, frame.payload);
|
|
5986
|
-
if (
|
|
5987
|
-
|
|
5988
|
-
if (
|
|
5989
|
-
|
|
6314
|
+
if (eph) pushKepler(eph.prn, eph);
|
|
6315
|
+
} else if (frame.id === ID_GALEPHEMERIS && frame.msgLen >= 220) {
|
|
6316
|
+
if (frame.week === 0) continue;
|
|
6317
|
+
const headerMs = gpsMs2(frame.week, frame.towMs / 1e3);
|
|
6318
|
+
const dec = decodeGalEphemeris(view, frame.payload, headerMs);
|
|
6319
|
+
if (dec)
|
|
6320
|
+
pushKepler(`${dec.eph.prn}:${dec.fnav ? "fnav" : "inav"}`, dec.eph);
|
|
6321
|
+
} else if (frame.id === ID_BDSEPHEMERIS && frame.msgLen >= 196) {
|
|
6322
|
+
const eph = decodeBdsEphemeris2(view, frame.payload);
|
|
6323
|
+
if (eph) pushKepler(eph.prn, eph);
|
|
6324
|
+
} else if (frame.id === ID_QZSSEPHEMERIS && frame.msgLen >= 204) {
|
|
6325
|
+
const eph = decodeQzssEphemeris2(view, frame.payload);
|
|
6326
|
+
if (eph) pushKepler(eph.prn, eph);
|
|
6327
|
+
} else if (frame.id === ID_IONUTC && frame.msgLen >= 108) {
|
|
6328
|
+
const p = frame.payload;
|
|
6329
|
+
const alpha = [];
|
|
6330
|
+
const beta = [];
|
|
6331
|
+
for (let i = 0; i < 4; i++) {
|
|
6332
|
+
alpha.push(view.getFloat64(p + i * 8, true));
|
|
6333
|
+
beta.push(view.getFloat64(p + 32 + i * 8, true));
|
|
5990
6334
|
}
|
|
5991
|
-
|
|
5992
|
-
|
|
6335
|
+
ionoCorrections["GPSA"] = alpha;
|
|
6336
|
+
ionoCorrections["GPSB"] = beta;
|
|
6337
|
+
leapSeconds = view.getInt32(p + 96, true);
|
|
5993
6338
|
} else if (frame.id === ID_GLOEPHEMERIS && frame.msgLen >= 144) {
|
|
5994
6339
|
const eph = decodeGloEphemeris(view, frame.payload);
|
|
5995
6340
|
if (!eph) continue;
|
|
@@ -6001,12 +6346,12 @@ function parseNovatelNav(data) {
|
|
|
6001
6346
|
ephemerides.push(eph);
|
|
6002
6347
|
}
|
|
6003
6348
|
}
|
|
6004
|
-
return { ephemerides, badCrc: stats.badCrc };
|
|
6349
|
+
return { ephemerides, ionoCorrections, leapSeconds, badCrc: stats.badCrc };
|
|
6005
6350
|
}
|
|
6006
6351
|
|
|
6007
6352
|
// src/novatel/index.ts
|
|
6008
6353
|
var GPS_EPOCH_MS6 = Date.UTC(1980, 0, 6);
|
|
6009
|
-
var
|
|
6354
|
+
var MS_PER_WEEK6 = 7 * 864e5;
|
|
6010
6355
|
var HDR = 28;
|
|
6011
6356
|
var ID_RANGE = 43;
|
|
6012
6357
|
var ID_RANGECMP = 140;
|
|
@@ -6175,7 +6520,7 @@ function parseNovatelRange(data) {
|
|
|
6175
6520
|
if (!codes.includes(code)) codes.push(code);
|
|
6176
6521
|
}
|
|
6177
6522
|
epochs.push({
|
|
6178
|
-
timeMs: GPS_EPOCH_MS6 + week *
|
|
6523
|
+
timeMs: GPS_EPOCH_MS6 + week * MS_PER_WEEK6 + towMs,
|
|
6179
6524
|
meas
|
|
6180
6525
|
});
|
|
6181
6526
|
}
|
|
@@ -6227,7 +6572,7 @@ function parseNovatelRange(data) {
|
|
|
6227
6572
|
if (!codes.includes(code)) codes.push(code);
|
|
6228
6573
|
}
|
|
6229
6574
|
epochs.push({
|
|
6230
|
-
timeMs: GPS_EPOCH_MS6 + week *
|
|
6575
|
+
timeMs: GPS_EPOCH_MS6 + week * MS_PER_WEEK6 + towMs,
|
|
6231
6576
|
meas
|
|
6232
6577
|
});
|
|
6233
6578
|
}
|
|
@@ -6587,9 +6932,9 @@ function selectBest(ephs, timeMs) {
|
|
|
6587
6932
|
return best;
|
|
6588
6933
|
}
|
|
6589
6934
|
var GPS_EPOCH_MS7 = START_GPS_TIME.getTime();
|
|
6590
|
-
var
|
|
6935
|
+
var MS_PER_WEEK7 = 7 * 864e5;
|
|
6591
6936
|
var BDS_EPOCH_MS = START_BDS_TIME.getTime();
|
|
6592
|
-
var GAL_EPOCH_MS = GPS_EPOCH_MS7 + 1024 *
|
|
6937
|
+
var GAL_EPOCH_MS = GPS_EPOCH_MS7 + 1024 * MS_PER_WEEK7;
|
|
6593
6938
|
function ephInfoToEphemeris(info) {
|
|
6594
6939
|
const sys = info.prn.charAt(0);
|
|
6595
6940
|
if (sys === "R") {
|
|
@@ -6641,10 +6986,10 @@ function ephInfoToEphemeris(info) {
|
|
|
6641
6986
|
epochMs = GAL_EPOCH_MS;
|
|
6642
6987
|
} else {
|
|
6643
6988
|
epochMs = GPS_EPOCH_MS7;
|
|
6644
|
-
const weeksNow = (info.lastReceived - GPS_EPOCH_MS7) /
|
|
6989
|
+
const weeksNow = (info.lastReceived - GPS_EPOCH_MS7) / MS_PER_WEEK7;
|
|
6645
6990
|
week += 1024 * Math.round((weeksNow - week) / 1024);
|
|
6646
6991
|
}
|
|
6647
|
-
const tocDate = new Date(epochMs + week *
|
|
6992
|
+
const tocDate = new Date(epochMs + week * MS_PER_WEEK7 + tocSec * 1e3);
|
|
6648
6993
|
return {
|
|
6649
6994
|
system: sys,
|
|
6650
6995
|
prn: info.prn,
|
|
@@ -9743,11 +10088,14 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
9743
10088
|
parseNovatelRange,
|
|
9744
10089
|
parseRinexStream,
|
|
9745
10090
|
parseSbfAlmanac,
|
|
10091
|
+
parseSbfIonoUtc,
|
|
9746
10092
|
parseSbfMeas,
|
|
9747
10093
|
parseSbfNav,
|
|
9748
10094
|
parseSinexBiasDcb,
|
|
9749
10095
|
parseSourcetable,
|
|
9750
10096
|
parseSp3,
|
|
10097
|
+
parseUbxIonoUtc,
|
|
10098
|
+
parseUbxNav,
|
|
9751
10099
|
parseUbxRawx,
|
|
9752
10100
|
phiAltBOC,
|
|
9753
10101
|
phiBOCc,
|
|
@@ -9761,6 +10109,8 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
9761
10109
|
rhumbLine,
|
|
9762
10110
|
rtcm3Constellation,
|
|
9763
10111
|
satClockCorrection,
|
|
10112
|
+
sbfCrc16,
|
|
10113
|
+
scanSbfFrames,
|
|
9764
10114
|
selectEphemeris,
|
|
9765
10115
|
setGloFreqNumber,
|
|
9766
10116
|
setRtcm3DebugHandler,
|
|
@@ -9770,6 +10120,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
9770
10120
|
systemCmp,
|
|
9771
10121
|
systemName,
|
|
9772
10122
|
transformFrame,
|
|
10123
|
+
ubxFrames,
|
|
9773
10124
|
updateStationMeta,
|
|
9774
10125
|
updateStreamStats,
|
|
9775
10126
|
verifyChecksum,
|