gnss-js 1.28.0 → 1.30.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-O65WA6CM.js → chunk-CRFFUU5Y.js} +42 -24
- package/dist/{chunk-4KMWWCUR.js → chunk-GPEP67TG.js} +63 -1
- package/dist/{sp3-BAq8l39b.d.ts → clk-DGVBGRzA.d.cts} +27 -1
- package/dist/{sp3-BAq8l39b.d.cts → clk-DGVBGRzA.d.ts} +27 -1
- package/dist/index.cjs +144 -63
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -3
- package/dist/positioning.cjs +62 -23
- package/dist/positioning.d.cts +6 -1
- package/dist/positioning.d.ts +6 -1
- package/dist/positioning.js +2 -2
- package/dist/rinex.cjs +64 -0
- package/dist/rinex.d.cts +1 -1
- package/dist/rinex.d.ts +1 -1
- package/dist/rinex.js +6 -2
- package/package.json +1 -1
- /package/dist/{chunk-6GTS5MVI.js → chunk-KDM2NVBO.js} +0 -0
|
@@ -10,8 +10,9 @@ import {
|
|
|
10
10
|
getEnuDifference
|
|
11
11
|
} from "./chunk-37QNKGTC.js";
|
|
12
12
|
import {
|
|
13
|
+
clkBias,
|
|
13
14
|
sp3Position
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-GPEP67TG.js";
|
|
15
16
|
import {
|
|
16
17
|
C_LIGHT,
|
|
17
18
|
OMEGA_E
|
|
@@ -1582,7 +1583,7 @@ function sagnacRotate(x, y, z, travelS) {
|
|
|
1582
1583
|
const s = Math.sin(theta);
|
|
1583
1584
|
return [x * c + y * s, -x * s + y * c, z];
|
|
1584
1585
|
}
|
|
1585
|
-
function satStateAtEmission(sp3, prn, recvTimeMs, rcv) {
|
|
1586
|
+
function satStateAtEmission(sp3, prn, recvTimeMs, rcv, clk) {
|
|
1586
1587
|
let travelS = 0.075;
|
|
1587
1588
|
let sx = 0;
|
|
1588
1589
|
let sy = 0;
|
|
@@ -1601,7 +1602,7 @@ function satStateAtEmission(sp3, prn, recvTimeMs, rcv) {
|
|
|
1601
1602
|
const vz = (pPlus.z - pMinus.z) / 1;
|
|
1602
1603
|
velDotPos = p.x * vx + p.y * vy + p.z * vz;
|
|
1603
1604
|
}
|
|
1604
|
-
clkS = p.clk;
|
|
1605
|
+
clkS = (clk && clkBias(clk, prn, tEmit)) ?? p.clk;
|
|
1605
1606
|
const [rx, ry, rz] = sagnacRotate(p.x, p.y, p.z, travelS);
|
|
1606
1607
|
sx = rx;
|
|
1607
1608
|
sy = ry;
|
|
@@ -1620,9 +1621,9 @@ function satStateAtEmission(sp3, prn, recvTimeMs, rcv) {
|
|
|
1620
1621
|
var IDX_X = 0;
|
|
1621
1622
|
var IDX_Y = 1;
|
|
1622
1623
|
var IDX_Z = 2;
|
|
1623
|
-
var
|
|
1624
|
-
var
|
|
1625
|
-
var
|
|
1624
|
+
var IDX_ZWD = 3;
|
|
1625
|
+
var NBASE = 4;
|
|
1626
|
+
var CLK_VAR = 1e10;
|
|
1626
1627
|
function solvePpp(epochs, sp3, opts) {
|
|
1627
1628
|
const elevMask = (opts.elevationMaskDeg ?? 10) * Math.PI / 180;
|
|
1628
1629
|
const codeSigma = opts.codeSigma ?? 3;
|
|
@@ -1633,8 +1634,6 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1633
1634
|
opts.aprioriPos[0],
|
|
1634
1635
|
opts.aprioriPos[1],
|
|
1635
1636
|
opts.aprioriPos[2],
|
|
1636
|
-
0,
|
|
1637
|
-
// receiver clock (m)
|
|
1638
1637
|
0.1
|
|
1639
1638
|
// zenith wet delay (m) a priori
|
|
1640
1639
|
];
|
|
@@ -1645,8 +1644,9 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1645
1644
|
P[IDX_X][IDX_X] = 100 * 100;
|
|
1646
1645
|
P[IDX_Y][IDX_Y] = 100 * 100;
|
|
1647
1646
|
P[IDX_Z][IDX_Z] = 100 * 100;
|
|
1648
|
-
P[IDX_CLK][IDX_CLK] = 1e10;
|
|
1649
1647
|
P[IDX_ZWD][IDX_ZWD] = 0.5 * 0.5;
|
|
1648
|
+
const clkIdx = /* @__PURE__ */ new Map();
|
|
1649
|
+
const clockSeeded = /* @__PURE__ */ new Set();
|
|
1650
1650
|
const ambIdx = /* @__PURE__ */ new Map();
|
|
1651
1651
|
const lastSeen = /* @__PURE__ */ new Map();
|
|
1652
1652
|
const mwState = /* @__PURE__ */ new Map();
|
|
@@ -1687,8 +1687,18 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1687
1687
|
if (i === idx) ambIdx.delete(prn);
|
|
1688
1688
|
else if (i > idx) ambIdx.set(prn, i - 1);
|
|
1689
1689
|
}
|
|
1690
|
+
for (const [sys, i] of clkIdx) {
|
|
1691
|
+
if (i > idx) clkIdx.set(sys, i - 1);
|
|
1692
|
+
}
|
|
1693
|
+
};
|
|
1694
|
+
const clockOf = (sys) => {
|
|
1695
|
+
let i = clkIdx.get(sys);
|
|
1696
|
+
if (i === void 0) {
|
|
1697
|
+
i = growState(0, CLK_VAR);
|
|
1698
|
+
clkIdx.set(sys, i);
|
|
1699
|
+
}
|
|
1700
|
+
return i;
|
|
1690
1701
|
};
|
|
1691
|
-
let clockSeeded = false;
|
|
1692
1702
|
const series = [];
|
|
1693
1703
|
const truth = opts.groundTruth;
|
|
1694
1704
|
const t0 = epochs[0]?.timeMs ?? 0;
|
|
@@ -1696,7 +1706,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1696
1706
|
let convergedStreak = 0;
|
|
1697
1707
|
for (let ei = 0; ei < epochs.length; ei++) {
|
|
1698
1708
|
const epoch = epochs[ei];
|
|
1699
|
-
P[
|
|
1709
|
+
for (const ci of clkIdx.values()) P[ci][ci] = CLK_VAR;
|
|
1700
1710
|
P[IDX_ZWD][IDX_ZWD] += ztdQ * (ei > 0 ? 1 : 0);
|
|
1701
1711
|
const rcv = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
1702
1712
|
const [latDeg, , heightM] = ecefToGeodetic(rcv[0], rcv[1], rcv[2]);
|
|
@@ -1706,7 +1716,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1706
1716
|
for (const o of epoch.obs) {
|
|
1707
1717
|
if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
|
|
1708
1718
|
const slip = detectSlip(o, ei);
|
|
1709
|
-
const sat = satStateAtEmission(sp3, o.prn, epoch.timeMs, rcv);
|
|
1719
|
+
const sat = satStateAtEmission(sp3, o.prn, epoch.timeMs, rcv, opts.clk);
|
|
1710
1720
|
if (!sat) continue;
|
|
1711
1721
|
const [elRad, azRad] = getAer(
|
|
1712
1722
|
sat.state.x,
|
|
@@ -1760,21 +1770,29 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1760
1770
|
});
|
|
1761
1771
|
}
|
|
1762
1772
|
const zwd0 = x[IDX_ZWD];
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1773
|
+
const bySys = /* @__PURE__ */ new Map();
|
|
1774
|
+
for (const v of vis) {
|
|
1775
|
+
const sys = v.prn[0];
|
|
1776
|
+
const r = v.pIf - (v.range - v.satClkM + v.tropoFixed + zwd0 * v.mw);
|
|
1777
|
+
const arr = bySys.get(sys);
|
|
1778
|
+
if (arr) arr.push(r);
|
|
1779
|
+
else bySys.set(sys, [r]);
|
|
1780
|
+
}
|
|
1781
|
+
for (const [sys, res] of bySys) {
|
|
1782
|
+
const ci = clockOf(sys);
|
|
1783
|
+
if (!clockSeeded.has(sys)) {
|
|
1784
|
+
res.sort((a, b) => a - b);
|
|
1785
|
+
x[ci] = res[Math.floor(res.length / 2)];
|
|
1786
|
+
clockSeeded.add(sys);
|
|
1770
1787
|
}
|
|
1771
|
-
P[
|
|
1788
|
+
P[ci][ci] = CLK_VAR;
|
|
1772
1789
|
}
|
|
1773
1790
|
let nSats = 0;
|
|
1774
1791
|
let sumPhaseResSq = 0;
|
|
1775
1792
|
let nPhaseRes = 0;
|
|
1776
1793
|
for (const v of vis) {
|
|
1777
|
-
const
|
|
1794
|
+
const ci = clockOf(v.prn[0]);
|
|
1795
|
+
const common = v.range + x[ci] - v.satClkM + v.tropoFixed + zwd0 * v.mw;
|
|
1778
1796
|
let ai = ambIdx.get(v.prn);
|
|
1779
1797
|
if (ai === void 0 || v.slip) {
|
|
1780
1798
|
const bInit = v.lIf - (common + v.windupM);
|
|
@@ -1799,13 +1817,13 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1799
1817
|
h[IDX_X] = -v.e[0];
|
|
1800
1818
|
h[IDX_Y] = -v.e[1];
|
|
1801
1819
|
h[IDX_Z] = -v.e[2];
|
|
1802
|
-
h[
|
|
1820
|
+
h[ci] = 1;
|
|
1803
1821
|
h[IDX_ZWD] = v.mw;
|
|
1804
1822
|
const innov = v.pIf - common;
|
|
1805
1823
|
if (Math.abs(innov) < 1e6) ekfUpdateScalar(x, P, h, innov, rCode, 4);
|
|
1806
1824
|
}
|
|
1807
1825
|
{
|
|
1808
|
-
const commonPh = v.range + x[
|
|
1826
|
+
const commonPh = v.range + x[ci] - v.satClkM + v.tropoFixed + x[IDX_ZWD] * v.mw;
|
|
1809
1827
|
const innov = v.lIf - (commonPh + v.windupM + x[ai]);
|
|
1810
1828
|
if (Math.abs(innov) > 0.15) {
|
|
1811
1829
|
x[ai] = v.lIf - (commonPh + v.windupM);
|
|
@@ -1819,7 +1837,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1819
1837
|
h[IDX_X] = -v.e[0];
|
|
1820
1838
|
h[IDX_Y] = -v.e[1];
|
|
1821
1839
|
h[IDX_Z] = -v.e[2];
|
|
1822
|
-
h[
|
|
1840
|
+
h[ci] = 1;
|
|
1823
1841
|
h[IDX_ZWD] = v.mw;
|
|
1824
1842
|
h[ai] = 1;
|
|
1825
1843
|
if (ekfUpdateScalar(x, P, h, innov, rPhase, 4)) {
|
|
@@ -114,7 +114,69 @@ function sp3Position(sp3, prn, tMs, order = 9) {
|
|
|
114
114
|
return { x, y, z, clk };
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
// src/rinex/clk.ts
|
|
118
|
+
var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
|
|
119
|
+
function parseClk(text) {
|
|
120
|
+
const sats = {};
|
|
121
|
+
let inData = false;
|
|
122
|
+
for (const line of text.split("\n")) {
|
|
123
|
+
if (!inData) {
|
|
124
|
+
if (line.includes("END OF HEADER")) inData = true;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (line.length < 3 || line[0] !== "A" || line[1] !== "S") continue;
|
|
128
|
+
const p = line.slice(2).trim().split(/\s+/);
|
|
129
|
+
if (p.length < 9) continue;
|
|
130
|
+
const prn = p[0];
|
|
131
|
+
const y = +p[1];
|
|
132
|
+
const mo = +p[2];
|
|
133
|
+
const d = +p[3];
|
|
134
|
+
const h = +p[4];
|
|
135
|
+
const mi = +p[5];
|
|
136
|
+
const s = +p[6];
|
|
137
|
+
const bias = +p[8];
|
|
138
|
+
if (!Number.isFinite(bias)) continue;
|
|
139
|
+
const t = Date.UTC(y, mo - 1, d, h, mi, Math.floor(s)) + s % 1 * 1e3;
|
|
140
|
+
let e = sats[prn];
|
|
141
|
+
if (!e) {
|
|
142
|
+
e = { t: [], c: [] };
|
|
143
|
+
sats[prn] = e;
|
|
144
|
+
}
|
|
145
|
+
e.t.push(t);
|
|
146
|
+
e.c.push(bias);
|
|
147
|
+
}
|
|
148
|
+
let intervalSec = 30;
|
|
149
|
+
for (const e of Object.values(sats)) {
|
|
150
|
+
if (e.t.length >= 2) {
|
|
151
|
+
intervalSec = Math.round((e.t[1] - e.t[0]) / 1e3);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return { sats, intervalSec };
|
|
156
|
+
}
|
|
157
|
+
function clkBias(clk, prn, tMs) {
|
|
158
|
+
const e = clk.sats[prn];
|
|
159
|
+
if (!e || e.t.length === 0) return null;
|
|
160
|
+
const { t, c } = e;
|
|
161
|
+
let lo = 0;
|
|
162
|
+
let hi = t.length - 1;
|
|
163
|
+
if (tMs < t[0] || tMs > t[hi]) return null;
|
|
164
|
+
while (lo < hi) {
|
|
165
|
+
const mid = lo + hi + 1 >> 1;
|
|
166
|
+
if (t[mid] <= tMs) lo = mid;
|
|
167
|
+
else hi = mid - 1;
|
|
168
|
+
}
|
|
169
|
+
if (t[lo] === tMs || lo === t.length - 1) return c[lo];
|
|
170
|
+
const t0 = t[lo];
|
|
171
|
+
const t1 = t[lo + 1];
|
|
172
|
+
if (t1 - t0 > clk.intervalSec * 1e3 * 4) return null;
|
|
173
|
+
const f = (tMs - t0) / (t1 - t0);
|
|
174
|
+
return c[lo] + f * (c[lo + 1] - c[lo]);
|
|
175
|
+
}
|
|
176
|
+
|
|
117
177
|
export {
|
|
118
178
|
parseSp3,
|
|
119
|
-
sp3Position
|
|
179
|
+
sp3Position,
|
|
180
|
+
parseClk,
|
|
181
|
+
clkBias
|
|
120
182
|
};
|
|
@@ -67,4 +67,30 @@ declare function sp3Position(sp3: Sp3File, prn: string, tMs: number, order?: num
|
|
|
67
67
|
clk: number | null;
|
|
68
68
|
} | null;
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
/**
|
|
71
|
+
* RINEX CLOCK (.CLK) parser — high-rate (typically 30 s) precise satellite
|
|
72
|
+
* clock corrections, the accuracy-limiting term for PPP that SP3's 5-minute
|
|
73
|
+
* (linearly interpolated) clocks cannot match.
|
|
74
|
+
*
|
|
75
|
+
* Only `AS` (satellite) records are kept; `AR` (station) records — the bulk
|
|
76
|
+
* of a combined file — are skipped. Clock bias is in seconds.
|
|
77
|
+
*/
|
|
78
|
+
interface ClkFile {
|
|
79
|
+
/** prn → time-sorted samples { t: GPS-scale ms, c: clock bias (s) }. */
|
|
80
|
+
sats: Record<string, {
|
|
81
|
+
t: number[];
|
|
82
|
+
c: number[];
|
|
83
|
+
}>;
|
|
84
|
+
/** Nominal sampling interval (s), inferred from the first satellite. */
|
|
85
|
+
intervalSec: number;
|
|
86
|
+
}
|
|
87
|
+
/** Parse a RINEX CLOCK file. */
|
|
88
|
+
declare function parseClk(text: string): ClkFile;
|
|
89
|
+
/**
|
|
90
|
+
* Satellite clock bias (seconds) at an arbitrary time by linear
|
|
91
|
+
* interpolation between the bracketing samples. Returns null outside the
|
|
92
|
+
* span or across a gap larger than 4 sampling intervals.
|
|
93
|
+
*/
|
|
94
|
+
declare function clkBias(clk: ClkFile, prn: string, tMs: number): number | null;
|
|
95
|
+
|
|
96
|
+
export { type ClkFile as C, type IonexGrid as I, type Sp3File as S, type Sp3Sample as a, parseIonex as b, clkBias as c, parseSp3 as d, parseClk as p, sp3Position as s };
|
|
@@ -67,4 +67,30 @@ declare function sp3Position(sp3: Sp3File, prn: string, tMs: number, order?: num
|
|
|
67
67
|
clk: number | null;
|
|
68
68
|
} | null;
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
/**
|
|
71
|
+
* RINEX CLOCK (.CLK) parser — high-rate (typically 30 s) precise satellite
|
|
72
|
+
* clock corrections, the accuracy-limiting term for PPP that SP3's 5-minute
|
|
73
|
+
* (linearly interpolated) clocks cannot match.
|
|
74
|
+
*
|
|
75
|
+
* Only `AS` (satellite) records are kept; `AR` (station) records — the bulk
|
|
76
|
+
* of a combined file — are skipped. Clock bias is in seconds.
|
|
77
|
+
*/
|
|
78
|
+
interface ClkFile {
|
|
79
|
+
/** prn → time-sorted samples { t: GPS-scale ms, c: clock bias (s) }. */
|
|
80
|
+
sats: Record<string, {
|
|
81
|
+
t: number[];
|
|
82
|
+
c: number[];
|
|
83
|
+
}>;
|
|
84
|
+
/** Nominal sampling interval (s), inferred from the first satellite. */
|
|
85
|
+
intervalSec: number;
|
|
86
|
+
}
|
|
87
|
+
/** Parse a RINEX CLOCK file. */
|
|
88
|
+
declare function parseClk(text: string): ClkFile;
|
|
89
|
+
/**
|
|
90
|
+
* Satellite clock bias (seconds) at an arbitrary time by linear
|
|
91
|
+
* interpolation between the bracketing samples. Returns null outside the
|
|
92
|
+
* span or across a gap larger than 4 sampling intervals.
|
|
93
|
+
*/
|
|
94
|
+
declare function clkBias(clk: ClkFile, prn: string, tMs: number): number | null;
|
|
95
|
+
|
|
96
|
+
export { type ClkFile as C, type IonexGrid as I, type Sp3File as S, type Sp3Sample as a, parseIonex as b, clkBias as c, parseSp3 as d, parseClk as p, sp3Position as s };
|
package/dist/index.cjs
CHANGED
|
@@ -119,6 +119,7 @@ __export(src_exports, {
|
|
|
119
119
|
buildObsIndices: () => buildObsIndices,
|
|
120
120
|
buildPppAntenna: () => buildPppAntenna,
|
|
121
121
|
clampUnit: () => clampUnit,
|
|
122
|
+
clkBias: () => clkBias,
|
|
122
123
|
computeAllPositions: () => computeAllPositions,
|
|
123
124
|
computeDop: () => computeDop,
|
|
124
125
|
computeIonoRate: () => computeIonoRate,
|
|
@@ -237,6 +238,7 @@ __export(src_exports, {
|
|
|
237
238
|
padR: () => padR,
|
|
238
239
|
parseAntex: () => parseAntex,
|
|
239
240
|
parseBinex: () => parseBinex,
|
|
241
|
+
parseClk: () => parseClk,
|
|
240
242
|
parseCrxDataLine: () => parseCrxDataLine,
|
|
241
243
|
parseIonex: () => parseIonex,
|
|
242
244
|
parseNavFile: () => parseNavFile,
|
|
@@ -3896,6 +3898,66 @@ function sp3Position(sp3, prn, tMs, order = 9) {
|
|
|
3896
3898
|
return { x, y, z, clk };
|
|
3897
3899
|
}
|
|
3898
3900
|
|
|
3901
|
+
// src/rinex/clk.ts
|
|
3902
|
+
var GPS_EPOCH_MS4 = Date.UTC(1980, 0, 6);
|
|
3903
|
+
function parseClk(text) {
|
|
3904
|
+
const sats = {};
|
|
3905
|
+
let inData = false;
|
|
3906
|
+
for (const line of text.split("\n")) {
|
|
3907
|
+
if (!inData) {
|
|
3908
|
+
if (line.includes("END OF HEADER")) inData = true;
|
|
3909
|
+
continue;
|
|
3910
|
+
}
|
|
3911
|
+
if (line.length < 3 || line[0] !== "A" || line[1] !== "S") continue;
|
|
3912
|
+
const p = line.slice(2).trim().split(/\s+/);
|
|
3913
|
+
if (p.length < 9) continue;
|
|
3914
|
+
const prn = p[0];
|
|
3915
|
+
const y = +p[1];
|
|
3916
|
+
const mo = +p[2];
|
|
3917
|
+
const d = +p[3];
|
|
3918
|
+
const h = +p[4];
|
|
3919
|
+
const mi = +p[5];
|
|
3920
|
+
const s = +p[6];
|
|
3921
|
+
const bias = +p[8];
|
|
3922
|
+
if (!Number.isFinite(bias)) continue;
|
|
3923
|
+
const t = Date.UTC(y, mo - 1, d, h, mi, Math.floor(s)) + s % 1 * 1e3;
|
|
3924
|
+
let e = sats[prn];
|
|
3925
|
+
if (!e) {
|
|
3926
|
+
e = { t: [], c: [] };
|
|
3927
|
+
sats[prn] = e;
|
|
3928
|
+
}
|
|
3929
|
+
e.t.push(t);
|
|
3930
|
+
e.c.push(bias);
|
|
3931
|
+
}
|
|
3932
|
+
let intervalSec = 30;
|
|
3933
|
+
for (const e of Object.values(sats)) {
|
|
3934
|
+
if (e.t.length >= 2) {
|
|
3935
|
+
intervalSec = Math.round((e.t[1] - e.t[0]) / 1e3);
|
|
3936
|
+
break;
|
|
3937
|
+
}
|
|
3938
|
+
}
|
|
3939
|
+
return { sats, intervalSec };
|
|
3940
|
+
}
|
|
3941
|
+
function clkBias(clk, prn, tMs) {
|
|
3942
|
+
const e = clk.sats[prn];
|
|
3943
|
+
if (!e || e.t.length === 0) return null;
|
|
3944
|
+
const { t, c } = e;
|
|
3945
|
+
let lo = 0;
|
|
3946
|
+
let hi = t.length - 1;
|
|
3947
|
+
if (tMs < t[0] || tMs > t[hi]) return null;
|
|
3948
|
+
while (lo < hi) {
|
|
3949
|
+
const mid = lo + hi + 1 >> 1;
|
|
3950
|
+
if (t[mid] <= tMs) lo = mid;
|
|
3951
|
+
else hi = mid - 1;
|
|
3952
|
+
}
|
|
3953
|
+
if (t[lo] === tMs || lo === t.length - 1) return c[lo];
|
|
3954
|
+
const t0 = t[lo];
|
|
3955
|
+
const t1 = t[lo + 1];
|
|
3956
|
+
if (t1 - t0 > clk.intervalSec * 1e3 * 4) return null;
|
|
3957
|
+
const f = (tMs - t0) / (t1 - t0);
|
|
3958
|
+
return c[lo] + f * (c[lo + 1] - c[lo]);
|
|
3959
|
+
}
|
|
3960
|
+
|
|
3899
3961
|
// src/rinex/obs-writer-common.ts
|
|
3900
3962
|
function createGzipLineSink() {
|
|
3901
3963
|
const encoder = new TextEncoder();
|
|
@@ -6147,7 +6209,7 @@ var BdsAssembler = class {
|
|
|
6147
6209
|
};
|
|
6148
6210
|
|
|
6149
6211
|
// src/navbits/gal.ts
|
|
6150
|
-
var
|
|
6212
|
+
var GPS_EPOCH_MS5 = Date.UTC(1980, 0, 6);
|
|
6151
6213
|
var SEC_PER_WEEK5 = 7 * 86400;
|
|
6152
6214
|
var HALF_WEEK3 = 302400;
|
|
6153
6215
|
var GST_GPS_WEEK_OFFSET = 1024;
|
|
@@ -6160,7 +6222,7 @@ function galFnavPageCrcOk(page) {
|
|
|
6160
6222
|
return crc24q(page, 214) === getBitU(page, 214, 24);
|
|
6161
6223
|
}
|
|
6162
6224
|
function gpsDate2(week, sec) {
|
|
6163
|
-
return new Date(
|
|
6225
|
+
return new Date(GPS_EPOCH_MS5 + (week * SEC_PER_WEEK5 + sec) * 1e3);
|
|
6164
6226
|
}
|
|
6165
6227
|
function weekOfToe(week, tow, toe) {
|
|
6166
6228
|
if (toe - tow > HALF_WEEK3) return week - 1;
|
|
@@ -6455,7 +6517,7 @@ var GalFnavAssembler = class {
|
|
|
6455
6517
|
};
|
|
6456
6518
|
|
|
6457
6519
|
// src/navbits/glo.ts
|
|
6458
|
-
var
|
|
6520
|
+
var GPS_EPOCH_MS6 = Date.UTC(1980, 0, 6);
|
|
6459
6521
|
var SEC_PER_WEEK6 = 7 * 86400;
|
|
6460
6522
|
var SEC_PER_DAY = 86400;
|
|
6461
6523
|
var GLO_STRING_BYTES = 10;
|
|
@@ -6549,7 +6611,7 @@ function decodeGloStrings(strings, refDate, opts = {}) {
|
|
|
6549
6611
|
const slot = getBitU(b, i, 5);
|
|
6550
6612
|
if (frn1 !== 1 || frn2 !== 2 || frn3 !== 3 || frn4 !== 4) return null;
|
|
6551
6613
|
if (slot < 1 || slot > 27) return null;
|
|
6552
|
-
const utcSec = (getUtcDate(refDate).getTime() -
|
|
6614
|
+
const utcSec = (getUtcDate(refDate).getTime() - GPS_EPOCH_MS6) / 1e3;
|
|
6553
6615
|
const week = Math.floor(utcSec / SEC_PER_WEEK6);
|
|
6554
6616
|
let tow = utcSec - week * SEC_PER_WEEK6;
|
|
6555
6617
|
const tod = tow % SEC_PER_DAY;
|
|
@@ -6564,7 +6626,7 @@ function decodeGloStrings(strings, refDate, opts = {}) {
|
|
|
6564
6626
|
system: "R",
|
|
6565
6627
|
prn: `R${String(slot).padStart(2, "0")}`,
|
|
6566
6628
|
// RINEX GLONASS epochs are UTC: build the UTC toe Date directly.
|
|
6567
|
-
tocDate: new Date(
|
|
6629
|
+
tocDate: new Date(GPS_EPOCH_MS6 + (week * SEC_PER_WEEK6 + tow + toe) * 1e3),
|
|
6568
6630
|
tauN: -tauN,
|
|
6569
6631
|
// RINEX stores −τn; the SIS carries τn (ICD sign)
|
|
6570
6632
|
gammaN,
|
|
@@ -6618,7 +6680,7 @@ var GloStringAssembler = class {
|
|
|
6618
6680
|
};
|
|
6619
6681
|
|
|
6620
6682
|
// src/ubx/rawnav.ts
|
|
6621
|
-
var
|
|
6683
|
+
var GPS_EPOCH_MS7 = Date.UTC(1980, 0, 6);
|
|
6622
6684
|
var SEC_PER_WEEK7 = 7 * 86400;
|
|
6623
6685
|
var two2 = (n) => String(n).padStart(2, "0");
|
|
6624
6686
|
function parseUbxRawNav(data, opts = {}) {
|
|
@@ -6638,7 +6700,7 @@ function parseUbxRawNav(data, opts = {}) {
|
|
|
6638
6700
|
if (week === 0 && opts.refWeek !== void 0) week = opts.refWeek;
|
|
6639
6701
|
if (week > 0) {
|
|
6640
6702
|
refDate = new Date(
|
|
6641
|
-
|
|
6703
|
+
GPS_EPOCH_MS7 + (week * SEC_PER_WEEK7 + rcvTow) * 1e3
|
|
6642
6704
|
);
|
|
6643
6705
|
}
|
|
6644
6706
|
continue;
|
|
@@ -6718,7 +6780,7 @@ function parseUbxRawNav(data, opts = {}) {
|
|
|
6718
6780
|
}
|
|
6719
6781
|
|
|
6720
6782
|
// src/ubx/index.ts
|
|
6721
|
-
var
|
|
6783
|
+
var GPS_EPOCH_MS8 = Date.UTC(1980, 0, 6);
|
|
6722
6784
|
var MS_PER_WEEK3 = 7 * 864e5;
|
|
6723
6785
|
var SIGNALS = {
|
|
6724
6786
|
0: { 0: ["G", "1C"], 3: ["G", "2X"], 4: ["G", "2X"] },
|
|
@@ -6801,7 +6863,7 @@ function parseUbxRawx(data) {
|
|
|
6801
6863
|
if (!codes.includes(sig[1])) codes.push(sig[1]);
|
|
6802
6864
|
}
|
|
6803
6865
|
epochs.push({
|
|
6804
|
-
timeMs:
|
|
6866
|
+
timeMs: GPS_EPOCH_MS8 + week * MS_PER_WEEK3 + Math.round(rcvTow * 1e3),
|
|
6805
6867
|
leapS: leapValid ? leapS : null,
|
|
6806
6868
|
meas
|
|
6807
6869
|
});
|
|
@@ -6872,7 +6934,7 @@ function svidToPrn(svid) {
|
|
|
6872
6934
|
|
|
6873
6935
|
// src/sbf/nav.ts
|
|
6874
6936
|
var PI2 = Math.PI;
|
|
6875
|
-
var
|
|
6937
|
+
var GPS_EPOCH_MS9 = Date.UTC(1980, 0, 6);
|
|
6876
6938
|
var BDT_EPOCH_MS2 = Date.UTC(2006, 0, 1);
|
|
6877
6939
|
var SEC_PER_WEEK8 = 7 * 86400;
|
|
6878
6940
|
var MS_PER_WEEK4 = SEC_PER_WEEK8 * 1e3;
|
|
@@ -6884,7 +6946,7 @@ function adjustWeek(refWeek, wn, mod) {
|
|
|
6884
6946
|
if (offset < -(mod / 2 - 1)) offset += mod;
|
|
6885
6947
|
return refWeek - offset;
|
|
6886
6948
|
}
|
|
6887
|
-
var gpsMs = (week, sec) =>
|
|
6949
|
+
var gpsMs = (week, sec) => GPS_EPOCH_MS9 + week * MS_PER_WEEK4 + sec * 1e3;
|
|
6888
6950
|
var sowOf2 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK8;
|
|
6889
6951
|
function decodeGpsQzsNav(view, b, sys) {
|
|
6890
6952
|
const svid = view.getUint8(b + 14);
|
|
@@ -7034,7 +7096,7 @@ function decodeGloNav(view, b) {
|
|
|
7034
7096
|
const tocDate = new Date(toeGpsMs - leapMs);
|
|
7035
7097
|
const tofGpsMs = gpsMs(wnc, 0) + view.getUint32(b + 8, true);
|
|
7036
7098
|
const tofLeapMs = getGpsLeap(new Date(tofGpsMs)) * 1e3;
|
|
7037
|
-
const messageFrameTime = (tofGpsMs - tofLeapMs -
|
|
7099
|
+
const messageFrameTime = (tofGpsMs - tofLeapMs - GPS_EPOCH_MS9) / 1e3 % SEC_PER_WEEK8;
|
|
7038
7100
|
return {
|
|
7039
7101
|
system: "R",
|
|
7040
7102
|
prn,
|
|
@@ -7306,7 +7368,7 @@ function isFnavDummy(page) {
|
|
|
7306
7368
|
}
|
|
7307
7369
|
|
|
7308
7370
|
// src/sbf/rawnav-bds.ts
|
|
7309
|
-
var
|
|
7371
|
+
var GPS_EPOCH_MS10 = Date.UTC(1980, 0, 6);
|
|
7310
7372
|
var MS_PER_WEEK5 = 7 * 86400 * 1e3;
|
|
7311
7373
|
var TOW_DNU = 4294967295;
|
|
7312
7374
|
var WNC_DNU = 65535;
|
|
@@ -7376,7 +7438,7 @@ function parseSbfGloNav(data) {
|
|
|
7376
7438
|
const eph = assembler.push(
|
|
7377
7439
|
prn,
|
|
7378
7440
|
str,
|
|
7379
|
-
new Date(
|
|
7441
|
+
new Date(GPS_EPOCH_MS10 + wnc * MS_PER_WEEK5 + towMs),
|
|
7380
7442
|
view.getUint8(b + 18) - 8
|
|
7381
7443
|
// FreqNr, offset by 8
|
|
7382
7444
|
);
|
|
@@ -7910,7 +7972,7 @@ function parseSbfHas(data) {
|
|
|
7910
7972
|
|
|
7911
7973
|
// src/sbf/index.ts
|
|
7912
7974
|
var CLIGHT = 299792458;
|
|
7913
|
-
var
|
|
7975
|
+
var GPS_EPOCH_MS11 = Date.UTC(1980, 0, 6);
|
|
7914
7976
|
var MS_PER_WEEK6 = 7 * 864e5;
|
|
7915
7977
|
var M3_SYS = ["G", "R", "E", "C", "S", "J", "I"];
|
|
7916
7978
|
var M3_PR_BASE = [19e6, 19e6, 22e6, 2e7, 34e6, 34e6, 34e6];
|
|
@@ -8564,7 +8626,7 @@ function parseSbfMeas(data) {
|
|
|
8564
8626
|
const tow = view.getUint32(i + 8, true);
|
|
8565
8627
|
const wnc = view.getUint16(i + 12, true);
|
|
8566
8628
|
if (tow !== 4294967295 && wnc !== 65535) {
|
|
8567
|
-
ensureEpoch(
|
|
8629
|
+
ensureEpoch(GPS_EPOCH_MS11 + wnc * MS_PER_WEEK6 + tow);
|
|
8568
8630
|
if (id === 4109) decodeMeas3Ranges(i, tow);
|
|
8569
8631
|
else if (id === 4110) decodeMeas3CN0(i, len);
|
|
8570
8632
|
else if (id === 4111) decodeMeas3Doppler(i, len);
|
|
@@ -8629,15 +8691,15 @@ var ID_GALEPHEMERIS = 1122;
|
|
|
8629
8691
|
var ID_QZSSEPHEMERIS = 1336;
|
|
8630
8692
|
var ID_GPSEPHEM = 7;
|
|
8631
8693
|
var ID_BDSEPHEMERIS = 1696;
|
|
8632
|
-
var
|
|
8694
|
+
var GPS_EPOCH_MS12 = Date.UTC(1980, 0, 6);
|
|
8633
8695
|
var BDT_EPOCH_MS3 = Date.UTC(2006, 0, 1);
|
|
8634
8696
|
var SEC_PER_WEEK9 = 7 * 86400;
|
|
8635
8697
|
var SEC_PER_DAY2 = 86400;
|
|
8636
8698
|
var MS_PER_WEEK7 = SEC_PER_WEEK9 * 1e3;
|
|
8637
|
-
var gpsMs2 = (week, sec) =>
|
|
8699
|
+
var gpsMs2 = (week, sec) => GPS_EPOCH_MS12 + week * MS_PER_WEEK7 + sec * 1e3;
|
|
8638
8700
|
var sowOf3 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK9;
|
|
8639
8701
|
function nearWeekMs(refMs, sow) {
|
|
8640
|
-
const refWeek = Math.floor((refMs -
|
|
8702
|
+
const refWeek = Math.floor((refMs - GPS_EPOCH_MS12) / MS_PER_WEEK7);
|
|
8641
8703
|
let ms = gpsMs2(refWeek, sow);
|
|
8642
8704
|
if (ms < refMs - MS_PER_WEEK7 / 2) ms += MS_PER_WEEK7;
|
|
8643
8705
|
else if (ms > refMs + MS_PER_WEEK7 / 2) ms -= MS_PER_WEEK7;
|
|
@@ -8664,9 +8726,9 @@ function decodeGloEphemeris(view, p) {
|
|
|
8664
8726
|
tof += Math.floor(tow / SEC_PER_DAY2) * SEC_PER_DAY2;
|
|
8665
8727
|
if (tof < tow - 43200) tof += SEC_PER_DAY2;
|
|
8666
8728
|
else if (tof > tow + 43200) tof -= SEC_PER_DAY2;
|
|
8667
|
-
const toeGpsMs =
|
|
8668
|
-
const tofGpsMs =
|
|
8669
|
-
const tofUtcSec = (getUtcDate(new Date(tofGpsMs)).getTime() -
|
|
8729
|
+
const toeGpsMs = GPS_EPOCH_MS12 + (week * SEC_PER_WEEK9 + tow) * 1e3;
|
|
8730
|
+
const tofGpsMs = GPS_EPOCH_MS12 + (week * SEC_PER_WEEK9 + tof) * 1e3;
|
|
8731
|
+
const tofUtcSec = (getUtcDate(new Date(tofGpsMs)).getTime() - GPS_EPOCH_MS12) / 1e3;
|
|
8670
8732
|
return {
|
|
8671
8733
|
system: "R",
|
|
8672
8734
|
prn: `R${String(slot).padStart(2, "0")}`,
|
|
@@ -8731,7 +8793,7 @@ function decodeGalEphemeris(view, p, headerMs) {
|
|
|
8731
8793
|
omega: view.getFloat64(p + 60, true),
|
|
8732
8794
|
omegaDot: view.getFloat64(p + 140, true),
|
|
8733
8795
|
idot: view.getFloat64(p + 124, true),
|
|
8734
|
-
week: Math.floor((toeMs -
|
|
8796
|
+
week: Math.floor((toeMs - GPS_EPOCH_MS12) / MS_PER_WEEK7),
|
|
8735
8797
|
// RINEX Galileo SVH bit layout (E1B DVS/HS in bits 0-2, E5a in
|
|
8736
8798
|
// 3-5, E5b in 6-8) — same packing as RTKLIB.
|
|
8737
8799
|
svHealth: svhE5b << 7 | dvsE5b << 6 | svhE5a << 4 | dvsE5a << 3 | svhE1b << 1 | dvsE1b,
|
|
@@ -8903,7 +8965,7 @@ function parseNovatelNav(data) {
|
|
|
8903
8965
|
}
|
|
8904
8966
|
|
|
8905
8967
|
// src/novatel/index.ts
|
|
8906
|
-
var
|
|
8968
|
+
var GPS_EPOCH_MS13 = Date.UTC(1980, 0, 6);
|
|
8907
8969
|
var MS_PER_WEEK8 = 7 * 864e5;
|
|
8908
8970
|
var HDR = 28;
|
|
8909
8971
|
var ID_RANGE = 43;
|
|
@@ -9073,7 +9135,7 @@ function parseNovatelRange(data) {
|
|
|
9073
9135
|
if (!codes.includes(code)) codes.push(code);
|
|
9074
9136
|
}
|
|
9075
9137
|
epochs.push({
|
|
9076
|
-
timeMs:
|
|
9138
|
+
timeMs: GPS_EPOCH_MS13 + week * MS_PER_WEEK8 + towMs,
|
|
9077
9139
|
meas
|
|
9078
9140
|
});
|
|
9079
9141
|
}
|
|
@@ -9125,7 +9187,7 @@ function parseNovatelRange(data) {
|
|
|
9125
9187
|
if (!codes.includes(code)) codes.push(code);
|
|
9126
9188
|
}
|
|
9127
9189
|
epochs.push({
|
|
9128
|
-
timeMs:
|
|
9190
|
+
timeMs: GPS_EPOCH_MS13 + week * MS_PER_WEEK8 + towMs,
|
|
9129
9191
|
meas
|
|
9130
9192
|
});
|
|
9131
9193
|
}
|
|
@@ -9176,11 +9238,11 @@ function* trimbleFrames(data, stats) {
|
|
|
9176
9238
|
}
|
|
9177
9239
|
|
|
9178
9240
|
// src/trimble/nav.ts
|
|
9179
|
-
var
|
|
9241
|
+
var GPS_EPOCH_MS14 = Date.UTC(1980, 0, 6);
|
|
9180
9242
|
var SEC_PER_WEEK10 = 7 * 86400;
|
|
9181
9243
|
var MS_PER_WEEK9 = SEC_PER_WEEK10 * 1e3;
|
|
9182
9244
|
var GPS_PI2 = 3.1415926535898;
|
|
9183
|
-
var gpsMs3 = (week, sec) =>
|
|
9245
|
+
var gpsMs3 = (week, sec) => GPS_EPOCH_MS14 + week * MS_PER_WEEK9 + sec * 1e3;
|
|
9184
9246
|
var sowOf4 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK10;
|
|
9185
9247
|
var SUB_GPS_EPHEMERIS = 1;
|
|
9186
9248
|
var SUB_ION_UTC = 3;
|
|
@@ -9282,7 +9344,7 @@ function parseTrimbleNav(data) {
|
|
|
9282
9344
|
}
|
|
9283
9345
|
|
|
9284
9346
|
// src/trimble/index.ts
|
|
9285
|
-
var
|
|
9347
|
+
var GPS_EPOCH_MS15 = Date.UTC(1980, 0, 6);
|
|
9286
9348
|
var MS_PER_WEEK10 = 7 * 864e5;
|
|
9287
9349
|
var REC_TYPE_27 = 6;
|
|
9288
9350
|
var SYS = {
|
|
@@ -9480,7 +9542,7 @@ function decodeEpoch(epoch, epochs, obsCodes) {
|
|
|
9480
9542
|
o += c.length;
|
|
9481
9543
|
}
|
|
9482
9544
|
const dv = new DataView(M.buffer, M.byteOffset, M.byteLength);
|
|
9483
|
-
const timeMs =
|
|
9545
|
+
const timeMs = GPS_EPOCH_MS15 + epoch.week * MS_PER_WEEK10 + epoch.towMs;
|
|
9484
9546
|
const meas = [];
|
|
9485
9547
|
let q = 0;
|
|
9486
9548
|
for (let sv = 0; sv < epoch.nsv && q + 8 <= M.length; sv++) {
|
|
@@ -9661,13 +9723,13 @@ function* binexRecords(data, view, stats) {
|
|
|
9661
9723
|
}
|
|
9662
9724
|
|
|
9663
9725
|
// src/binex/nav.ts
|
|
9664
|
-
var
|
|
9726
|
+
var GPS_EPOCH_MS16 = Date.UTC(1980, 0, 6);
|
|
9665
9727
|
var GLO_DAY0_MS = Date.UTC(1980, 0, 1);
|
|
9666
9728
|
var BDT_EPOCH_MS4 = Date.UTC(2006, 0, 1);
|
|
9667
9729
|
var SEC_PER_WEEK11 = 7 * 86400;
|
|
9668
9730
|
var MS_PER_WEEK11 = SEC_PER_WEEK11 * 1e3;
|
|
9669
9731
|
var SC2RAD = GPS_PI;
|
|
9670
|
-
var gpsMs4 = (week, sec) =>
|
|
9732
|
+
var gpsMs4 = (week, sec) => GPS_EPOCH_MS16 + week * MS_PER_WEEK11 + sec * 1e3;
|
|
9671
9733
|
var sowOf5 = (dateMs) => (dateMs / 1e3 % SEC_PER_WEEK11 + SEC_PER_WEEK11) % SEC_PER_WEEK11;
|
|
9672
9734
|
var two5 = (n) => String(n).padStart(2, "0");
|
|
9673
9735
|
var Reader = class {
|
|
@@ -9955,7 +10017,7 @@ function decodeBinexEph(view, body, len, le) {
|
|
|
9955
10017
|
}
|
|
9956
10018
|
|
|
9957
10019
|
// src/binex/index.ts
|
|
9958
|
-
var
|
|
10020
|
+
var GPS_EPOCH_MS17 = Date.UTC(1980, 0, 6);
|
|
9959
10021
|
var CLIGHT2 = 299792458;
|
|
9960
10022
|
var OBS_CODES = {
|
|
9961
10023
|
0: [
|
|
@@ -10213,7 +10275,7 @@ function decodeObsRecord(data, view, body, len, obsCodes) {
|
|
|
10213
10275
|
p += 4;
|
|
10214
10276
|
const msec = view.getUint16(p);
|
|
10215
10277
|
p += 2;
|
|
10216
|
-
const timeMs =
|
|
10278
|
+
const timeMs = GPS_EPOCH_MS17 + min * 6e4 + msec;
|
|
10217
10279
|
const flag = data[p++];
|
|
10218
10280
|
const nsat = (flag & 63) + 1;
|
|
10219
10281
|
if (flag & 128) p += 3;
|
|
@@ -10299,7 +10361,7 @@ function parseBinex(data) {
|
|
|
10299
10361
|
var GM_GPS = 3986005e8;
|
|
10300
10362
|
var GM_GAL = 3986004418e5;
|
|
10301
10363
|
var GM_BDS = 3986004418e5;
|
|
10302
|
-
var
|
|
10364
|
+
var GPS_EPOCH_MS18 = Date.UTC(1980, 0, 6);
|
|
10303
10365
|
var BDT_EPOCH_MS5 = Date.UTC(2006, 0, 1);
|
|
10304
10366
|
var WEEK_MS = 6048e5;
|
|
10305
10367
|
var BDT_MINUS_GPST_MS = 14e3;
|
|
@@ -10308,7 +10370,7 @@ function almanacEpochMs(alm) {
|
|
|
10308
10370
|
if (alm.system === "C") {
|
|
10309
10371
|
return BDT_EPOCH_MS5 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3 + BDT_MINUS_GPST_MS;
|
|
10310
10372
|
}
|
|
10311
|
-
return
|
|
10373
|
+
return GPS_EPOCH_MS18 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3;
|
|
10312
10374
|
}
|
|
10313
10375
|
function almanacSatPosition(alm, timeMs) {
|
|
10314
10376
|
const GM = alm.system === "E" ? GM_GAL : alm.system === "C" ? GM_BDS : GM_GPS;
|
|
@@ -10817,10 +10879,10 @@ function selectBest(ephs, timeMs) {
|
|
|
10817
10879
|
}
|
|
10818
10880
|
return best;
|
|
10819
10881
|
}
|
|
10820
|
-
var
|
|
10882
|
+
var GPS_EPOCH_MS19 = START_GPS_TIME.getTime();
|
|
10821
10883
|
var MS_PER_WEEK12 = 7 * 864e5;
|
|
10822
10884
|
var BDS_EPOCH_MS = START_BDS_TIME.getTime();
|
|
10823
|
-
var GAL_EPOCH_MS =
|
|
10885
|
+
var GAL_EPOCH_MS = GPS_EPOCH_MS19 + 1024 * MS_PER_WEEK12;
|
|
10824
10886
|
function ephInfoToEphemeris(info) {
|
|
10825
10887
|
const sys = info.prn.charAt(0);
|
|
10826
10888
|
if (sys === "R") {
|
|
@@ -10871,8 +10933,8 @@ function ephInfoToEphemeris(info) {
|
|
|
10871
10933
|
} else if (sys === "E") {
|
|
10872
10934
|
epochMs = GAL_EPOCH_MS;
|
|
10873
10935
|
} else {
|
|
10874
|
-
epochMs =
|
|
10875
|
-
const weeksNow = (info.lastReceived -
|
|
10936
|
+
epochMs = GPS_EPOCH_MS19;
|
|
10937
|
+
const weeksNow = (info.lastReceived - GPS_EPOCH_MS19) / MS_PER_WEEK12;
|
|
10876
10938
|
week += 1024 * Math.round((weeksNow - week) / 1024);
|
|
10877
10939
|
}
|
|
10878
10940
|
const tocDate = new Date(epochMs + week * MS_PER_WEEK12 + tocSec * 1e3);
|
|
@@ -12834,7 +12896,7 @@ function sagnacRotate(x, y, z, travelS) {
|
|
|
12834
12896
|
const s = Math.sin(theta);
|
|
12835
12897
|
return [x * c + y * s, -x * s + y * c, z];
|
|
12836
12898
|
}
|
|
12837
|
-
function satStateAtEmission(sp3, prn, recvTimeMs, rcv) {
|
|
12899
|
+
function satStateAtEmission(sp3, prn, recvTimeMs, rcv, clk) {
|
|
12838
12900
|
let travelS = 0.075;
|
|
12839
12901
|
let sx = 0;
|
|
12840
12902
|
let sy = 0;
|
|
@@ -12853,7 +12915,7 @@ function satStateAtEmission(sp3, prn, recvTimeMs, rcv) {
|
|
|
12853
12915
|
const vz = (pPlus.z - pMinus.z) / 1;
|
|
12854
12916
|
velDotPos = p.x * vx + p.y * vy + p.z * vz;
|
|
12855
12917
|
}
|
|
12856
|
-
clkS = p.clk;
|
|
12918
|
+
clkS = (clk && clkBias(clk, prn, tEmit)) ?? p.clk;
|
|
12857
12919
|
const [rx, ry, rz] = sagnacRotate(p.x, p.y, p.z, travelS);
|
|
12858
12920
|
sx = rx;
|
|
12859
12921
|
sy = ry;
|
|
@@ -12872,9 +12934,9 @@ function satStateAtEmission(sp3, prn, recvTimeMs, rcv) {
|
|
|
12872
12934
|
var IDX_X = 0;
|
|
12873
12935
|
var IDX_Y = 1;
|
|
12874
12936
|
var IDX_Z = 2;
|
|
12875
|
-
var
|
|
12876
|
-
var
|
|
12877
|
-
var
|
|
12937
|
+
var IDX_ZWD = 3;
|
|
12938
|
+
var NBASE = 4;
|
|
12939
|
+
var CLK_VAR = 1e10;
|
|
12878
12940
|
function solvePpp(epochs, sp3, opts) {
|
|
12879
12941
|
const elevMask = (opts.elevationMaskDeg ?? 10) * Math.PI / 180;
|
|
12880
12942
|
const codeSigma = opts.codeSigma ?? 3;
|
|
@@ -12885,8 +12947,6 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
12885
12947
|
opts.aprioriPos[0],
|
|
12886
12948
|
opts.aprioriPos[1],
|
|
12887
12949
|
opts.aprioriPos[2],
|
|
12888
|
-
0,
|
|
12889
|
-
// receiver clock (m)
|
|
12890
12950
|
0.1
|
|
12891
12951
|
// zenith wet delay (m) a priori
|
|
12892
12952
|
];
|
|
@@ -12897,8 +12957,9 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
12897
12957
|
P[IDX_X][IDX_X] = 100 * 100;
|
|
12898
12958
|
P[IDX_Y][IDX_Y] = 100 * 100;
|
|
12899
12959
|
P[IDX_Z][IDX_Z] = 100 * 100;
|
|
12900
|
-
P[IDX_CLK][IDX_CLK] = 1e10;
|
|
12901
12960
|
P[IDX_ZWD][IDX_ZWD] = 0.5 * 0.5;
|
|
12961
|
+
const clkIdx = /* @__PURE__ */ new Map();
|
|
12962
|
+
const clockSeeded = /* @__PURE__ */ new Set();
|
|
12902
12963
|
const ambIdx = /* @__PURE__ */ new Map();
|
|
12903
12964
|
const lastSeen = /* @__PURE__ */ new Map();
|
|
12904
12965
|
const mwState = /* @__PURE__ */ new Map();
|
|
@@ -12939,8 +13000,18 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
12939
13000
|
if (i === idx) ambIdx.delete(prn);
|
|
12940
13001
|
else if (i > idx) ambIdx.set(prn, i - 1);
|
|
12941
13002
|
}
|
|
13003
|
+
for (const [sys, i] of clkIdx) {
|
|
13004
|
+
if (i > idx) clkIdx.set(sys, i - 1);
|
|
13005
|
+
}
|
|
13006
|
+
};
|
|
13007
|
+
const clockOf = (sys) => {
|
|
13008
|
+
let i = clkIdx.get(sys);
|
|
13009
|
+
if (i === void 0) {
|
|
13010
|
+
i = growState(0, CLK_VAR);
|
|
13011
|
+
clkIdx.set(sys, i);
|
|
13012
|
+
}
|
|
13013
|
+
return i;
|
|
12942
13014
|
};
|
|
12943
|
-
let clockSeeded = false;
|
|
12944
13015
|
const series = [];
|
|
12945
13016
|
const truth = opts.groundTruth;
|
|
12946
13017
|
const t0 = epochs[0]?.timeMs ?? 0;
|
|
@@ -12948,7 +13019,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
12948
13019
|
let convergedStreak = 0;
|
|
12949
13020
|
for (let ei = 0; ei < epochs.length; ei++) {
|
|
12950
13021
|
const epoch = epochs[ei];
|
|
12951
|
-
P[
|
|
13022
|
+
for (const ci of clkIdx.values()) P[ci][ci] = CLK_VAR;
|
|
12952
13023
|
P[IDX_ZWD][IDX_ZWD] += ztdQ * (ei > 0 ? 1 : 0);
|
|
12953
13024
|
const rcv = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
12954
13025
|
const [latDeg, , heightM] = ecefToGeodetic(rcv[0], rcv[1], rcv[2]);
|
|
@@ -12958,7 +13029,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
12958
13029
|
for (const o of epoch.obs) {
|
|
12959
13030
|
if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
|
|
12960
13031
|
const slip = detectSlip(o, ei);
|
|
12961
|
-
const sat = satStateAtEmission(sp3, o.prn, epoch.timeMs, rcv);
|
|
13032
|
+
const sat = satStateAtEmission(sp3, o.prn, epoch.timeMs, rcv, opts.clk);
|
|
12962
13033
|
if (!sat) continue;
|
|
12963
13034
|
const [elRad, azRad] = getAer(
|
|
12964
13035
|
sat.state.x,
|
|
@@ -13012,21 +13083,29 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
13012
13083
|
});
|
|
13013
13084
|
}
|
|
13014
13085
|
const zwd0 = x[IDX_ZWD];
|
|
13015
|
-
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
|
|
13020
|
-
|
|
13021
|
-
|
|
13086
|
+
const bySys = /* @__PURE__ */ new Map();
|
|
13087
|
+
for (const v of vis) {
|
|
13088
|
+
const sys = v.prn[0];
|
|
13089
|
+
const r = v.pIf - (v.range - v.satClkM + v.tropoFixed + zwd0 * v.mw);
|
|
13090
|
+
const arr = bySys.get(sys);
|
|
13091
|
+
if (arr) arr.push(r);
|
|
13092
|
+
else bySys.set(sys, [r]);
|
|
13093
|
+
}
|
|
13094
|
+
for (const [sys, res] of bySys) {
|
|
13095
|
+
const ci = clockOf(sys);
|
|
13096
|
+
if (!clockSeeded.has(sys)) {
|
|
13097
|
+
res.sort((a, b) => a - b);
|
|
13098
|
+
x[ci] = res[Math.floor(res.length / 2)];
|
|
13099
|
+
clockSeeded.add(sys);
|
|
13022
13100
|
}
|
|
13023
|
-
P[
|
|
13101
|
+
P[ci][ci] = CLK_VAR;
|
|
13024
13102
|
}
|
|
13025
13103
|
let nSats = 0;
|
|
13026
13104
|
let sumPhaseResSq = 0;
|
|
13027
13105
|
let nPhaseRes = 0;
|
|
13028
13106
|
for (const v of vis) {
|
|
13029
|
-
const
|
|
13107
|
+
const ci = clockOf(v.prn[0]);
|
|
13108
|
+
const common = v.range + x[ci] - v.satClkM + v.tropoFixed + zwd0 * v.mw;
|
|
13030
13109
|
let ai = ambIdx.get(v.prn);
|
|
13031
13110
|
if (ai === void 0 || v.slip) {
|
|
13032
13111
|
const bInit = v.lIf - (common + v.windupM);
|
|
@@ -13051,13 +13130,13 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
13051
13130
|
h[IDX_X] = -v.e[0];
|
|
13052
13131
|
h[IDX_Y] = -v.e[1];
|
|
13053
13132
|
h[IDX_Z] = -v.e[2];
|
|
13054
|
-
h[
|
|
13133
|
+
h[ci] = 1;
|
|
13055
13134
|
h[IDX_ZWD] = v.mw;
|
|
13056
13135
|
const innov = v.pIf - common;
|
|
13057
13136
|
if (Math.abs(innov) < 1e6) ekfUpdateScalar(x, P, h, innov, rCode, 4);
|
|
13058
13137
|
}
|
|
13059
13138
|
{
|
|
13060
|
-
const commonPh = v.range + x[
|
|
13139
|
+
const commonPh = v.range + x[ci] - v.satClkM + v.tropoFixed + x[IDX_ZWD] * v.mw;
|
|
13061
13140
|
const innov = v.lIf - (commonPh + v.windupM + x[ai]);
|
|
13062
13141
|
if (Math.abs(innov) > 0.15) {
|
|
13063
13142
|
x[ai] = v.lIf - (commonPh + v.windupM);
|
|
@@ -13071,7 +13150,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
13071
13150
|
h[IDX_X] = -v.e[0];
|
|
13072
13151
|
h[IDX_Y] = -v.e[1];
|
|
13073
13152
|
h[IDX_Z] = -v.e[2];
|
|
13074
|
-
h[
|
|
13153
|
+
h[ci] = 1;
|
|
13075
13154
|
h[IDX_ZWD] = v.mw;
|
|
13076
13155
|
h[ai] = 1;
|
|
13077
13156
|
if (ekfUpdateScalar(x, P, h, innov, rPhase, 4)) {
|
|
@@ -15732,6 +15811,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
15732
15811
|
buildObsIndices,
|
|
15733
15812
|
buildPppAntenna,
|
|
15734
15813
|
clampUnit,
|
|
15814
|
+
clkBias,
|
|
15735
15815
|
computeAllPositions,
|
|
15736
15816
|
computeDop,
|
|
15737
15817
|
computeIonoRate,
|
|
@@ -15850,6 +15930,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
15850
15930
|
padR,
|
|
15851
15931
|
parseAntex,
|
|
15852
15932
|
parseBinex,
|
|
15933
|
+
parseClk,
|
|
15853
15934
|
parseCrxDataLine,
|
|
15854
15935
|
parseIonex,
|
|
15855
15936
|
parseNavFile,
|
package/dist/index.d.cts
CHANGED
|
@@ -7,7 +7,7 @@ export { c as clampUnit, e as ecefToGeodetic, g as geodeticToEcef, a as getAer,
|
|
|
7
7
|
export { CompactEpoch, CrxField, DiffState, EMPTY_WARNINGS, Nav4Input, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, WriteCrxOptions, createGzipLineSink, crxDecompress, crxRepair, fmtD, fmtF, hdrLine, padL, padR, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob } from './rinex.cjs';
|
|
8
8
|
export { E as EpochSummary, P as ParseOptions, R as RinexHeader, 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';
|
|
9
9
|
export { C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, R as RinexCnavEphemeris, p as parseNavFile } from './nav-DImXUdbp.cjs';
|
|
10
|
-
export { I as IonexGrid, S as Sp3File, a as Sp3Sample, p as
|
|
10
|
+
export { C as ClkFile, I as IonexGrid, S as Sp3File, a as Sp3Sample, c as clkBias, p as parseClk, b as parseIonex, d as parseSp3, s as sp3Position } from './clk-DGVBGRzA.cjs';
|
|
11
11
|
export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.cjs';
|
|
12
12
|
export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.cjs';
|
|
13
13
|
export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { c as clampUnit, e as ecefToGeodetic, g as geodeticToEcef, a as getAer,
|
|
|
7
7
|
export { CompactEpoch, CrxField, DiffState, EMPTY_WARNINGS, Nav4Input, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, WriteCrxOptions, createGzipLineSink, crxDecompress, crxRepair, fmtD, fmtF, hdrLine, padL, padR, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob } from './rinex.js';
|
|
8
8
|
export { E as EpochSummary, P as ParseOptions, R as RinexHeader, 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';
|
|
9
9
|
export { C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, R as RinexCnavEphemeris, p as parseNavFile } from './nav-DImXUdbp.js';
|
|
10
|
-
export { I as IonexGrid, S as Sp3File, a as Sp3Sample, p as
|
|
10
|
+
export { C as ClkFile, I as IonexGrid, S as Sp3File, a as Sp3Sample, c as clkBias, p as parseClk, b as parseIonex, d as parseSp3, s as sp3Position } from './clk-DGVBGRzA.js';
|
|
11
11
|
export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.js';
|
|
12
12
|
export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.js';
|
|
13
13
|
export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.js';
|
package/dist/index.js
CHANGED
|
@@ -162,7 +162,7 @@ import {
|
|
|
162
162
|
solveSpp,
|
|
163
163
|
sunEcef,
|
|
164
164
|
toRtkEpoch
|
|
165
|
-
} from "./chunk-
|
|
165
|
+
} from "./chunk-CRFFUU5Y.js";
|
|
166
166
|
import {
|
|
167
167
|
almanacEpochMs,
|
|
168
168
|
almanacSatPosition,
|
|
@@ -217,7 +217,7 @@ import {
|
|
|
217
217
|
writeRinexNav,
|
|
218
218
|
writeRinexNav4,
|
|
219
219
|
writeRinexObsBlob
|
|
220
|
-
} from "./chunk-
|
|
220
|
+
} from "./chunk-KDM2NVBO.js";
|
|
221
221
|
import "./chunk-726LQBGM.js";
|
|
222
222
|
import "./chunk-IQ5OIMQD.js";
|
|
223
223
|
import {
|
|
@@ -230,9 +230,11 @@ import {
|
|
|
230
230
|
systemName
|
|
231
231
|
} from "./chunk-3U5AX7PY.js";
|
|
232
232
|
import {
|
|
233
|
+
clkBias,
|
|
234
|
+
parseClk,
|
|
233
235
|
parseSp3,
|
|
234
236
|
sp3Position
|
|
235
|
-
} from "./chunk-
|
|
237
|
+
} from "./chunk-GPEP67TG.js";
|
|
236
238
|
import {
|
|
237
239
|
BitReader,
|
|
238
240
|
RTCM3_MESSAGE_NAMES,
|
|
@@ -434,6 +436,7 @@ export {
|
|
|
434
436
|
buildObsIndices,
|
|
435
437
|
buildPppAntenna,
|
|
436
438
|
clampUnit,
|
|
439
|
+
clkBias,
|
|
437
440
|
computeAllPositions,
|
|
438
441
|
computeDop,
|
|
439
442
|
computeIonoRate,
|
|
@@ -552,6 +555,7 @@ export {
|
|
|
552
555
|
padR,
|
|
553
556
|
parseAntex,
|
|
554
557
|
parseBinex,
|
|
558
|
+
parseClk,
|
|
555
559
|
parseCrxDataLine,
|
|
556
560
|
parseIonex,
|
|
557
561
|
parseNavFile,
|
package/dist/positioning.cjs
CHANGED
|
@@ -1597,6 +1597,28 @@ function sp3Position(sp3, prn, tMs, order = 9) {
|
|
|
1597
1597
|
return { x, y, z, clk };
|
|
1598
1598
|
}
|
|
1599
1599
|
|
|
1600
|
+
// src/rinex/clk.ts
|
|
1601
|
+
var GPS_EPOCH_MS2 = Date.UTC(1980, 0, 6);
|
|
1602
|
+
function clkBias(clk, prn, tMs) {
|
|
1603
|
+
const e = clk.sats[prn];
|
|
1604
|
+
if (!e || e.t.length === 0) return null;
|
|
1605
|
+
const { t, c } = e;
|
|
1606
|
+
let lo = 0;
|
|
1607
|
+
let hi = t.length - 1;
|
|
1608
|
+
if (tMs < t[0] || tMs > t[hi]) return null;
|
|
1609
|
+
while (lo < hi) {
|
|
1610
|
+
const mid = lo + hi + 1 >> 1;
|
|
1611
|
+
if (t[mid] <= tMs) lo = mid;
|
|
1612
|
+
else hi = mid - 1;
|
|
1613
|
+
}
|
|
1614
|
+
if (t[lo] === tMs || lo === t.length - 1) return c[lo];
|
|
1615
|
+
const t0 = t[lo];
|
|
1616
|
+
const t1 = t[lo + 1];
|
|
1617
|
+
if (t1 - t0 > clk.intervalSec * 1e3 * 4) return null;
|
|
1618
|
+
const f = (tMs - t0) / (t1 - t0);
|
|
1619
|
+
return c[lo] + f * (c[lo + 1] - c[lo]);
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1600
1622
|
// src/positioning/ppp-tropo.ts
|
|
1601
1623
|
var HYD_AVG_A = [
|
|
1602
1624
|
0.0012769934,
|
|
@@ -2080,7 +2102,7 @@ function sagnacRotate(x, y, z, travelS) {
|
|
|
2080
2102
|
const s = Math.sin(theta);
|
|
2081
2103
|
return [x * c + y * s, -x * s + y * c, z];
|
|
2082
2104
|
}
|
|
2083
|
-
function satStateAtEmission(sp3, prn, recvTimeMs, rcv) {
|
|
2105
|
+
function satStateAtEmission(sp3, prn, recvTimeMs, rcv, clk) {
|
|
2084
2106
|
let travelS = 0.075;
|
|
2085
2107
|
let sx = 0;
|
|
2086
2108
|
let sy = 0;
|
|
@@ -2099,7 +2121,7 @@ function satStateAtEmission(sp3, prn, recvTimeMs, rcv) {
|
|
|
2099
2121
|
const vz = (pPlus.z - pMinus.z) / 1;
|
|
2100
2122
|
velDotPos = p.x * vx + p.y * vy + p.z * vz;
|
|
2101
2123
|
}
|
|
2102
|
-
clkS = p.clk;
|
|
2124
|
+
clkS = (clk && clkBias(clk, prn, tEmit)) ?? p.clk;
|
|
2103
2125
|
const [rx, ry, rz] = sagnacRotate(p.x, p.y, p.z, travelS);
|
|
2104
2126
|
sx = rx;
|
|
2105
2127
|
sy = ry;
|
|
@@ -2118,9 +2140,9 @@ function satStateAtEmission(sp3, prn, recvTimeMs, rcv) {
|
|
|
2118
2140
|
var IDX_X = 0;
|
|
2119
2141
|
var IDX_Y = 1;
|
|
2120
2142
|
var IDX_Z = 2;
|
|
2121
|
-
var
|
|
2122
|
-
var
|
|
2123
|
-
var
|
|
2143
|
+
var IDX_ZWD = 3;
|
|
2144
|
+
var NBASE = 4;
|
|
2145
|
+
var CLK_VAR = 1e10;
|
|
2124
2146
|
function solvePpp(epochs, sp3, opts) {
|
|
2125
2147
|
const elevMask = (opts.elevationMaskDeg ?? 10) * Math.PI / 180;
|
|
2126
2148
|
const codeSigma = opts.codeSigma ?? 3;
|
|
@@ -2131,8 +2153,6 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2131
2153
|
opts.aprioriPos[0],
|
|
2132
2154
|
opts.aprioriPos[1],
|
|
2133
2155
|
opts.aprioriPos[2],
|
|
2134
|
-
0,
|
|
2135
|
-
// receiver clock (m)
|
|
2136
2156
|
0.1
|
|
2137
2157
|
// zenith wet delay (m) a priori
|
|
2138
2158
|
];
|
|
@@ -2143,8 +2163,9 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2143
2163
|
P[IDX_X][IDX_X] = 100 * 100;
|
|
2144
2164
|
P[IDX_Y][IDX_Y] = 100 * 100;
|
|
2145
2165
|
P[IDX_Z][IDX_Z] = 100 * 100;
|
|
2146
|
-
P[IDX_CLK][IDX_CLK] = 1e10;
|
|
2147
2166
|
P[IDX_ZWD][IDX_ZWD] = 0.5 * 0.5;
|
|
2167
|
+
const clkIdx = /* @__PURE__ */ new Map();
|
|
2168
|
+
const clockSeeded = /* @__PURE__ */ new Set();
|
|
2148
2169
|
const ambIdx = /* @__PURE__ */ new Map();
|
|
2149
2170
|
const lastSeen = /* @__PURE__ */ new Map();
|
|
2150
2171
|
const mwState = /* @__PURE__ */ new Map();
|
|
@@ -2185,8 +2206,18 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2185
2206
|
if (i === idx) ambIdx.delete(prn);
|
|
2186
2207
|
else if (i > idx) ambIdx.set(prn, i - 1);
|
|
2187
2208
|
}
|
|
2209
|
+
for (const [sys, i] of clkIdx) {
|
|
2210
|
+
if (i > idx) clkIdx.set(sys, i - 1);
|
|
2211
|
+
}
|
|
2212
|
+
};
|
|
2213
|
+
const clockOf = (sys) => {
|
|
2214
|
+
let i = clkIdx.get(sys);
|
|
2215
|
+
if (i === void 0) {
|
|
2216
|
+
i = growState(0, CLK_VAR);
|
|
2217
|
+
clkIdx.set(sys, i);
|
|
2218
|
+
}
|
|
2219
|
+
return i;
|
|
2188
2220
|
};
|
|
2189
|
-
let clockSeeded = false;
|
|
2190
2221
|
const series = [];
|
|
2191
2222
|
const truth = opts.groundTruth;
|
|
2192
2223
|
const t0 = epochs[0]?.timeMs ?? 0;
|
|
@@ -2194,7 +2225,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2194
2225
|
let convergedStreak = 0;
|
|
2195
2226
|
for (let ei = 0; ei < epochs.length; ei++) {
|
|
2196
2227
|
const epoch = epochs[ei];
|
|
2197
|
-
P[
|
|
2228
|
+
for (const ci of clkIdx.values()) P[ci][ci] = CLK_VAR;
|
|
2198
2229
|
P[IDX_ZWD][IDX_ZWD] += ztdQ * (ei > 0 ? 1 : 0);
|
|
2199
2230
|
const rcv = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
2200
2231
|
const [latDeg, , heightM] = ecefToGeodetic(rcv[0], rcv[1], rcv[2]);
|
|
@@ -2204,7 +2235,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2204
2235
|
for (const o of epoch.obs) {
|
|
2205
2236
|
if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
|
|
2206
2237
|
const slip = detectSlip(o, ei);
|
|
2207
|
-
const sat = satStateAtEmission(sp3, o.prn, epoch.timeMs, rcv);
|
|
2238
|
+
const sat = satStateAtEmission(sp3, o.prn, epoch.timeMs, rcv, opts.clk);
|
|
2208
2239
|
if (!sat) continue;
|
|
2209
2240
|
const [elRad, azRad] = getAer(
|
|
2210
2241
|
sat.state.x,
|
|
@@ -2258,21 +2289,29 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2258
2289
|
});
|
|
2259
2290
|
}
|
|
2260
2291
|
const zwd0 = x[IDX_ZWD];
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2292
|
+
const bySys = /* @__PURE__ */ new Map();
|
|
2293
|
+
for (const v of vis) {
|
|
2294
|
+
const sys = v.prn[0];
|
|
2295
|
+
const r = v.pIf - (v.range - v.satClkM + v.tropoFixed + zwd0 * v.mw);
|
|
2296
|
+
const arr = bySys.get(sys);
|
|
2297
|
+
if (arr) arr.push(r);
|
|
2298
|
+
else bySys.set(sys, [r]);
|
|
2299
|
+
}
|
|
2300
|
+
for (const [sys, res] of bySys) {
|
|
2301
|
+
const ci = clockOf(sys);
|
|
2302
|
+
if (!clockSeeded.has(sys)) {
|
|
2303
|
+
res.sort((a, b) => a - b);
|
|
2304
|
+
x[ci] = res[Math.floor(res.length / 2)];
|
|
2305
|
+
clockSeeded.add(sys);
|
|
2268
2306
|
}
|
|
2269
|
-
P[
|
|
2307
|
+
P[ci][ci] = CLK_VAR;
|
|
2270
2308
|
}
|
|
2271
2309
|
let nSats = 0;
|
|
2272
2310
|
let sumPhaseResSq = 0;
|
|
2273
2311
|
let nPhaseRes = 0;
|
|
2274
2312
|
for (const v of vis) {
|
|
2275
|
-
const
|
|
2313
|
+
const ci = clockOf(v.prn[0]);
|
|
2314
|
+
const common = v.range + x[ci] - v.satClkM + v.tropoFixed + zwd0 * v.mw;
|
|
2276
2315
|
let ai = ambIdx.get(v.prn);
|
|
2277
2316
|
if (ai === void 0 || v.slip) {
|
|
2278
2317
|
const bInit = v.lIf - (common + v.windupM);
|
|
@@ -2297,13 +2336,13 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2297
2336
|
h[IDX_X] = -v.e[0];
|
|
2298
2337
|
h[IDX_Y] = -v.e[1];
|
|
2299
2338
|
h[IDX_Z] = -v.e[2];
|
|
2300
|
-
h[
|
|
2339
|
+
h[ci] = 1;
|
|
2301
2340
|
h[IDX_ZWD] = v.mw;
|
|
2302
2341
|
const innov = v.pIf - common;
|
|
2303
2342
|
if (Math.abs(innov) < 1e6) ekfUpdateScalar(x, P, h, innov, rCode, 4);
|
|
2304
2343
|
}
|
|
2305
2344
|
{
|
|
2306
|
-
const commonPh = v.range + x[
|
|
2345
|
+
const commonPh = v.range + x[ci] - v.satClkM + v.tropoFixed + x[IDX_ZWD] * v.mw;
|
|
2307
2346
|
const innov = v.lIf - (commonPh + v.windupM + x[ai]);
|
|
2308
2347
|
if (Math.abs(innov) > 0.15) {
|
|
2309
2348
|
x[ai] = v.lIf - (commonPh + v.windupM);
|
|
@@ -2317,7 +2356,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2317
2356
|
h[IDX_X] = -v.e[0];
|
|
2318
2357
|
h[IDX_Y] = -v.e[1];
|
|
2319
2358
|
h[IDX_Z] = -v.e[2];
|
|
2320
|
-
h[
|
|
2359
|
+
h[ci] = 1;
|
|
2321
2360
|
h[IDX_ZWD] = v.mw;
|
|
2322
2361
|
h[ai] = 1;
|
|
2323
2362
|
if (ekfUpdateScalar(x, P, h, innov, rPhase, 4)) {
|
package/dist/positioning.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { E as Ephemeris } from './nav-DImXUdbp.cjs';
|
|
2
2
|
import { DopValues } from './orbit.cjs';
|
|
3
|
-
import { I as IonexGrid, S as Sp3File } from './
|
|
3
|
+
import { I as IonexGrid, C as ClkFile, S as Sp3File } from './clk-DGVBGRzA.cjs';
|
|
4
4
|
import { AntexFile } from './antex.cjs';
|
|
5
5
|
import './ephemeris-Ohl6NAfw.cjs';
|
|
6
6
|
import './ecef-CF0uAysr.cjs';
|
|
@@ -631,6 +631,11 @@ interface PppOptions {
|
|
|
631
631
|
ztdProcessNoise?: number;
|
|
632
632
|
/** Model + estimate the troposphere. Default true. */
|
|
633
633
|
troposphere?: boolean;
|
|
634
|
+
/** High-rate precise satellite clocks (RINEX CLOCK, typically 30 s). When
|
|
635
|
+
* given, satellite clock offsets come from this by linear interpolation
|
|
636
|
+
* instead of the SP3 5-minute clocks — the dominant PPP accuracy term.
|
|
637
|
+
* Satellites/epochs absent from the CLK fall back to the SP3 clock. */
|
|
638
|
+
clk?: ClkFile;
|
|
634
639
|
}
|
|
635
640
|
interface PppEpochResult {
|
|
636
641
|
timeMs: number;
|
package/dist/positioning.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { E as Ephemeris } from './nav-DImXUdbp.js';
|
|
2
2
|
import { DopValues } from './orbit.js';
|
|
3
|
-
import { I as IonexGrid, S as Sp3File } from './
|
|
3
|
+
import { I as IonexGrid, C as ClkFile, S as Sp3File } from './clk-DGVBGRzA.js';
|
|
4
4
|
import { AntexFile } from './antex.js';
|
|
5
5
|
import './ephemeris-Ohl6NAfw.js';
|
|
6
6
|
import './ecef-CF0uAysr.js';
|
|
@@ -631,6 +631,11 @@ interface PppOptions {
|
|
|
631
631
|
ztdProcessNoise?: number;
|
|
632
632
|
/** Model + estimate the troposphere. Default true. */
|
|
633
633
|
troposphere?: boolean;
|
|
634
|
+
/** High-rate precise satellite clocks (RINEX CLOCK, typically 30 s). When
|
|
635
|
+
* given, satellite clock offsets come from this by linear interpolation
|
|
636
|
+
* instead of the SP3 5-minute clocks — the dominant PPP accuracy term.
|
|
637
|
+
* Satellites/epochs absent from the CLK fall back to the SP3 clock. */
|
|
638
|
+
clk?: ClkFile;
|
|
634
639
|
}
|
|
635
640
|
interface PppEpochResult {
|
|
636
641
|
timeMs: number;
|
package/dist/positioning.js
CHANGED
|
@@ -19,11 +19,11 @@ import {
|
|
|
19
19
|
solveSpp,
|
|
20
20
|
sunEcef,
|
|
21
21
|
toRtkEpoch
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-CRFFUU5Y.js";
|
|
23
23
|
import "./chunk-MHGNKSSH.js";
|
|
24
24
|
import "./chunk-37QNKGTC.js";
|
|
25
25
|
import "./chunk-6FAL6P4G.js";
|
|
26
|
-
import "./chunk-
|
|
26
|
+
import "./chunk-GPEP67TG.js";
|
|
27
27
|
import "./chunk-HVXYFUCB.js";
|
|
28
28
|
import "./chunk-LEEU5OIO.js";
|
|
29
29
|
import "./chunk-FIEWO4J4.js";
|
package/dist/rinex.cjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(rinex_exports, {
|
|
|
23
23
|
EMPTY_WARNINGS: () => EMPTY_WARNINGS,
|
|
24
24
|
SYSTEM_ORDER: () => SYSTEM_ORDER,
|
|
25
25
|
WarningAccumulator: () => WarningAccumulator,
|
|
26
|
+
clkBias: () => clkBias,
|
|
26
27
|
createGzipLineSink: () => createGzipLineSink,
|
|
27
28
|
crxDecompress: () => crxDecompress,
|
|
28
29
|
crxRepair: () => crxRepair,
|
|
@@ -31,6 +32,7 @@ __export(rinex_exports, {
|
|
|
31
32
|
hdrLine: () => hdrLine,
|
|
32
33
|
padL: () => padL,
|
|
33
34
|
padR: () => padR,
|
|
35
|
+
parseClk: () => parseClk,
|
|
34
36
|
parseCrxDataLine: () => parseCrxDataLine,
|
|
35
37
|
parseIonex: () => parseIonex,
|
|
36
38
|
parseNavFile: () => parseNavFile,
|
|
@@ -2388,6 +2390,66 @@ function sp3Position(sp3, prn, tMs, order = 9) {
|
|
|
2388
2390
|
return { x, y, z, clk };
|
|
2389
2391
|
}
|
|
2390
2392
|
|
|
2393
|
+
// src/rinex/clk.ts
|
|
2394
|
+
var GPS_EPOCH_MS4 = Date.UTC(1980, 0, 6);
|
|
2395
|
+
function parseClk(text) {
|
|
2396
|
+
const sats = {};
|
|
2397
|
+
let inData = false;
|
|
2398
|
+
for (const line of text.split("\n")) {
|
|
2399
|
+
if (!inData) {
|
|
2400
|
+
if (line.includes("END OF HEADER")) inData = true;
|
|
2401
|
+
continue;
|
|
2402
|
+
}
|
|
2403
|
+
if (line.length < 3 || line[0] !== "A" || line[1] !== "S") continue;
|
|
2404
|
+
const p = line.slice(2).trim().split(/\s+/);
|
|
2405
|
+
if (p.length < 9) continue;
|
|
2406
|
+
const prn = p[0];
|
|
2407
|
+
const y = +p[1];
|
|
2408
|
+
const mo = +p[2];
|
|
2409
|
+
const d = +p[3];
|
|
2410
|
+
const h = +p[4];
|
|
2411
|
+
const mi = +p[5];
|
|
2412
|
+
const s = +p[6];
|
|
2413
|
+
const bias = +p[8];
|
|
2414
|
+
if (!Number.isFinite(bias)) continue;
|
|
2415
|
+
const t = Date.UTC(y, mo - 1, d, h, mi, Math.floor(s)) + s % 1 * 1e3;
|
|
2416
|
+
let e = sats[prn];
|
|
2417
|
+
if (!e) {
|
|
2418
|
+
e = { t: [], c: [] };
|
|
2419
|
+
sats[prn] = e;
|
|
2420
|
+
}
|
|
2421
|
+
e.t.push(t);
|
|
2422
|
+
e.c.push(bias);
|
|
2423
|
+
}
|
|
2424
|
+
let intervalSec = 30;
|
|
2425
|
+
for (const e of Object.values(sats)) {
|
|
2426
|
+
if (e.t.length >= 2) {
|
|
2427
|
+
intervalSec = Math.round((e.t[1] - e.t[0]) / 1e3);
|
|
2428
|
+
break;
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
return { sats, intervalSec };
|
|
2432
|
+
}
|
|
2433
|
+
function clkBias(clk, prn, tMs) {
|
|
2434
|
+
const e = clk.sats[prn];
|
|
2435
|
+
if (!e || e.t.length === 0) return null;
|
|
2436
|
+
const { t, c } = e;
|
|
2437
|
+
let lo = 0;
|
|
2438
|
+
let hi = t.length - 1;
|
|
2439
|
+
if (tMs < t[0] || tMs > t[hi]) return null;
|
|
2440
|
+
while (lo < hi) {
|
|
2441
|
+
const mid = lo + hi + 1 >> 1;
|
|
2442
|
+
if (t[mid] <= tMs) lo = mid;
|
|
2443
|
+
else hi = mid - 1;
|
|
2444
|
+
}
|
|
2445
|
+
if (t[lo] === tMs || lo === t.length - 1) return c[lo];
|
|
2446
|
+
const t0 = t[lo];
|
|
2447
|
+
const t1 = t[lo + 1];
|
|
2448
|
+
if (t1 - t0 > clk.intervalSec * 1e3 * 4) return null;
|
|
2449
|
+
const f = (tMs - t0) / (t1 - t0);
|
|
2450
|
+
return c[lo] + f * (c[lo + 1] - c[lo]);
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2391
2453
|
// src/rinex/obs-writer-common.ts
|
|
2392
2454
|
function createGzipLineSink() {
|
|
2393
2455
|
const encoder = new TextEncoder();
|
|
@@ -2766,6 +2828,7 @@ function writeRinex4ObsBlob(header, epochs, obsTypes) {
|
|
|
2766
2828
|
EMPTY_WARNINGS,
|
|
2767
2829
|
SYSTEM_ORDER,
|
|
2768
2830
|
WarningAccumulator,
|
|
2831
|
+
clkBias,
|
|
2769
2832
|
createGzipLineSink,
|
|
2770
2833
|
crxDecompress,
|
|
2771
2834
|
crxRepair,
|
|
@@ -2774,6 +2837,7 @@ function writeRinex4ObsBlob(header, epochs, obsTypes) {
|
|
|
2774
2837
|
hdrLine,
|
|
2775
2838
|
padL,
|
|
2776
2839
|
padR,
|
|
2840
|
+
parseClk,
|
|
2777
2841
|
parseCrxDataLine,
|
|
2778
2842
|
parseIonex,
|
|
2779
2843
|
parseNavFile,
|
package/dist/rinex.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ 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
3
|
import { a as NavResult, N as NavHeader, E as Ephemeris, R as RinexCnavEphemeris } from './nav-DImXUdbp.cjs';
|
|
4
4
|
export { G as GlonassEphemeris, K as KeplerEphemeris, p as parseNavFile } from './nav-DImXUdbp.cjs';
|
|
5
|
-
export { I as IonexGrid, S as Sp3File, a as Sp3Sample, p as
|
|
5
|
+
export { C as ClkFile, I as IonexGrid, S as Sp3File, a as Sp3Sample, c as clkBias, p as parseClk, b as parseIonex, d as parseSp3, s as sp3Position } from './clk-DGVBGRzA.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Compact RINEX (Hatanaka / CRX) decompression utilities.
|
package/dist/rinex.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ 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
3
|
import { a as NavResult, N as NavHeader, E as Ephemeris, R as RinexCnavEphemeris } from './nav-DImXUdbp.js';
|
|
4
4
|
export { G as GlonassEphemeris, K as KeplerEphemeris, p as parseNavFile } from './nav-DImXUdbp.js';
|
|
5
|
-
export { I as IonexGrid, S as Sp3File, a as Sp3Sample, p as
|
|
5
|
+
export { C as ClkFile, I as IonexGrid, S as Sp3File, a as Sp3Sample, c as clkBias, p as parseClk, b as parseIonex, d as parseSp3, s as sp3Position } from './clk-DGVBGRzA.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Compact RINEX (Hatanaka / CRX) decompression utilities.
|
package/dist/rinex.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
writeRinexNav,
|
|
18
18
|
writeRinexNav4,
|
|
19
19
|
writeRinexObsBlob
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-KDM2NVBO.js";
|
|
21
21
|
import "./chunk-726LQBGM.js";
|
|
22
22
|
import "./chunk-IQ5OIMQD.js";
|
|
23
23
|
import {
|
|
@@ -30,14 +30,17 @@ import {
|
|
|
30
30
|
systemName
|
|
31
31
|
} from "./chunk-3U5AX7PY.js";
|
|
32
32
|
import {
|
|
33
|
+
clkBias,
|
|
34
|
+
parseClk,
|
|
33
35
|
parseSp3,
|
|
34
36
|
sp3Position
|
|
35
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-GPEP67TG.js";
|
|
36
38
|
import "./chunk-FIEWO4J4.js";
|
|
37
39
|
export {
|
|
38
40
|
EMPTY_WARNINGS,
|
|
39
41
|
SYSTEM_ORDER,
|
|
40
42
|
WarningAccumulator,
|
|
43
|
+
clkBias,
|
|
41
44
|
createGzipLineSink,
|
|
42
45
|
crxDecompress,
|
|
43
46
|
crxRepair,
|
|
@@ -46,6 +49,7 @@ export {
|
|
|
46
49
|
hdrLine,
|
|
47
50
|
padL,
|
|
48
51
|
padR,
|
|
52
|
+
parseClk,
|
|
49
53
|
parseCrxDataLine,
|
|
50
54
|
parseIonex,
|
|
51
55
|
parseNavFile,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gnss-js",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.30.0",
|
|
4
4
|
"description": "Comprehensive GNSS library for JavaScript — time scales, coordinates, RINEX parsing, RTCM3 decoding, orbit computation, and signal analysis",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
File without changes
|