gnss-js 2.10.1 → 2.12.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/README.md +16 -1
- package/dist/analysis.cjs +24 -25
- package/dist/analysis.js +2 -2
- package/dist/{clk-DGVBGRzA.d.cts → bias-sinex-OGMw9xEZ.d.cts} +66 -1
- package/dist/{clk-DGVBGRzA.d.ts → bias-sinex-OGMw9xEZ.d.ts} +66 -1
- package/dist/binex.d.cts +1 -1
- package/dist/binex.d.ts +1 -1
- package/dist/{chunk-56HM5B6T.js → chunk-2DJ4XENO.js} +177 -9
- package/dist/{chunk-GH7MYXON.js → chunk-2KQMCJ5Z.js} +7 -5
- package/dist/chunk-E3Y6YKQM.js +65 -0
- package/dist/{chunk-3U5AX7PY.js → chunk-FEABDV5P.js} +24 -25
- package/dist/{chunk-WQX354KD.js → chunk-H3AKFD25.js} +1 -1
- package/dist/{chunk-YUW33VXK.js → chunk-HUXQABJI.js} +2 -0
- package/dist/{chunk-74IVYOQV.js → chunk-HWHD5E6V.js} +128 -78
- package/dist/{chunk-KUSUN7DP.js → chunk-MFCPYUEI.js} +1 -1
- package/dist/{chunk-3KSDL3CO.js → chunk-NIJ6WFQJ.js} +6 -321
- package/dist/chunk-NL2ORX75.js +319 -0
- package/dist/{chunk-K3GLUWZI.js → chunk-RWFJEVLJ.js} +590 -296
- package/dist/{chunk-SEYH4BEN.js → chunk-SZP4TLYR.js} +2 -2
- package/dist/chunk-TWGZTRBL.js +323 -0
- package/dist/index.cjs +1315 -460
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +20 -12
- package/dist/{nav-DImXUdbp.d.cts → nav-COp0Vmlw.d.cts} +83 -2
- package/dist/{nav-DImXUdbp.d.ts → nav-COp0Vmlw.d.ts} +83 -2
- package/dist/{nav-BYmYoh9A.d.cts → nav-CvZXmumD.d.cts} +1 -1
- package/dist/{nav-CN8rxL4h.d.ts → nav-D2DFlVpa.d.ts} +1 -1
- package/dist/novatel.d.cts +1 -1
- package/dist/novatel.d.ts +1 -1
- package/dist/novatel.js +3 -3
- package/dist/orbit.d.cts +2 -2
- package/dist/orbit.d.ts +2 -2
- package/dist/osnma.cjs +1336 -0
- package/dist/osnma.d.cts +273 -0
- package/dist/osnma.d.ts +273 -0
- package/dist/osnma.js +1216 -0
- package/dist/positioning.cjs +585 -291
- package/dist/positioning.d.cts +116 -6
- package/dist/positioning.d.ts +116 -6
- package/dist/positioning.js +3 -3
- package/dist/rinex.cjs +210 -36
- package/dist/rinex.d.cts +10 -55
- package/dist/rinex.d.ts +10 -55
- package/dist/rinex.js +6 -3
- package/dist/sbf.cjs +420 -24
- package/dist/sbf.d.cts +46 -5
- package/dist/sbf.d.ts +46 -5
- package/dist/sbf.js +12 -6
- package/dist/trimble.d.cts +1 -1
- package/dist/trimble.d.ts +1 -1
- package/dist/ubx.d.cts +1 -1
- package/dist/ubx.d.ts +1 -1
- package/dist/ubx.js +5 -4
- package/package.json +6 -1
package/dist/rinex.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var rinex_exports = {};
|
|
|
22
22
|
__export(rinex_exports, {
|
|
23
23
|
EMPTY_WARNINGS: () => EMPTY_WARNINGS,
|
|
24
24
|
SYSTEM_ORDER: () => SYSTEM_ORDER,
|
|
25
|
+
SatOsbTable: () => SatOsbTable,
|
|
25
26
|
WarningAccumulator: () => WarningAccumulator,
|
|
26
27
|
biasMetres: () => biasMetres,
|
|
27
28
|
clkBias: () => clkBias,
|
|
@@ -59,20 +60,14 @@ module.exports = __toCommonJS(rinex_exports);
|
|
|
59
60
|
// src/rinex/crx.ts
|
|
60
61
|
function crxRepair(old, diff) {
|
|
61
62
|
const chars = old.split("");
|
|
62
|
-
|
|
63
|
+
const n = Math.min(old.length, diff.length);
|
|
64
|
+
for (let i = 0; i < n; i++) {
|
|
63
65
|
const dc = diff[i];
|
|
64
|
-
if (dc === " ")
|
|
65
|
-
|
|
66
|
-
chars[i] = " ";
|
|
67
|
-
} else {
|
|
68
|
-
chars[i] = dc;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (diff.length > chars.length) {
|
|
72
|
-
for (let i = chars.length; i < diff.length; i++) {
|
|
73
|
-
chars[i] = diff[i] === "&" ? " " : diff[i];
|
|
74
|
-
}
|
|
66
|
+
if (dc === " ") continue;
|
|
67
|
+
chars[i] = dc === "&" ? " " : dc;
|
|
75
68
|
}
|
|
69
|
+
for (let i = old.length; i < diff.length; i++)
|
|
70
|
+
chars[i] = diff[i] === "&" ? " " : diff[i];
|
|
76
71
|
return chars.join("");
|
|
77
72
|
}
|
|
78
73
|
function parseCrxDataLine(line, ntype) {
|
|
@@ -782,6 +777,15 @@ function readObsValue(line, index) {
|
|
|
782
777
|
const v = parseFloat(raw);
|
|
783
778
|
return isNaN(v) ? null : v;
|
|
784
779
|
}
|
|
780
|
+
function normalizePrn(id) {
|
|
781
|
+
let sys = id[0];
|
|
782
|
+
let num = id.substring(1);
|
|
783
|
+
if (sys === " " || /\d/.test(sys)) {
|
|
784
|
+
num = id;
|
|
785
|
+
sys = "G";
|
|
786
|
+
}
|
|
787
|
+
return sys + num.replace(/\s/g, "").padStart(2, "0");
|
|
788
|
+
}
|
|
785
789
|
function parseEpochLine3(line) {
|
|
786
790
|
if (line[0] !== ">") return null;
|
|
787
791
|
const yr = parseInt(line.substring(2, 6));
|
|
@@ -931,7 +935,7 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
931
935
|
function processSatLineV3(line) {
|
|
932
936
|
if (!header || line.length < 3) return;
|
|
933
937
|
const sys = line[0];
|
|
934
|
-
const prn = line.substring(0, 3);
|
|
938
|
+
const prn = normalizePrn(line.substring(0, 3));
|
|
935
939
|
trackSat(sys, prn);
|
|
936
940
|
const obsLine = line.substring(3);
|
|
937
941
|
const codes = header.obsTypes[sys] ?? [];
|
|
@@ -956,10 +960,8 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
956
960
|
let v2ObsAccum = [];
|
|
957
961
|
function processSatLineV2(line) {
|
|
958
962
|
if (!header || v2SatIndex >= v2SatIds.length) return;
|
|
959
|
-
const
|
|
960
|
-
|
|
961
|
-
if (sys === " " || /\d/.test(sys)) sys = "G";
|
|
962
|
-
const prn = sys + satId.substring(1).padStart(2, "0");
|
|
963
|
+
const prn = normalizePrn(v2SatIds[v2SatIndex]);
|
|
964
|
+
const sys = prn[0];
|
|
963
965
|
if (v2CurrentSatLine === 0) {
|
|
964
966
|
trackSat(sys, prn);
|
|
965
967
|
if (onSatObs) v2ObsAccum = [];
|
|
@@ -1050,6 +1052,7 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
1050
1052
|
} else {
|
|
1051
1053
|
epochLine = crxRepair(crxPrevEpochLine, line);
|
|
1052
1054
|
}
|
|
1055
|
+
epochLine = epochLine.replace(/ +$/, "");
|
|
1053
1056
|
if (isV3) {
|
|
1054
1057
|
if (epochLine[0] !== ">") return;
|
|
1055
1058
|
const info = parseEpochLine3(epochLine);
|
|
@@ -1067,10 +1070,11 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
1067
1070
|
return;
|
|
1068
1071
|
}
|
|
1069
1072
|
resetEpochAccum(info);
|
|
1070
|
-
const satPart = epochLine.substring(41).replace(/\s+$/, "");
|
|
1071
1073
|
crxSatList = [];
|
|
1072
|
-
for (let
|
|
1073
|
-
crxSatList.push(
|
|
1074
|
+
for (let k = 0; k < info.numSats; k++) {
|
|
1075
|
+
crxSatList.push(
|
|
1076
|
+
normalizePrn(epochLine.substring(41 + 3 * k, 44 + 3 * k))
|
|
1077
|
+
);
|
|
1074
1078
|
}
|
|
1075
1079
|
crxSatIndex = 0;
|
|
1076
1080
|
crxPrevEpochLine = epochLine;
|
|
@@ -1091,11 +1095,7 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
1091
1095
|
return;
|
|
1092
1096
|
}
|
|
1093
1097
|
resetEpochAccum(info);
|
|
1094
|
-
crxSatList = (info.satIds ?? []).map(
|
|
1095
|
-
let sys = id[0];
|
|
1096
|
-
if (sys === " " || /\d/.test(sys)) sys = "G";
|
|
1097
|
-
return sys + id.substring(1).padStart(2, "0");
|
|
1098
|
-
});
|
|
1098
|
+
crxSatList = (info.satIds ?? []).slice(0, info.numSats).map(normalizePrn);
|
|
1099
1099
|
crxSatIndex = 0;
|
|
1100
1100
|
crxPrevEpochLine = epochLine;
|
|
1101
1101
|
crxPhase = "clock";
|
|
@@ -1495,6 +1495,15 @@ var SEC_PER_WEEK2 = 7 * 86400;
|
|
|
1495
1495
|
var CNAV_A_REF = 26559710;
|
|
1496
1496
|
var CNAV_OMEGA_DOT_REF = -26e-10;
|
|
1497
1497
|
|
|
1498
|
+
// src/navbits/bds-cnav.ts
|
|
1499
|
+
var BDT_EPOCH_MS = Date.UTC(2006, 0, 1);
|
|
1500
|
+
var SEC_PER_WEEK3 = 7 * 86400;
|
|
1501
|
+
var BDS_CNAV_A_REF_MEO = 27906100;
|
|
1502
|
+
var BDS_CNAV_A_REF_IGSO_GEO = 42162200;
|
|
1503
|
+
function bdsCnavAref(satType) {
|
|
1504
|
+
return satType === 3 ? BDS_CNAV_A_REF_MEO : BDS_CNAV_A_REF_IGSO_GEO;
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1498
1507
|
// src/rinex/nav.ts
|
|
1499
1508
|
var DATA_LINES = {
|
|
1500
1509
|
G: 7,
|
|
@@ -1520,16 +1529,17 @@ var R4_MSG_LINES = {
|
|
|
1520
1529
|
// RINEX 4 adds orbit-4 (status flags) vs 3 in RINEX 3
|
|
1521
1530
|
// EPH type parsed into RinexCnavEphemeris for G/J (skipped otherwise)
|
|
1522
1531
|
CNAV: 9,
|
|
1523
|
-
//
|
|
1532
|
+
// BeiDou-3 B-CNAV, parsed into BdsCnavEphemeris
|
|
1524
1533
|
CNV1: 10,
|
|
1525
1534
|
CNV2: 10,
|
|
1526
1535
|
CNV3: 9,
|
|
1536
|
+
// EPH types we skip (different field layout)
|
|
1527
1537
|
L1NV: 8,
|
|
1528
1538
|
L1OC: 9,
|
|
1529
1539
|
L3OC: 9
|
|
1530
1540
|
};
|
|
1531
1541
|
var GPS_EPOCH_MS3 = Date.UTC(1980, 0, 6);
|
|
1532
|
-
var
|
|
1542
|
+
var SEC_PER_WEEK4 = 7 * 86400;
|
|
1533
1543
|
var QZSS_CNAV_A_REF = 42164200;
|
|
1534
1544
|
var SUPPORTED_EPH_MSGS = /* @__PURE__ */ new Set([
|
|
1535
1545
|
"LNAV",
|
|
@@ -1674,8 +1684,8 @@ function buildCnavEphemeris(sys, prn, date, epochVals, d) {
|
|
|
1674
1684
|
const num = (r, c) => d[r]?.[c] ?? 0;
|
|
1675
1685
|
const opt = (r, c) => d[r]?.[c] ?? null;
|
|
1676
1686
|
const t = (date.getTime() - GPS_EPOCH_MS3) / 1e3;
|
|
1677
|
-
const week = Math.floor(t /
|
|
1678
|
-
const toc = t - week *
|
|
1687
|
+
const week = Math.floor(t / SEC_PER_WEEK4);
|
|
1688
|
+
const toc = t - week * SEC_PER_WEEK4;
|
|
1679
1689
|
const sqrtA = num(1, 3);
|
|
1680
1690
|
const a = sqrtA * sqrtA;
|
|
1681
1691
|
const aRef = sys === "J" ? QZSS_CNAV_A_REF : CNAV_A_REF;
|
|
@@ -1732,6 +1742,68 @@ function buildCnavEphemeris(sys, prn, date, epochVals, d) {
|
|
|
1732
1742
|
tow: num(7, 0)
|
|
1733
1743
|
};
|
|
1734
1744
|
}
|
|
1745
|
+
var BDT_EPOCH_MS2 = Date.UTC(2006, 0, 1);
|
|
1746
|
+
function buildBdsCnavEphemeris(message, prn, date, epochVals, d) {
|
|
1747
|
+
const num = (r, c) => d[r]?.[c] ?? 0;
|
|
1748
|
+
const opt = (r, c) => d[r]?.[c] ?? null;
|
|
1749
|
+
const cnv3 = message === "CNV3";
|
|
1750
|
+
const t = (date.getTime() - BDT_EPOCH_MS2) / 1e3;
|
|
1751
|
+
const weekToc = Math.floor(t / SEC_PER_WEEK4);
|
|
1752
|
+
const toc = t - weekToc * SEC_PER_WEEK4;
|
|
1753
|
+
const toe = num(2, 0);
|
|
1754
|
+
const week = toe - toc > SEC_PER_WEEK4 / 2 ? weekToc - 1 : toc - toe > SEC_PER_WEEK4 / 2 ? weekToc + 1 : weekToc;
|
|
1755
|
+
const sqrtA = num(1, 3);
|
|
1756
|
+
const a = sqrtA * sqrtA;
|
|
1757
|
+
const satType = num(4, 2);
|
|
1758
|
+
return {
|
|
1759
|
+
system: "C",
|
|
1760
|
+
prn,
|
|
1761
|
+
message,
|
|
1762
|
+
week,
|
|
1763
|
+
toe,
|
|
1764
|
+
toeDate: new Date(BDT_EPOCH_MS2 + (week * SEC_PER_WEEK4 + toe) * 1e3),
|
|
1765
|
+
toc,
|
|
1766
|
+
tocDate: date,
|
|
1767
|
+
satType,
|
|
1768
|
+
a,
|
|
1769
|
+
deltaA: a - bdsCnavAref(satType),
|
|
1770
|
+
aDot: num(0, 0),
|
|
1771
|
+
deltaN0: num(0, 2),
|
|
1772
|
+
deltaN0Dot: num(4, 1),
|
|
1773
|
+
m0: num(0, 3),
|
|
1774
|
+
e: num(1, 1),
|
|
1775
|
+
omega: num(3, 2),
|
|
1776
|
+
omega0: num(2, 2),
|
|
1777
|
+
i0: num(3, 0),
|
|
1778
|
+
omegaDot: num(3, 3),
|
|
1779
|
+
i0Dot: num(4, 0),
|
|
1780
|
+
cis: num(2, 3),
|
|
1781
|
+
cic: num(2, 1),
|
|
1782
|
+
crs: num(0, 1),
|
|
1783
|
+
crc: num(3, 1),
|
|
1784
|
+
cus: num(1, 2),
|
|
1785
|
+
cuc: num(1, 0),
|
|
1786
|
+
af0: epochVals[0] ?? 0,
|
|
1787
|
+
af1: epochVals[1] ?? 0,
|
|
1788
|
+
af2: epochVals[2] ?? 0,
|
|
1789
|
+
iode: cnv3 ? null : opt(8, 3),
|
|
1790
|
+
iodc: cnv3 ? null : opt(7, 3),
|
|
1791
|
+
tgdB1Cp: cnv3 ? null : opt(6, 2),
|
|
1792
|
+
tgdB2ap: cnv3 ? null : opt(6, 3),
|
|
1793
|
+
iscB1Cd: cnv3 ? null : opt(6, 0),
|
|
1794
|
+
iscB2ad: cnv3 ? null : opt(6, 1),
|
|
1795
|
+
tgdB2bI: cnv3 ? opt(6, 3) : null,
|
|
1796
|
+
top: opt(4, 3),
|
|
1797
|
+
sisaiOe: opt(5, 0),
|
|
1798
|
+
sisaiOcb: opt(5, 1),
|
|
1799
|
+
sisaiOc1: opt(5, 2),
|
|
1800
|
+
sisaiOc2: opt(5, 3),
|
|
1801
|
+
sismai: cnv3 ? opt(6, 0) : opt(7, 0),
|
|
1802
|
+
health: cnv3 ? opt(6, 1) : opt(7, 1),
|
|
1803
|
+
integrityFlags: cnv3 ? opt(6, 2) : opt(7, 2),
|
|
1804
|
+
tow: cnv3 ? num(7, 0) : num(8, 0)
|
|
1805
|
+
};
|
|
1806
|
+
}
|
|
1735
1807
|
function parseNavFile(text) {
|
|
1736
1808
|
const lines = text.split("\n");
|
|
1737
1809
|
const header = {
|
|
@@ -1742,6 +1814,7 @@ function parseNavFile(text) {
|
|
|
1742
1814
|
};
|
|
1743
1815
|
const ephemerides = [];
|
|
1744
1816
|
const cnav = [];
|
|
1817
|
+
const bdsCnav = [];
|
|
1745
1818
|
let inHeader = true;
|
|
1746
1819
|
let i = 0;
|
|
1747
1820
|
while (i < lines.length) {
|
|
@@ -1810,7 +1883,8 @@ function parseNavFile(text) {
|
|
|
1810
1883
|
continue;
|
|
1811
1884
|
}
|
|
1812
1885
|
const isCnav = msgType === "CNAV" && (svSys === "G" || svSys === "J");
|
|
1813
|
-
|
|
1886
|
+
const isBdsCnav = svSys === "C" && (msgType === "CNV1" || msgType === "CNV2" || msgType === "CNV3");
|
|
1887
|
+
if (!SUPPORTED_EPH_MSGS.has(msgType) && !isCnav && !isBdsCnav) {
|
|
1814
1888
|
const totalLines = R4_MSG_LINES[msgType] ?? 2;
|
|
1815
1889
|
i += totalLines + 1;
|
|
1816
1890
|
continue;
|
|
@@ -1822,17 +1896,34 @@ function parseNavFile(text) {
|
|
|
1822
1896
|
const sys2 = epochLine.charAt(0);
|
|
1823
1897
|
const parsed = parseNavEpochV3(epochLine);
|
|
1824
1898
|
const prn2 = `${sys2}${parsed.prn.substring(1)}`;
|
|
1825
|
-
if (isCnav) {
|
|
1899
|
+
if (isCnav || isBdsCnav) {
|
|
1826
1900
|
const slotLines = [];
|
|
1827
1901
|
for (let j = 0; j < numDataLines2; j++) {
|
|
1828
1902
|
i++;
|
|
1829
1903
|
if (i >= lines.length) break;
|
|
1830
1904
|
slotLines.push(parseDataLineSlots(lines[i]));
|
|
1831
1905
|
}
|
|
1832
|
-
if (slotLines.length === numDataLines2
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1906
|
+
if (slotLines.length === numDataLines2) {
|
|
1907
|
+
if (isBdsCnav && sys2 === "C")
|
|
1908
|
+
bdsCnav.push(
|
|
1909
|
+
buildBdsCnavEphemeris(
|
|
1910
|
+
msgType,
|
|
1911
|
+
prn2,
|
|
1912
|
+
parsed.date,
|
|
1913
|
+
parsed.values,
|
|
1914
|
+
slotLines
|
|
1915
|
+
)
|
|
1916
|
+
);
|
|
1917
|
+
else if (sys2 === "G" || sys2 === "J")
|
|
1918
|
+
cnav.push(
|
|
1919
|
+
buildCnavEphemeris(
|
|
1920
|
+
sys2,
|
|
1921
|
+
prn2,
|
|
1922
|
+
parsed.date,
|
|
1923
|
+
parsed.values,
|
|
1924
|
+
slotLines
|
|
1925
|
+
)
|
|
1926
|
+
);
|
|
1836
1927
|
}
|
|
1837
1928
|
i++;
|
|
1838
1929
|
continue;
|
|
@@ -1910,7 +2001,12 @@ function parseNavFile(text) {
|
|
|
1910
2001
|
}
|
|
1911
2002
|
i++;
|
|
1912
2003
|
}
|
|
1913
|
-
return
|
|
2004
|
+
return {
|
|
2005
|
+
header,
|
|
2006
|
+
ephemerides,
|
|
2007
|
+
...cnav.length > 0 && { cnav },
|
|
2008
|
+
...bdsCnav.length > 0 && { bdsCnav }
|
|
2009
|
+
};
|
|
1914
2010
|
}
|
|
1915
2011
|
|
|
1916
2012
|
// src/rinex/nav-writer.ts
|
|
@@ -2106,6 +2202,30 @@ function cnavRecord(eph) {
|
|
|
2106
2202
|
orbitLine4([eph.tow, resolveWnOp(eph.week, eph.wnOp)])
|
|
2107
2203
|
].join("\n");
|
|
2108
2204
|
}
|
|
2205
|
+
function bdsCnavRecord(eph) {
|
|
2206
|
+
const lines = [
|
|
2207
|
+
epochLine4(eph.prn, eph.tocDate, [eph.af0, eph.af1, eph.af2]),
|
|
2208
|
+
orbitLine4([eph.aDot, eph.crs, eph.deltaN0, eph.m0]),
|
|
2209
|
+
orbitLine4([eph.cuc, eph.e, eph.cus, Math.sqrt(eph.a)]),
|
|
2210
|
+
orbitLine4([eph.toe, eph.cic, eph.omega0, eph.cis]),
|
|
2211
|
+
orbitLine4([eph.i0, eph.crc, eph.omega, eph.omegaDot]),
|
|
2212
|
+
orbitLine4([eph.i0Dot, eph.deltaN0Dot, eph.satType, eph.top]),
|
|
2213
|
+
orbitLine4([eph.sisaiOe, eph.sisaiOcb, eph.sisaiOc1, eph.sisaiOc2])
|
|
2214
|
+
];
|
|
2215
|
+
if (eph.message === "CNV3") {
|
|
2216
|
+
lines.push(
|
|
2217
|
+
orbitLine4([eph.sismai, eph.health, eph.integrityFlags, eph.tgdB2bI]),
|
|
2218
|
+
orbitLine4([eph.tow])
|
|
2219
|
+
);
|
|
2220
|
+
} else {
|
|
2221
|
+
lines.push(
|
|
2222
|
+
orbitLine4([eph.iscB1Cd, eph.iscB2ad, eph.tgdB1Cp, eph.tgdB2ap]),
|
|
2223
|
+
orbitLine4([eph.sismai, eph.health, eph.integrityFlags, eph.iodc]),
|
|
2224
|
+
orbitLine4([eph.tow, null, null, eph.iode])
|
|
2225
|
+
);
|
|
2226
|
+
}
|
|
2227
|
+
return lines.join("\n");
|
|
2228
|
+
}
|
|
2109
2229
|
var KLOBUCHAR_SOURCES = [
|
|
2110
2230
|
["GPSA", "GPSB", "G", "LNAV"],
|
|
2111
2231
|
["QZSA", "QZSB", "J", "LNAV"],
|
|
@@ -2183,6 +2303,15 @@ function writeRinexNav4(nav) {
|
|
|
2183
2303
|
` + cnavRecord(eph)
|
|
2184
2304
|
});
|
|
2185
2305
|
}
|
|
2306
|
+
for (const eph of nav.bdsCnav ?? []) {
|
|
2307
|
+
records.push({
|
|
2308
|
+
prn: eph.prn,
|
|
2309
|
+
time: eph.tocDate.getTime(),
|
|
2310
|
+
label: eph.message,
|
|
2311
|
+
body: `> EPH ${padL(eph.prn, 3)} ${eph.message}
|
|
2312
|
+
` + bdsCnavRecord(eph)
|
|
2313
|
+
});
|
|
2314
|
+
}
|
|
2186
2315
|
records.sort(
|
|
2187
2316
|
(a, b) => a.prn.localeCompare(b.prn) || a.time - b.time || a.label.localeCompare(b.label)
|
|
2188
2317
|
);
|
|
@@ -2529,6 +2658,50 @@ function findSatBias(bias, prn, obs1, obs2, tMs) {
|
|
|
2529
2658
|
}
|
|
2530
2659
|
return null;
|
|
2531
2660
|
}
|
|
2661
|
+
var SatOsbTable = class {
|
|
2662
|
+
byKey = /* @__PURE__ */ new Map();
|
|
2663
|
+
constructor(bias) {
|
|
2664
|
+
const recs = Array.isArray(bias) ? bias : bias.records;
|
|
2665
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2666
|
+
for (const r of recs) {
|
|
2667
|
+
if (r.type !== "OSB" || !r.prn || r.station) continue;
|
|
2668
|
+
if (r.unit !== "ns") continue;
|
|
2669
|
+
const k = `${r.prn} ${r.obs1}`;
|
|
2670
|
+
let g = groups.get(k);
|
|
2671
|
+
if (!g) groups.set(k, g = []);
|
|
2672
|
+
g.push(r);
|
|
2673
|
+
}
|
|
2674
|
+
for (const [k, g] of groups) {
|
|
2675
|
+
g.sort((a, b) => a.startMs - b.startMs);
|
|
2676
|
+
this.byKey.set(k, {
|
|
2677
|
+
start: Float64Array.from(g, (r) => r.startMs),
|
|
2678
|
+
end: Float64Array.from(g, (r) => r.endMs),
|
|
2679
|
+
m: Float64Array.from(g, biasMetres)
|
|
2680
|
+
});
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
/** Whether any phase (L…) OSB is present — i.e. the product supports AR. */
|
|
2684
|
+
get hasPhase() {
|
|
2685
|
+
for (const k of this.byKey.keys())
|
|
2686
|
+
if (k.split(" ")[1][0] === "L") return true;
|
|
2687
|
+
return false;
|
|
2688
|
+
}
|
|
2689
|
+
/** OSB (m) of `prn`'s observable `obs` (e.g. 'C1W', 'L2W') at `tMs`;
|
|
2690
|
+
* null when the product has none valid then. */
|
|
2691
|
+
get(prn, obs, tMs) {
|
|
2692
|
+
const e = this.byKey.get(`${prn} ${obs}`) ?? this.byKey.get(`${prn} ${obs.slice(0, 2)}X`);
|
|
2693
|
+
if (!e) return null;
|
|
2694
|
+
let lo = 0;
|
|
2695
|
+
let hi = e.start.length - 1;
|
|
2696
|
+
if (tMs < e.start[0]) return null;
|
|
2697
|
+
while (lo < hi) {
|
|
2698
|
+
const mid = lo + hi + 1 >> 1;
|
|
2699
|
+
if (e.start[mid] <= tMs) lo = mid;
|
|
2700
|
+
else hi = mid - 1;
|
|
2701
|
+
}
|
|
2702
|
+
return tMs <= e.end[lo] ? e.m[lo] : null;
|
|
2703
|
+
}
|
|
2704
|
+
};
|
|
2532
2705
|
|
|
2533
2706
|
// src/rinex/obs-writer-common.ts
|
|
2534
2707
|
function createGzipLineSink() {
|
|
@@ -2920,6 +3093,7 @@ function writeRinex4ObsBlob(header, epochs, obsTypes) {
|
|
|
2920
3093
|
0 && (module.exports = {
|
|
2921
3094
|
EMPTY_WARNINGS,
|
|
2922
3095
|
SYSTEM_ORDER,
|
|
3096
|
+
SatOsbTable,
|
|
2923
3097
|
WarningAccumulator,
|
|
2924
3098
|
biasMetres,
|
|
2925
3099
|
clkBias,
|
package/dist/rinex.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { R as RinexHeader } from './parser-JPjjFgeP.cjs';
|
|
2
2
|
export { E as EpochSummary, P as ParseOptions, a as RinexResult, b as RinexStats, S as SYSTEM_ORDER, c as SatObsCallback, p as parseRinexStream, s as systemCmp, d as systemName } from './parser-JPjjFgeP.cjs';
|
|
3
|
-
import {
|
|
4
|
-
export { G as GlonassEphemeris, K as KeplerEphemeris, p as parseNavFile } from './nav-
|
|
5
|
-
export { C as ClkFile, I as IonexGrid, S as Sp3File,
|
|
3
|
+
import { b as NavResult, N as NavHeader, E as Ephemeris, R as RinexCnavEphemeris, B as BdsCnavEphemeris } from './nav-COp0Vmlw.cjs';
|
|
4
|
+
export { a as BdsCnavMessage, G as GlonassEphemeris, K as KeplerEphemeris, p as parseNavFile } from './nav-COp0Vmlw.cjs';
|
|
5
|
+
export { B as BiasRecord, a as BiasSinex, C as ClkFile, I as IonexGrid, S as SatOsbTable, b as Sp3File, c as Sp3Sample, d as biasMetres, e as clkBias, f as findSatBias, p as parseBiasSinex, g as parseClk, h as parseIonex, i as parseSp3, s as sp3Position } from './bias-sinex-OGMw9xEZ.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Compact RINEX (Hatanaka / CRX) decompression utilities.
|
|
@@ -155,7 +155,8 @@ declare function writeRinexNav(nav: NavResult): string;
|
|
|
155
155
|
*
|
|
156
156
|
* Produces `> EPH` data records for the classic ephemeris types
|
|
157
157
|
* (GPS/QZSS/NavIC LNAV, Galileo INAV, BeiDou D1/D2, GLONASS FDMA,
|
|
158
|
-
* SBAS), `> EPH ... CNAV` records for GPS/QZSS CNAV ephemerides,
|
|
158
|
+
* SBAS), `> EPH ... CNAV` records for GPS/QZSS CNAV ephemerides, BeiDou-3
|
|
159
|
+
* `CNV1`/`CNV2`/`CNV3` records for B-CNAV ephemerides, and
|
|
159
160
|
* `> ION` records for the header's Klobuchar/NeQuick-G coefficients,
|
|
160
161
|
* per the RINEX 4.01 record tables (A9-A18, A21, A26, A32, A33).
|
|
161
162
|
*/
|
|
@@ -165,13 +166,15 @@ interface Nav4Input {
|
|
|
165
166
|
header: NavHeader;
|
|
166
167
|
ephemerides: Ephemeris[];
|
|
167
168
|
cnav?: RinexCnavEphemeris[];
|
|
169
|
+
bdsCnav?: BdsCnavEphemeris[];
|
|
168
170
|
}
|
|
169
171
|
/**
|
|
170
172
|
* Write a RINEX 4.01 mixed navigation file.
|
|
171
173
|
*
|
|
172
174
|
* Emits `> EPH` records for every classic ephemeris (message labels
|
|
173
|
-
* per constellation: LNAV, INAV, D1/D2, FDMA, SBAS)
|
|
174
|
-
* ephemeris (`CNAV`)
|
|
175
|
+
* per constellation: LNAV, INAV, D1/D2, FDMA, SBAS), every GPS/QZSS
|
|
176
|
+
* CNAV ephemeris (`CNAV`) and every BeiDou-3 B-CNAV ephemeris (`CNV1`/
|
|
177
|
+
* `CNV2`/`CNV3`), sorted by PRN, epoch, then label; followed by
|
|
175
178
|
* `> ION` records when the header carries Klobuchar (GPSA/GPSB,
|
|
176
179
|
* QZSA/QZSB, BDSA/BDSB, IRNA/IRNB) or NeQuick-G (GAL) coefficients.
|
|
177
180
|
* ION records need a transmit-time epoch, which RINEX 3-style headers
|
|
@@ -182,54 +185,6 @@ interface Nav4Input {
|
|
|
182
185
|
*/
|
|
183
186
|
declare function writeRinexNav4(nav: Nav4Input): string;
|
|
184
187
|
|
|
185
|
-
/**
|
|
186
|
-
* Bias-SINEX (`.BIA`) parser — GNSS code/phase biases published by the IGS
|
|
187
|
-
* analysis centres. Two record kinds matter here:
|
|
188
|
-
*
|
|
189
|
-
* - **DSB** differential signal bias (OBS1−OBS2), the classic inter-code
|
|
190
|
-
* bias used for ionosphere/DCB corrections in SPP.
|
|
191
|
-
* - **OSB** observable-specific (absolute) bias for a single OBS, the
|
|
192
|
-
* ingredient PPP-AR needs: the *phase* OSBs are the satellite
|
|
193
|
-
* fractional-cycle biases that make the ambiguities integer-recoverable.
|
|
194
|
-
*
|
|
195
|
-
* Values keep their file unit (`ns` for code/most phase biases, `cyc` for
|
|
196
|
-
* cycle-based phase biases); `biasMetres` converts ns → m via c.
|
|
197
|
-
*/
|
|
198
|
-
interface BiasRecord {
|
|
199
|
-
/** 'DSB' | 'OSB' | 'ISB' | … */
|
|
200
|
-
type: string;
|
|
201
|
-
/** Satellite PRN (e.g. 'G01', 'E11'); '' for a pure station bias. */
|
|
202
|
-
prn: string;
|
|
203
|
-
/** Station (9-char), '' for satellite biases. */
|
|
204
|
-
station: string;
|
|
205
|
-
/** First observable code (e.g. 'C1W', 'L1C'). */
|
|
206
|
-
obs1: string;
|
|
207
|
-
/** Second observable (DSB only; '' for OSB). */
|
|
208
|
-
obs2: string;
|
|
209
|
-
/** Validity start / end (GPS-scale ms); ±Infinity when open. */
|
|
210
|
-
startMs: number;
|
|
211
|
-
endMs: number;
|
|
212
|
-
/** Estimated value in the file unit. */
|
|
213
|
-
value: number;
|
|
214
|
-
/** File unit ('ns' | 'cyc' | …). */
|
|
215
|
-
unit: string;
|
|
216
|
-
}
|
|
217
|
-
interface BiasSinex {
|
|
218
|
-
records: BiasRecord[];
|
|
219
|
-
/** All satellite records grouped by PRN (station === ''). */
|
|
220
|
-
bySat: Map<string, BiasRecord[]>;
|
|
221
|
-
}
|
|
222
|
-
/** Parse a Bias-SINEX file. */
|
|
223
|
-
declare function parseBiasSinex(text: string): BiasSinex;
|
|
224
|
-
/** A satellite bias record's value in metres (ns → m via c; cyc left as-is). */
|
|
225
|
-
declare function biasMetres(r: BiasRecord): number;
|
|
226
|
-
/**
|
|
227
|
-
* Look up a satellite bias: a DSB by its (obs1,obs2) pair, or an OSB by obs1
|
|
228
|
-
* alone (pass obs2 = undefined), valid at `tMs` (default: any). Returns the
|
|
229
|
-
* record or null.
|
|
230
|
-
*/
|
|
231
|
-
declare function findSatBias(bias: BiasSinex, prn: string, obs1: string, obs2?: string, tMs?: number): BiasRecord | null;
|
|
232
|
-
|
|
233
188
|
/**
|
|
234
189
|
* RINEX 3.04 / 4.01 observation file writer.
|
|
235
190
|
*
|
|
@@ -320,4 +275,4 @@ declare function createGzipLineSink(): {
|
|
|
320
275
|
*/
|
|
321
276
|
declare function stationHeaderLines(header: RinexHeader): string[];
|
|
322
277
|
|
|
323
|
-
export {
|
|
278
|
+
export { BdsCnavEphemeris, type CompactEpoch, type CrxField, type DiffState, EMPTY_WARNINGS, Ephemeris, type Nav4Input, NavHeader, NavResult, RinexCnavEphemeris, RinexHeader, type RinexWarning, type RinexWarnings, WarningAccumulator, type WarningSeverity, type WriteCrxOptions, createGzipLineSink, crxDecompress, crxRepair, fmtD, fmtF, hdrLine, modalIntervalS, padL, padR, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob };
|
package/dist/rinex.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { R as RinexHeader } from './parser-JPjjFgeP.js';
|
|
2
2
|
export { E as EpochSummary, P as ParseOptions, a as RinexResult, b as RinexStats, S as SYSTEM_ORDER, c as SatObsCallback, p as parseRinexStream, s as systemCmp, d as systemName } from './parser-JPjjFgeP.js';
|
|
3
|
-
import {
|
|
4
|
-
export { G as GlonassEphemeris, K as KeplerEphemeris, p as parseNavFile } from './nav-
|
|
5
|
-
export { C as ClkFile, I as IonexGrid, S as Sp3File,
|
|
3
|
+
import { b as NavResult, N as NavHeader, E as Ephemeris, R as RinexCnavEphemeris, B as BdsCnavEphemeris } from './nav-COp0Vmlw.js';
|
|
4
|
+
export { a as BdsCnavMessage, G as GlonassEphemeris, K as KeplerEphemeris, p as parseNavFile } from './nav-COp0Vmlw.js';
|
|
5
|
+
export { B as BiasRecord, a as BiasSinex, C as ClkFile, I as IonexGrid, S as SatOsbTable, b as Sp3File, c as Sp3Sample, d as biasMetres, e as clkBias, f as findSatBias, p as parseBiasSinex, g as parseClk, h as parseIonex, i as parseSp3, s as sp3Position } from './bias-sinex-OGMw9xEZ.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Compact RINEX (Hatanaka / CRX) decompression utilities.
|
|
@@ -155,7 +155,8 @@ declare function writeRinexNav(nav: NavResult): string;
|
|
|
155
155
|
*
|
|
156
156
|
* Produces `> EPH` data records for the classic ephemeris types
|
|
157
157
|
* (GPS/QZSS/NavIC LNAV, Galileo INAV, BeiDou D1/D2, GLONASS FDMA,
|
|
158
|
-
* SBAS), `> EPH ... CNAV` records for GPS/QZSS CNAV ephemerides,
|
|
158
|
+
* SBAS), `> EPH ... CNAV` records for GPS/QZSS CNAV ephemerides, BeiDou-3
|
|
159
|
+
* `CNV1`/`CNV2`/`CNV3` records for B-CNAV ephemerides, and
|
|
159
160
|
* `> ION` records for the header's Klobuchar/NeQuick-G coefficients,
|
|
160
161
|
* per the RINEX 4.01 record tables (A9-A18, A21, A26, A32, A33).
|
|
161
162
|
*/
|
|
@@ -165,13 +166,15 @@ interface Nav4Input {
|
|
|
165
166
|
header: NavHeader;
|
|
166
167
|
ephemerides: Ephemeris[];
|
|
167
168
|
cnav?: RinexCnavEphemeris[];
|
|
169
|
+
bdsCnav?: BdsCnavEphemeris[];
|
|
168
170
|
}
|
|
169
171
|
/**
|
|
170
172
|
* Write a RINEX 4.01 mixed navigation file.
|
|
171
173
|
*
|
|
172
174
|
* Emits `> EPH` records for every classic ephemeris (message labels
|
|
173
|
-
* per constellation: LNAV, INAV, D1/D2, FDMA, SBAS)
|
|
174
|
-
* ephemeris (`CNAV`)
|
|
175
|
+
* per constellation: LNAV, INAV, D1/D2, FDMA, SBAS), every GPS/QZSS
|
|
176
|
+
* CNAV ephemeris (`CNAV`) and every BeiDou-3 B-CNAV ephemeris (`CNV1`/
|
|
177
|
+
* `CNV2`/`CNV3`), sorted by PRN, epoch, then label; followed by
|
|
175
178
|
* `> ION` records when the header carries Klobuchar (GPSA/GPSB,
|
|
176
179
|
* QZSA/QZSB, BDSA/BDSB, IRNA/IRNB) or NeQuick-G (GAL) coefficients.
|
|
177
180
|
* ION records need a transmit-time epoch, which RINEX 3-style headers
|
|
@@ -182,54 +185,6 @@ interface Nav4Input {
|
|
|
182
185
|
*/
|
|
183
186
|
declare function writeRinexNav4(nav: Nav4Input): string;
|
|
184
187
|
|
|
185
|
-
/**
|
|
186
|
-
* Bias-SINEX (`.BIA`) parser — GNSS code/phase biases published by the IGS
|
|
187
|
-
* analysis centres. Two record kinds matter here:
|
|
188
|
-
*
|
|
189
|
-
* - **DSB** differential signal bias (OBS1−OBS2), the classic inter-code
|
|
190
|
-
* bias used for ionosphere/DCB corrections in SPP.
|
|
191
|
-
* - **OSB** observable-specific (absolute) bias for a single OBS, the
|
|
192
|
-
* ingredient PPP-AR needs: the *phase* OSBs are the satellite
|
|
193
|
-
* fractional-cycle biases that make the ambiguities integer-recoverable.
|
|
194
|
-
*
|
|
195
|
-
* Values keep their file unit (`ns` for code/most phase biases, `cyc` for
|
|
196
|
-
* cycle-based phase biases); `biasMetres` converts ns → m via c.
|
|
197
|
-
*/
|
|
198
|
-
interface BiasRecord {
|
|
199
|
-
/** 'DSB' | 'OSB' | 'ISB' | … */
|
|
200
|
-
type: string;
|
|
201
|
-
/** Satellite PRN (e.g. 'G01', 'E11'); '' for a pure station bias. */
|
|
202
|
-
prn: string;
|
|
203
|
-
/** Station (9-char), '' for satellite biases. */
|
|
204
|
-
station: string;
|
|
205
|
-
/** First observable code (e.g. 'C1W', 'L1C'). */
|
|
206
|
-
obs1: string;
|
|
207
|
-
/** Second observable (DSB only; '' for OSB). */
|
|
208
|
-
obs2: string;
|
|
209
|
-
/** Validity start / end (GPS-scale ms); ±Infinity when open. */
|
|
210
|
-
startMs: number;
|
|
211
|
-
endMs: number;
|
|
212
|
-
/** Estimated value in the file unit. */
|
|
213
|
-
value: number;
|
|
214
|
-
/** File unit ('ns' | 'cyc' | …). */
|
|
215
|
-
unit: string;
|
|
216
|
-
}
|
|
217
|
-
interface BiasSinex {
|
|
218
|
-
records: BiasRecord[];
|
|
219
|
-
/** All satellite records grouped by PRN (station === ''). */
|
|
220
|
-
bySat: Map<string, BiasRecord[]>;
|
|
221
|
-
}
|
|
222
|
-
/** Parse a Bias-SINEX file. */
|
|
223
|
-
declare function parseBiasSinex(text: string): BiasSinex;
|
|
224
|
-
/** A satellite bias record's value in metres (ns → m via c; cyc left as-is). */
|
|
225
|
-
declare function biasMetres(r: BiasRecord): number;
|
|
226
|
-
/**
|
|
227
|
-
* Look up a satellite bias: a DSB by its (obs1,obs2) pair, or an OSB by obs1
|
|
228
|
-
* alone (pass obs2 = undefined), valid at `tMs` (default: any). Returns the
|
|
229
|
-
* record or null.
|
|
230
|
-
*/
|
|
231
|
-
declare function findSatBias(bias: BiasSinex, prn: string, obs1: string, obs2?: string, tMs?: number): BiasRecord | null;
|
|
232
|
-
|
|
233
188
|
/**
|
|
234
189
|
* RINEX 3.04 / 4.01 observation file writer.
|
|
235
190
|
*
|
|
@@ -320,4 +275,4 @@ declare function createGzipLineSink(): {
|
|
|
320
275
|
*/
|
|
321
276
|
declare function stationHeaderLines(header: RinexHeader): string[];
|
|
322
277
|
|
|
323
|
-
export {
|
|
278
|
+
export { BdsCnavEphemeris, type CompactEpoch, type CrxField, type DiffState, EMPTY_WARNINGS, Ephemeris, type Nav4Input, NavHeader, NavResult, RinexCnavEphemeris, RinexHeader, type RinexWarning, type RinexWarnings, WarningAccumulator, type WarningSeverity, type WriteCrxOptions, createGzipLineSink, crxDecompress, crxRepair, fmtD, fmtF, hdrLine, modalIntervalS, padL, padR, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob };
|
package/dist/rinex.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EMPTY_WARNINGS,
|
|
3
|
+
SatOsbTable,
|
|
3
4
|
WarningAccumulator,
|
|
4
5
|
biasMetres,
|
|
5
6
|
createGzipLineSink,
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
writeRinexNav,
|
|
22
23
|
writeRinexNav4,
|
|
23
24
|
writeRinexObsBlob
|
|
24
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-2DJ4XENO.js";
|
|
25
26
|
import {
|
|
26
27
|
SYSTEM_ORDER,
|
|
27
28
|
crxDecompress,
|
|
@@ -30,19 +31,21 @@ import {
|
|
|
30
31
|
parseRinexStream,
|
|
31
32
|
systemCmp,
|
|
32
33
|
systemName
|
|
33
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-FEABDV5P.js";
|
|
35
|
+
import "./chunk-NL2ORX75.js";
|
|
34
36
|
import {
|
|
35
37
|
clkBias,
|
|
36
38
|
parseClk,
|
|
37
39
|
parseSp3,
|
|
38
40
|
sp3Position
|
|
39
41
|
} from "./chunk-GPEP67TG.js";
|
|
40
|
-
import "./chunk-
|
|
42
|
+
import "./chunk-HUXQABJI.js";
|
|
41
43
|
import "./chunk-V2D5KUKH.js";
|
|
42
44
|
import "./chunk-FIEWO4J4.js";
|
|
43
45
|
export {
|
|
44
46
|
EMPTY_WARNINGS,
|
|
45
47
|
SYSTEM_ORDER,
|
|
48
|
+
SatOsbTable,
|
|
46
49
|
WarningAccumulator,
|
|
47
50
|
biasMetres,
|
|
48
51
|
clkBias,
|