gnss-js 1.33.0 → 1.35.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-PVOF4IGX.js → chunk-BLGBMRX7.js} +147 -27
- package/dist/index.cjs +165 -43
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -1
- package/dist/positioning.cjs +149 -27
- package/dist/positioning.d.cts +88 -1
- package/dist/positioning.d.ts +88 -1
- package/dist/positioning.js +5 -1
- package/package.json +1 -1
|
@@ -461,15 +461,15 @@ function matMul(A, B) {
|
|
|
461
461
|
const n = A.length;
|
|
462
462
|
const k = B.length;
|
|
463
463
|
const m = B[0]?.length ?? 0;
|
|
464
|
-
const
|
|
464
|
+
const C2 = zeros(n, m);
|
|
465
465
|
for (let i = 0; i < n; i++) {
|
|
466
466
|
for (let l = 0; l < k; l++) {
|
|
467
467
|
const a = A[i][l];
|
|
468
468
|
if (a === 0) continue;
|
|
469
|
-
for (let j = 0; j < m; j++)
|
|
469
|
+
for (let j = 0; j < m; j++) C2[i][j] += a * B[l][j];
|
|
470
470
|
}
|
|
471
471
|
}
|
|
472
|
-
return
|
|
472
|
+
return C2;
|
|
473
473
|
}
|
|
474
474
|
function transpose(A) {
|
|
475
475
|
const n = A.length;
|
|
@@ -1649,6 +1649,24 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1649
1649
|
const clockSeeded = /* @__PURE__ */ new Set();
|
|
1650
1650
|
const ambIdx = /* @__PURE__ */ new Map();
|
|
1651
1651
|
const lastSeen = /* @__PURE__ */ new Map();
|
|
1652
|
+
const arcs = [];
|
|
1653
|
+
const arcSnap = /* @__PURE__ */ new Map();
|
|
1654
|
+
const flushArc = (prn, minEpochs = 10) => {
|
|
1655
|
+
const s = arcSnap.get(prn);
|
|
1656
|
+
arcSnap.delete(prn);
|
|
1657
|
+
if (!s || s.nEpochs < minEpochs) return;
|
|
1658
|
+
arcs.push({
|
|
1659
|
+
prn,
|
|
1660
|
+
aIF: s.aIF,
|
|
1661
|
+
mwCyc: s.mwCyc,
|
|
1662
|
+
f1: s.f1,
|
|
1663
|
+
f2: s.f2,
|
|
1664
|
+
meanElevDeg: s.elevSum / s.nEpochs,
|
|
1665
|
+
nEpochs: s.nEpochs,
|
|
1666
|
+
startMs: s.startMs,
|
|
1667
|
+
endMs: s.endMs
|
|
1668
|
+
});
|
|
1669
|
+
};
|
|
1652
1670
|
const mwState = /* @__PURE__ */ new Map();
|
|
1653
1671
|
const detectSlip = (o, ei) => {
|
|
1654
1672
|
const lamW = C_LIGHT / (o.f1 - o.f2);
|
|
@@ -1766,7 +1784,9 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1766
1784
|
tropoFixed: zhd * mh + corr.rangeM,
|
|
1767
1785
|
mw,
|
|
1768
1786
|
windupM: corr.phaseWindupM,
|
|
1769
|
-
slip
|
|
1787
|
+
slip,
|
|
1788
|
+
f1: o.f1,
|
|
1789
|
+
f2: o.f2
|
|
1770
1790
|
});
|
|
1771
1791
|
}
|
|
1772
1792
|
const zwd0 = x[IDX_ZWD];
|
|
@@ -1791,6 +1811,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1791
1811
|
for (const v of vis) {
|
|
1792
1812
|
const ci = clockOf(v.prn[0]);
|
|
1793
1813
|
const common = v.range + x[ci] - v.satClkM + v.tropoFixed + zwd0 * v.mw;
|
|
1814
|
+
if (v.slip) flushArc(v.prn);
|
|
1794
1815
|
let ai = ambIdx.get(v.prn);
|
|
1795
1816
|
if (ai === void 0 || v.slip) {
|
|
1796
1817
|
const bInit = v.lIf - (common + v.windupM);
|
|
@@ -1824,6 +1845,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1824
1845
|
const commonPh = v.range + x[ci] - v.satClkM + v.tropoFixed + x[IDX_ZWD] * v.mw;
|
|
1825
1846
|
const innov = v.lIf - (commonPh + v.windupM + x[ai]);
|
|
1826
1847
|
if (Math.abs(innov) > 0.15) {
|
|
1848
|
+
flushArc(v.prn);
|
|
1827
1849
|
x[ai] = v.lIf - (commonPh + v.windupM);
|
|
1828
1850
|
for (let j = 0; j < P.length; j++) {
|
|
1829
1851
|
P[ai][j] = 0;
|
|
@@ -1841,6 +1863,29 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1841
1863
|
ekfUpdateScalar(x, P, h, innov, rPhase, 4);
|
|
1842
1864
|
}
|
|
1843
1865
|
}
|
|
1866
|
+
{
|
|
1867
|
+
const elevDeg = v.elRad * 180 / Math.PI;
|
|
1868
|
+
const mwMean = mwState.get(v.prn)?.mean ?? 0;
|
|
1869
|
+
const s = arcSnap.get(v.prn);
|
|
1870
|
+
if (s) {
|
|
1871
|
+
s.aIF = x[ai];
|
|
1872
|
+
s.mwCyc = mwMean;
|
|
1873
|
+
s.elevSum += elevDeg;
|
|
1874
|
+
s.nEpochs++;
|
|
1875
|
+
s.endMs = epoch.timeMs;
|
|
1876
|
+
} else {
|
|
1877
|
+
arcSnap.set(v.prn, {
|
|
1878
|
+
aIF: x[ai],
|
|
1879
|
+
mwCyc: mwMean,
|
|
1880
|
+
f1: v.f1,
|
|
1881
|
+
f2: v.f2,
|
|
1882
|
+
elevSum: elevDeg,
|
|
1883
|
+
nEpochs: 1,
|
|
1884
|
+
startMs: epoch.timeMs,
|
|
1885
|
+
endMs: epoch.timeMs
|
|
1886
|
+
});
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1844
1889
|
lastSeen.set(v.prn, ei);
|
|
1845
1890
|
nSats++;
|
|
1846
1891
|
}
|
|
@@ -1874,6 +1919,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1874
1919
|
const idx = ambIdx.get(prn);
|
|
1875
1920
|
if (idx !== void 0) dropState(idx);
|
|
1876
1921
|
lastSeen.delete(prn);
|
|
1922
|
+
flushArc(prn);
|
|
1877
1923
|
}
|
|
1878
1924
|
}
|
|
1879
1925
|
const pos = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
@@ -1913,6 +1959,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1913
1959
|
phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0
|
|
1914
1960
|
});
|
|
1915
1961
|
}
|
|
1962
|
+
for (const prn of [...arcSnap.keys()]) flushArc(prn);
|
|
1916
1963
|
const finalPos = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
1917
1964
|
const llh = ecefToGeodetic(finalPos[0], finalPos[1], finalPos[2]);
|
|
1918
1965
|
const finalError3d = truth ? Math.hypot(
|
|
@@ -1927,7 +1974,8 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
1927
1974
|
ztdWet: x[IDX_ZWD],
|
|
1928
1975
|
epochsUsed: epochs.length,
|
|
1929
1976
|
convergenceSec,
|
|
1930
|
-
finalError3d
|
|
1977
|
+
finalError3d,
|
|
1978
|
+
arcs
|
|
1931
1979
|
};
|
|
1932
1980
|
}
|
|
1933
1981
|
|
|
@@ -2068,34 +2116,34 @@ function circMean(vals, weights) {
|
|
|
2068
2116
|
if (s === 0 && c === 0) return 0;
|
|
2069
2117
|
return wrapHalf(Math.atan2(s, c) / (2 * Math.PI));
|
|
2070
2118
|
}
|
|
2071
|
-
function
|
|
2119
|
+
function decomposeFcb(entries, opts = {}) {
|
|
2072
2120
|
const maxIter = opts.maxIter ?? 50;
|
|
2073
2121
|
const tol = opts.tol ?? 1e-4;
|
|
2074
2122
|
const fixWindow = opts.fixWindow ?? 0.25;
|
|
2075
|
-
const sats = [...new Set(
|
|
2076
|
-
const stations = [...new Set(
|
|
2123
|
+
const sats = [...new Set(entries.map((e) => e.sat))].sort();
|
|
2124
|
+
const stations = [...new Set(entries.map((e) => e.station))].sort();
|
|
2077
2125
|
const refStation = stations[0] ?? "";
|
|
2078
2126
|
const satFcb = new Map(sats.map((s) => [s, 0]));
|
|
2079
2127
|
const rcvBias = new Map(stations.map((s) => [s, 0]));
|
|
2080
|
-
const nInt = new Array(
|
|
2128
|
+
const nInt = new Array(entries.length).fill(0);
|
|
2081
2129
|
let iterations = 0;
|
|
2082
2130
|
for (let it = 0; it < maxIter; it++) {
|
|
2083
2131
|
iterations = it + 1;
|
|
2084
|
-
for (let i = 0; i <
|
|
2085
|
-
const
|
|
2132
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2133
|
+
const e = entries[i];
|
|
2086
2134
|
nInt[i] = Math.round(
|
|
2087
|
-
|
|
2135
|
+
e.value - rcvBias.get(e.station) - satFcb.get(e.sat)
|
|
2088
2136
|
);
|
|
2089
2137
|
}
|
|
2090
2138
|
let maxChange = 0;
|
|
2091
2139
|
for (const s of sats) {
|
|
2092
2140
|
const vals = [];
|
|
2093
2141
|
const w = [];
|
|
2094
|
-
for (let i = 0; i <
|
|
2095
|
-
const
|
|
2096
|
-
if (
|
|
2097
|
-
vals.push(
|
|
2098
|
-
w.push(
|
|
2142
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2143
|
+
const e = entries[i];
|
|
2144
|
+
if (e.sat !== s) continue;
|
|
2145
|
+
vals.push(e.value - nInt[i] - rcvBias.get(e.station));
|
|
2146
|
+
w.push(e.weight);
|
|
2099
2147
|
}
|
|
2100
2148
|
if (!vals.length) continue;
|
|
2101
2149
|
const nv = circMean(vals, w);
|
|
@@ -2105,11 +2153,11 @@ function estimateWidelaneFcb(arcs, opts = {}) {
|
|
|
2105
2153
|
for (const r of stations) {
|
|
2106
2154
|
const vals = [];
|
|
2107
2155
|
const w = [];
|
|
2108
|
-
for (let i = 0; i <
|
|
2109
|
-
const
|
|
2110
|
-
if (
|
|
2111
|
-
vals.push(
|
|
2112
|
-
w.push(
|
|
2156
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2157
|
+
const e = entries[i];
|
|
2158
|
+
if (e.station !== r) continue;
|
|
2159
|
+
vals.push(e.value - nInt[i] - satFcb.get(e.sat));
|
|
2160
|
+
w.push(e.weight);
|
|
2113
2161
|
}
|
|
2114
2162
|
if (!vals.length) continue;
|
|
2115
2163
|
rcvBias.set(r, circMean(vals, w));
|
|
@@ -2124,18 +2172,88 @@ function estimateWidelaneFcb(arcs, opts = {}) {
|
|
|
2124
2172
|
}
|
|
2125
2173
|
let sumSq = 0;
|
|
2126
2174
|
let fixed = 0;
|
|
2127
|
-
for (let i = 0; i <
|
|
2128
|
-
const
|
|
2175
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2176
|
+
const e = entries[i];
|
|
2129
2177
|
const resid = wrapHalf(
|
|
2130
|
-
|
|
2178
|
+
e.value - nInt[i] - rcvBias.get(e.station) - satFcb.get(e.sat)
|
|
2131
2179
|
);
|
|
2132
2180
|
sumSq += resid * resid;
|
|
2133
2181
|
if (Math.abs(resid) <= fixWindow) fixed++;
|
|
2134
2182
|
}
|
|
2135
|
-
const residRms =
|
|
2136
|
-
const fixRate =
|
|
2183
|
+
const residRms = entries.length ? Math.sqrt(sumSq / entries.length) : 0;
|
|
2184
|
+
const fixRate = entries.length ? fixed / entries.length : 0;
|
|
2137
2185
|
return { satFcb, rcvBias, residRms, fixRate, refStation, iterations };
|
|
2138
2186
|
}
|
|
2187
|
+
function estimateWidelaneFcb(arcs, opts = {}) {
|
|
2188
|
+
return decomposeFcb(
|
|
2189
|
+
arcs.map((a) => ({
|
|
2190
|
+
station: a.station,
|
|
2191
|
+
sat: a.prn,
|
|
2192
|
+
value: a.wlFloat,
|
|
2193
|
+
weight: a.nObs
|
|
2194
|
+
})),
|
|
2195
|
+
opts
|
|
2196
|
+
);
|
|
2197
|
+
}
|
|
2198
|
+
var C = 299792458;
|
|
2199
|
+
function estimateNarrowlaneFcb(arcs, wl, opts = {}) {
|
|
2200
|
+
const entries = [];
|
|
2201
|
+
let wlRejected = 0;
|
|
2202
|
+
for (const a of arcs) {
|
|
2203
|
+
const satWl = wl.satFcb.get(a.prn);
|
|
2204
|
+
const rcvWl = wl.rcvBias.get(a.station);
|
|
2205
|
+
if (satWl === void 0 || rcvWl === void 0) continue;
|
|
2206
|
+
const wlFloat = a.mwCyc - satWl - rcvWl;
|
|
2207
|
+
const nWl = Math.round(wlFloat);
|
|
2208
|
+
if (Math.abs(wlFloat - nWl) > (opts.fixWindow ?? 0.25)) {
|
|
2209
|
+
wlRejected++;
|
|
2210
|
+
continue;
|
|
2211
|
+
}
|
|
2212
|
+
const lamNl = C / (a.f1 + a.f2);
|
|
2213
|
+
const n1Float = a.aIF / lamNl - a.f2 / (a.f1 - a.f2) * nWl;
|
|
2214
|
+
entries.push({
|
|
2215
|
+
station: a.station,
|
|
2216
|
+
sat: a.prn,
|
|
2217
|
+
value: n1Float,
|
|
2218
|
+
weight: a.nEpochs
|
|
2219
|
+
});
|
|
2220
|
+
}
|
|
2221
|
+
const res = decomposeFcb(entries, { fixWindow: 0.15, ...opts });
|
|
2222
|
+
return { ...res, usedArcs: entries.length, wlRejected };
|
|
2223
|
+
}
|
|
2224
|
+
function estimateNetworkFcbs(arcs, opts = {}) {
|
|
2225
|
+
const minArcEpochs = opts.minArcEpochs ?? 120;
|
|
2226
|
+
const minWlObs = opts.minWlObs ?? 40;
|
|
2227
|
+
const fixWindow = opts.fixWindow ?? 0.15;
|
|
2228
|
+
const satWlFcb = /* @__PURE__ */ new Map();
|
|
2229
|
+
const satNlFcb = /* @__PURE__ */ new Map();
|
|
2230
|
+
const perSystem = {};
|
|
2231
|
+
const systems = [...new Set(arcs.map((a) => a.prn[0]))].sort();
|
|
2232
|
+
for (const sys of systems) {
|
|
2233
|
+
const sysArcs = arcs.filter((a) => a.prn[0] === sys);
|
|
2234
|
+
const wlArcs = sysArcs.filter((a) => a.nEpochs >= minWlObs).map((a) => ({
|
|
2235
|
+
station: a.station,
|
|
2236
|
+
prn: a.prn,
|
|
2237
|
+
wlFloat: a.mwCyc,
|
|
2238
|
+
nObs: a.nEpochs
|
|
2239
|
+
}));
|
|
2240
|
+
if (wlArcs.length < 3) continue;
|
|
2241
|
+
const wl = estimateWidelaneFcb(wlArcs, { fixWindow });
|
|
2242
|
+
const nlInput = sysArcs.filter((a) => a.nEpochs >= minArcEpochs);
|
|
2243
|
+
const nl = estimateNarrowlaneFcb(nlInput, wl, { fixWindow });
|
|
2244
|
+
for (const [prn, v] of wl.satFcb) satWlFcb.set(prn, v);
|
|
2245
|
+
for (const [prn, v] of nl.satFcb) satNlFcb.set(prn, v);
|
|
2246
|
+
perSystem[sys] = {
|
|
2247
|
+
wlFixRate: wl.fixRate,
|
|
2248
|
+
wlResidRms: wl.residRms,
|
|
2249
|
+
nlUsedArcs: nl.usedArcs,
|
|
2250
|
+
nlFixRate: nl.fixRate,
|
|
2251
|
+
nlResidRms: nl.residRms,
|
|
2252
|
+
wlRejected: nl.wlRejected
|
|
2253
|
+
};
|
|
2254
|
+
}
|
|
2255
|
+
return { satWlFcb, satNlFcb, perSystem };
|
|
2256
|
+
}
|
|
2139
2257
|
|
|
2140
2258
|
// src/positioning/index.ts
|
|
2141
2259
|
var GM_GPS = 3986005e8;
|
|
@@ -2388,6 +2506,8 @@ export {
|
|
|
2388
2506
|
resolvePppAmbiguities,
|
|
2389
2507
|
extractWidelaneArcs,
|
|
2390
2508
|
estimateWidelaneFcb,
|
|
2509
|
+
estimateNarrowlaneFcb,
|
|
2510
|
+
estimateNetworkFcbs,
|
|
2391
2511
|
satClockCorrection,
|
|
2392
2512
|
ionoFree,
|
|
2393
2513
|
solveSpp
|
package/dist/index.cjs
CHANGED
|
@@ -149,6 +149,8 @@ __export(src_exports, {
|
|
|
149
149
|
ecefToAzEl: () => ecefToAzEl,
|
|
150
150
|
ecefToGeodetic: () => ecefToGeodetic,
|
|
151
151
|
ephInfoToEphemeris: () => ephInfoToEphemeris,
|
|
152
|
+
estimateNarrowlaneFcb: () => estimateNarrowlaneFcb,
|
|
153
|
+
estimateNetworkFcbs: () => estimateNetworkFcbs,
|
|
152
154
|
estimateWidelaneFcb: () => estimateWidelaneFcb,
|
|
153
155
|
euclidean3D: () => euclidean3D,
|
|
154
156
|
extractWidelaneArcs: () => extractWidelaneArcs,
|
|
@@ -1067,7 +1069,7 @@ function vincenty(lat1, lon1, lat2, lon2) {
|
|
|
1067
1069
|
let lambdaPrev;
|
|
1068
1070
|
let sinSigma, cosSigma, sigma;
|
|
1069
1071
|
let sinAlpha, cos2Alpha, cos2SigmaM;
|
|
1070
|
-
let
|
|
1072
|
+
let C2;
|
|
1071
1073
|
let iter = 0;
|
|
1072
1074
|
do {
|
|
1073
1075
|
const sinLambda2 = Math.sin(lambda);
|
|
@@ -1083,9 +1085,9 @@ function vincenty(lat1, lon1, lat2, lon2) {
|
|
|
1083
1085
|
sinAlpha = cosU1 * cosU2 * sinLambda2 / sinSigma;
|
|
1084
1086
|
cos2Alpha = 1 - sinAlpha ** 2;
|
|
1085
1087
|
cos2SigmaM = cos2Alpha !== 0 ? cosSigma - 2 * sinU1 * sinU2 / cos2Alpha : 0;
|
|
1086
|
-
|
|
1088
|
+
C2 = WGS84_FLATTENING / 16 * cos2Alpha * (4 + WGS84_FLATTENING * (4 - 3 * cos2Alpha));
|
|
1087
1089
|
lambdaPrev = lambda;
|
|
1088
|
-
lambda = lon2 - lon1 + (1 -
|
|
1090
|
+
lambda = lon2 - lon1 + (1 - C2) * WGS84_FLATTENING * sinAlpha * (sigma + C2 * sinSigma * (cos2SigmaM + C2 * cosSigma * (-1 + 2 * cos2SigmaM ** 2)));
|
|
1089
1091
|
} while (Math.abs(lambda - lambdaPrev) > 1e-12 && ++iter < 200);
|
|
1090
1092
|
if (iter >= 200) {
|
|
1091
1093
|
const cosLat1 = Math.cos(lat1), sinLat1 = Math.sin(lat1);
|
|
@@ -1189,11 +1191,11 @@ function geodeticToUtm(lat, lon) {
|
|
|
1189
1191
|
const ep2 = e2 / (1 - e2);
|
|
1190
1192
|
const N = WGS84_SEMI_MAJOR_AXIS / Math.sqrt(1 - e2 * Math.sin(lat) ** 2);
|
|
1191
1193
|
const T = Math.tan(lat) ** 2;
|
|
1192
|
-
const
|
|
1194
|
+
const C2 = ep2 * Math.cos(lat) ** 2;
|
|
1193
1195
|
const A = Math.cos(lat) * (lon - lon0);
|
|
1194
1196
|
const M = WGS84_SEMI_MAJOR_AXIS * ((1 - e2 / 4 - 3 * e2 ** 2 / 64 - 5 * e2 ** 3 / 256) * lat - (3 * e2 / 8 + 3 * e2 ** 2 / 32 + 45 * e2 ** 3 / 1024) * Math.sin(2 * lat) + (15 * e2 ** 2 / 256 + 45 * e2 ** 3 / 1024) * Math.sin(4 * lat) - 35 * e2 ** 3 / 3072 * Math.sin(6 * lat));
|
|
1195
|
-
const easting = k0 * N * (A + (1 - T +
|
|
1196
|
-
let northing = k0 * (M + N * Math.tan(lat) * (A ** 2 / 2 + (5 - T + 9 *
|
|
1197
|
+
const easting = k0 * N * (A + (1 - T + C2) * A ** 3 / 6 + (5 - 18 * T + T ** 2 + 72 * C2 - 58 * ep2) * A ** 5 / 120) + 5e5;
|
|
1198
|
+
let northing = k0 * (M + N * Math.tan(lat) * (A ** 2 / 2 + (5 - T + 9 * C2 + 4 * C2 ** 2) * A ** 4 / 24 + (61 - 58 * T + T ** 2 + 600 * C2 - 330 * ep2) * A ** 6 / 720));
|
|
1197
1199
|
const hemisphere = latDeg >= 0 ? "N" : "S";
|
|
1198
1200
|
if (hemisphere === "S") {
|
|
1199
1201
|
northing += 1e7;
|
|
@@ -11857,15 +11859,15 @@ function matMul(A, B) {
|
|
|
11857
11859
|
const n = A.length;
|
|
11858
11860
|
const k = B.length;
|
|
11859
11861
|
const m = B[0]?.length ?? 0;
|
|
11860
|
-
const
|
|
11862
|
+
const C2 = zeros(n, m);
|
|
11861
11863
|
for (let i = 0; i < n; i++) {
|
|
11862
11864
|
for (let l = 0; l < k; l++) {
|
|
11863
11865
|
const a = A[i][l];
|
|
11864
11866
|
if (a === 0) continue;
|
|
11865
|
-
for (let j = 0; j < m; j++)
|
|
11867
|
+
for (let j = 0; j < m; j++) C2[i][j] += a * B[l][j];
|
|
11866
11868
|
}
|
|
11867
11869
|
}
|
|
11868
|
-
return
|
|
11870
|
+
return C2;
|
|
11869
11871
|
}
|
|
11870
11872
|
function transpose(A) {
|
|
11871
11873
|
const n = A.length;
|
|
@@ -13045,6 +13047,24 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
13045
13047
|
const clockSeeded = /* @__PURE__ */ new Set();
|
|
13046
13048
|
const ambIdx = /* @__PURE__ */ new Map();
|
|
13047
13049
|
const lastSeen = /* @__PURE__ */ new Map();
|
|
13050
|
+
const arcs = [];
|
|
13051
|
+
const arcSnap = /* @__PURE__ */ new Map();
|
|
13052
|
+
const flushArc = (prn, minEpochs = 10) => {
|
|
13053
|
+
const s = arcSnap.get(prn);
|
|
13054
|
+
arcSnap.delete(prn);
|
|
13055
|
+
if (!s || s.nEpochs < minEpochs) return;
|
|
13056
|
+
arcs.push({
|
|
13057
|
+
prn,
|
|
13058
|
+
aIF: s.aIF,
|
|
13059
|
+
mwCyc: s.mwCyc,
|
|
13060
|
+
f1: s.f1,
|
|
13061
|
+
f2: s.f2,
|
|
13062
|
+
meanElevDeg: s.elevSum / s.nEpochs,
|
|
13063
|
+
nEpochs: s.nEpochs,
|
|
13064
|
+
startMs: s.startMs,
|
|
13065
|
+
endMs: s.endMs
|
|
13066
|
+
});
|
|
13067
|
+
};
|
|
13048
13068
|
const mwState = /* @__PURE__ */ new Map();
|
|
13049
13069
|
const detectSlip = (o, ei) => {
|
|
13050
13070
|
const lamW = C_LIGHT / (o.f1 - o.f2);
|
|
@@ -13162,7 +13182,9 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
13162
13182
|
tropoFixed: zhd * mh + corr.rangeM,
|
|
13163
13183
|
mw,
|
|
13164
13184
|
windupM: corr.phaseWindupM,
|
|
13165
|
-
slip
|
|
13185
|
+
slip,
|
|
13186
|
+
f1: o.f1,
|
|
13187
|
+
f2: o.f2
|
|
13166
13188
|
});
|
|
13167
13189
|
}
|
|
13168
13190
|
const zwd0 = x[IDX_ZWD];
|
|
@@ -13187,6 +13209,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
13187
13209
|
for (const v of vis) {
|
|
13188
13210
|
const ci = clockOf(v.prn[0]);
|
|
13189
13211
|
const common = v.range + x[ci] - v.satClkM + v.tropoFixed + zwd0 * v.mw;
|
|
13212
|
+
if (v.slip) flushArc(v.prn);
|
|
13190
13213
|
let ai = ambIdx.get(v.prn);
|
|
13191
13214
|
if (ai === void 0 || v.slip) {
|
|
13192
13215
|
const bInit = v.lIf - (common + v.windupM);
|
|
@@ -13220,6 +13243,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
13220
13243
|
const commonPh = v.range + x[ci] - v.satClkM + v.tropoFixed + x[IDX_ZWD] * v.mw;
|
|
13221
13244
|
const innov = v.lIf - (commonPh + v.windupM + x[ai]);
|
|
13222
13245
|
if (Math.abs(innov) > 0.15) {
|
|
13246
|
+
flushArc(v.prn);
|
|
13223
13247
|
x[ai] = v.lIf - (commonPh + v.windupM);
|
|
13224
13248
|
for (let j = 0; j < P.length; j++) {
|
|
13225
13249
|
P[ai][j] = 0;
|
|
@@ -13237,6 +13261,29 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
13237
13261
|
ekfUpdateScalar(x, P, h, innov, rPhase, 4);
|
|
13238
13262
|
}
|
|
13239
13263
|
}
|
|
13264
|
+
{
|
|
13265
|
+
const elevDeg = v.elRad * 180 / Math.PI;
|
|
13266
|
+
const mwMean = mwState.get(v.prn)?.mean ?? 0;
|
|
13267
|
+
const s = arcSnap.get(v.prn);
|
|
13268
|
+
if (s) {
|
|
13269
|
+
s.aIF = x[ai];
|
|
13270
|
+
s.mwCyc = mwMean;
|
|
13271
|
+
s.elevSum += elevDeg;
|
|
13272
|
+
s.nEpochs++;
|
|
13273
|
+
s.endMs = epoch.timeMs;
|
|
13274
|
+
} else {
|
|
13275
|
+
arcSnap.set(v.prn, {
|
|
13276
|
+
aIF: x[ai],
|
|
13277
|
+
mwCyc: mwMean,
|
|
13278
|
+
f1: v.f1,
|
|
13279
|
+
f2: v.f2,
|
|
13280
|
+
elevSum: elevDeg,
|
|
13281
|
+
nEpochs: 1,
|
|
13282
|
+
startMs: epoch.timeMs,
|
|
13283
|
+
endMs: epoch.timeMs
|
|
13284
|
+
});
|
|
13285
|
+
}
|
|
13286
|
+
}
|
|
13240
13287
|
lastSeen.set(v.prn, ei);
|
|
13241
13288
|
nSats++;
|
|
13242
13289
|
}
|
|
@@ -13270,6 +13317,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
13270
13317
|
const idx = ambIdx.get(prn);
|
|
13271
13318
|
if (idx !== void 0) dropState(idx);
|
|
13272
13319
|
lastSeen.delete(prn);
|
|
13320
|
+
flushArc(prn);
|
|
13273
13321
|
}
|
|
13274
13322
|
}
|
|
13275
13323
|
const pos = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
@@ -13309,6 +13357,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
13309
13357
|
phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0
|
|
13310
13358
|
});
|
|
13311
13359
|
}
|
|
13360
|
+
for (const prn of [...arcSnap.keys()]) flushArc(prn);
|
|
13312
13361
|
const finalPos = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
13313
13362
|
const llh = ecefToGeodetic(finalPos[0], finalPos[1], finalPos[2]);
|
|
13314
13363
|
const finalError3d = truth ? Math.hypot(
|
|
@@ -13323,7 +13372,8 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
13323
13372
|
ztdWet: x[IDX_ZWD],
|
|
13324
13373
|
epochsUsed: epochs.length,
|
|
13325
13374
|
convergenceSec,
|
|
13326
|
-
finalError3d
|
|
13375
|
+
finalError3d,
|
|
13376
|
+
arcs
|
|
13327
13377
|
};
|
|
13328
13378
|
}
|
|
13329
13379
|
|
|
@@ -13464,34 +13514,34 @@ function circMean(vals, weights) {
|
|
|
13464
13514
|
if (s === 0 && c === 0) return 0;
|
|
13465
13515
|
return wrapHalf(Math.atan2(s, c) / (2 * Math.PI));
|
|
13466
13516
|
}
|
|
13467
|
-
function
|
|
13517
|
+
function decomposeFcb(entries, opts = {}) {
|
|
13468
13518
|
const maxIter = opts.maxIter ?? 50;
|
|
13469
13519
|
const tol = opts.tol ?? 1e-4;
|
|
13470
13520
|
const fixWindow = opts.fixWindow ?? 0.25;
|
|
13471
|
-
const sats = [...new Set(
|
|
13472
|
-
const stations = [...new Set(
|
|
13521
|
+
const sats = [...new Set(entries.map((e) => e.sat))].sort();
|
|
13522
|
+
const stations = [...new Set(entries.map((e) => e.station))].sort();
|
|
13473
13523
|
const refStation = stations[0] ?? "";
|
|
13474
13524
|
const satFcb = new Map(sats.map((s) => [s, 0]));
|
|
13475
13525
|
const rcvBias = new Map(stations.map((s) => [s, 0]));
|
|
13476
|
-
const nInt = new Array(
|
|
13526
|
+
const nInt = new Array(entries.length).fill(0);
|
|
13477
13527
|
let iterations = 0;
|
|
13478
13528
|
for (let it = 0; it < maxIter; it++) {
|
|
13479
13529
|
iterations = it + 1;
|
|
13480
|
-
for (let i = 0; i <
|
|
13481
|
-
const
|
|
13530
|
+
for (let i = 0; i < entries.length; i++) {
|
|
13531
|
+
const e = entries[i];
|
|
13482
13532
|
nInt[i] = Math.round(
|
|
13483
|
-
|
|
13533
|
+
e.value - rcvBias.get(e.station) - satFcb.get(e.sat)
|
|
13484
13534
|
);
|
|
13485
13535
|
}
|
|
13486
13536
|
let maxChange = 0;
|
|
13487
13537
|
for (const s of sats) {
|
|
13488
13538
|
const vals = [];
|
|
13489
13539
|
const w = [];
|
|
13490
|
-
for (let i = 0; i <
|
|
13491
|
-
const
|
|
13492
|
-
if (
|
|
13493
|
-
vals.push(
|
|
13494
|
-
w.push(
|
|
13540
|
+
for (let i = 0; i < entries.length; i++) {
|
|
13541
|
+
const e = entries[i];
|
|
13542
|
+
if (e.sat !== s) continue;
|
|
13543
|
+
vals.push(e.value - nInt[i] - rcvBias.get(e.station));
|
|
13544
|
+
w.push(e.weight);
|
|
13495
13545
|
}
|
|
13496
13546
|
if (!vals.length) continue;
|
|
13497
13547
|
const nv = circMean(vals, w);
|
|
@@ -13501,11 +13551,11 @@ function estimateWidelaneFcb(arcs, opts = {}) {
|
|
|
13501
13551
|
for (const r of stations) {
|
|
13502
13552
|
const vals = [];
|
|
13503
13553
|
const w = [];
|
|
13504
|
-
for (let i = 0; i <
|
|
13505
|
-
const
|
|
13506
|
-
if (
|
|
13507
|
-
vals.push(
|
|
13508
|
-
w.push(
|
|
13554
|
+
for (let i = 0; i < entries.length; i++) {
|
|
13555
|
+
const e = entries[i];
|
|
13556
|
+
if (e.station !== r) continue;
|
|
13557
|
+
vals.push(e.value - nInt[i] - satFcb.get(e.sat));
|
|
13558
|
+
w.push(e.weight);
|
|
13509
13559
|
}
|
|
13510
13560
|
if (!vals.length) continue;
|
|
13511
13561
|
rcvBias.set(r, circMean(vals, w));
|
|
@@ -13520,18 +13570,88 @@ function estimateWidelaneFcb(arcs, opts = {}) {
|
|
|
13520
13570
|
}
|
|
13521
13571
|
let sumSq = 0;
|
|
13522
13572
|
let fixed = 0;
|
|
13523
|
-
for (let i = 0; i <
|
|
13524
|
-
const
|
|
13573
|
+
for (let i = 0; i < entries.length; i++) {
|
|
13574
|
+
const e = entries[i];
|
|
13525
13575
|
const resid = wrapHalf(
|
|
13526
|
-
|
|
13576
|
+
e.value - nInt[i] - rcvBias.get(e.station) - satFcb.get(e.sat)
|
|
13527
13577
|
);
|
|
13528
13578
|
sumSq += resid * resid;
|
|
13529
13579
|
if (Math.abs(resid) <= fixWindow) fixed++;
|
|
13530
13580
|
}
|
|
13531
|
-
const residRms =
|
|
13532
|
-
const fixRate =
|
|
13581
|
+
const residRms = entries.length ? Math.sqrt(sumSq / entries.length) : 0;
|
|
13582
|
+
const fixRate = entries.length ? fixed / entries.length : 0;
|
|
13533
13583
|
return { satFcb, rcvBias, residRms, fixRate, refStation, iterations };
|
|
13534
13584
|
}
|
|
13585
|
+
function estimateWidelaneFcb(arcs, opts = {}) {
|
|
13586
|
+
return decomposeFcb(
|
|
13587
|
+
arcs.map((a) => ({
|
|
13588
|
+
station: a.station,
|
|
13589
|
+
sat: a.prn,
|
|
13590
|
+
value: a.wlFloat,
|
|
13591
|
+
weight: a.nObs
|
|
13592
|
+
})),
|
|
13593
|
+
opts
|
|
13594
|
+
);
|
|
13595
|
+
}
|
|
13596
|
+
var C = 299792458;
|
|
13597
|
+
function estimateNarrowlaneFcb(arcs, wl, opts = {}) {
|
|
13598
|
+
const entries = [];
|
|
13599
|
+
let wlRejected = 0;
|
|
13600
|
+
for (const a of arcs) {
|
|
13601
|
+
const satWl = wl.satFcb.get(a.prn);
|
|
13602
|
+
const rcvWl = wl.rcvBias.get(a.station);
|
|
13603
|
+
if (satWl === void 0 || rcvWl === void 0) continue;
|
|
13604
|
+
const wlFloat = a.mwCyc - satWl - rcvWl;
|
|
13605
|
+
const nWl = Math.round(wlFloat);
|
|
13606
|
+
if (Math.abs(wlFloat - nWl) > (opts.fixWindow ?? 0.25)) {
|
|
13607
|
+
wlRejected++;
|
|
13608
|
+
continue;
|
|
13609
|
+
}
|
|
13610
|
+
const lamNl = C / (a.f1 + a.f2);
|
|
13611
|
+
const n1Float = a.aIF / lamNl - a.f2 / (a.f1 - a.f2) * nWl;
|
|
13612
|
+
entries.push({
|
|
13613
|
+
station: a.station,
|
|
13614
|
+
sat: a.prn,
|
|
13615
|
+
value: n1Float,
|
|
13616
|
+
weight: a.nEpochs
|
|
13617
|
+
});
|
|
13618
|
+
}
|
|
13619
|
+
const res = decomposeFcb(entries, { fixWindow: 0.15, ...opts });
|
|
13620
|
+
return { ...res, usedArcs: entries.length, wlRejected };
|
|
13621
|
+
}
|
|
13622
|
+
function estimateNetworkFcbs(arcs, opts = {}) {
|
|
13623
|
+
const minArcEpochs = opts.minArcEpochs ?? 120;
|
|
13624
|
+
const minWlObs = opts.minWlObs ?? 40;
|
|
13625
|
+
const fixWindow = opts.fixWindow ?? 0.15;
|
|
13626
|
+
const satWlFcb = /* @__PURE__ */ new Map();
|
|
13627
|
+
const satNlFcb = /* @__PURE__ */ new Map();
|
|
13628
|
+
const perSystem = {};
|
|
13629
|
+
const systems = [...new Set(arcs.map((a) => a.prn[0]))].sort();
|
|
13630
|
+
for (const sys of systems) {
|
|
13631
|
+
const sysArcs = arcs.filter((a) => a.prn[0] === sys);
|
|
13632
|
+
const wlArcs = sysArcs.filter((a) => a.nEpochs >= minWlObs).map((a) => ({
|
|
13633
|
+
station: a.station,
|
|
13634
|
+
prn: a.prn,
|
|
13635
|
+
wlFloat: a.mwCyc,
|
|
13636
|
+
nObs: a.nEpochs
|
|
13637
|
+
}));
|
|
13638
|
+
if (wlArcs.length < 3) continue;
|
|
13639
|
+
const wl = estimateWidelaneFcb(wlArcs, { fixWindow });
|
|
13640
|
+
const nlInput = sysArcs.filter((a) => a.nEpochs >= minArcEpochs);
|
|
13641
|
+
const nl = estimateNarrowlaneFcb(nlInput, wl, { fixWindow });
|
|
13642
|
+
for (const [prn, v] of wl.satFcb) satWlFcb.set(prn, v);
|
|
13643
|
+
for (const [prn, v] of nl.satFcb) satNlFcb.set(prn, v);
|
|
13644
|
+
perSystem[sys] = {
|
|
13645
|
+
wlFixRate: wl.fixRate,
|
|
13646
|
+
wlResidRms: wl.residRms,
|
|
13647
|
+
nlUsedArcs: nl.usedArcs,
|
|
13648
|
+
nlFixRate: nl.fixRate,
|
|
13649
|
+
nlResidRms: nl.residRms,
|
|
13650
|
+
wlRejected: nl.wlRejected
|
|
13651
|
+
};
|
|
13652
|
+
}
|
|
13653
|
+
return { satWlFcb, satNlFcb, perSystem };
|
|
13654
|
+
}
|
|
13535
13655
|
|
|
13536
13656
|
// src/positioning/index.ts
|
|
13537
13657
|
var GM_GPS3 = 3986005e8;
|
|
@@ -13943,9 +14063,9 @@ var MultipathAccumulator = class {
|
|
|
13943
14063
|
const bandMap = this.obsIndices.get(sys) ?? this.obsIndices.get("_v2");
|
|
13944
14064
|
if (!bandMap) return;
|
|
13945
14065
|
const bandData = /* @__PURE__ */ new Map();
|
|
13946
|
-
for (const [band, { C, L }] of bandMap) {
|
|
13947
|
-
if (
|
|
13948
|
-
const cVal = values[
|
|
14066
|
+
for (const [band, { C: C2, L }] of bandMap) {
|
|
14067
|
+
if (C2 === null) continue;
|
|
14068
|
+
const cVal = values[C2];
|
|
13949
14069
|
const lVal = values[L];
|
|
13950
14070
|
const freq = getFreq(this.gloChannels, prn, band);
|
|
13951
14071
|
if (cVal != null && cVal !== 0 && lVal != null && lVal !== 0 && freq) {
|
|
@@ -14157,13 +14277,13 @@ var CycleSlipAccumulator = class {
|
|
|
14157
14277
|
if (sys !== "R" && !FREQ[sys]) return;
|
|
14158
14278
|
const phaseM = /* @__PURE__ */ new Map();
|
|
14159
14279
|
const codeM = /* @__PURE__ */ new Map();
|
|
14160
|
-
for (const [band, { L, C }] of idxMap) {
|
|
14280
|
+
for (const [band, { L, C: C2 }] of idxMap) {
|
|
14161
14281
|
const freq = this.getFreqForPrn(prn, band);
|
|
14162
14282
|
if (!freq) continue;
|
|
14163
14283
|
const lVal = values[L];
|
|
14164
14284
|
if (lVal != null && lVal !== 0) phaseM.set(band, lVal * (C_LIGHT / freq));
|
|
14165
|
-
if (
|
|
14166
|
-
const cVal = values[
|
|
14285
|
+
if (C2 !== null) {
|
|
14286
|
+
const cVal = values[C2];
|
|
14167
14287
|
if (cVal != null && cVal !== 0) codeM.set(band, cVal);
|
|
14168
14288
|
}
|
|
14169
14289
|
}
|
|
@@ -14427,9 +14547,9 @@ var IonoAccumulator = class {
|
|
|
14427
14547
|
const bandMap = this.obsIndices.get(sys) ?? this.obsIndices.get("_v2");
|
|
14428
14548
|
if (!bandMap) return;
|
|
14429
14549
|
const bandData = /* @__PURE__ */ new Map();
|
|
14430
|
-
for (const [band, { C, L }] of bandMap) {
|
|
14431
|
-
if (
|
|
14432
|
-
const cVal = values[
|
|
14550
|
+
for (const [band, { C: C2, L }] of bandMap) {
|
|
14551
|
+
if (C2 === null) continue;
|
|
14552
|
+
const cVal = values[C2];
|
|
14433
14553
|
const lVal = values[L];
|
|
14434
14554
|
const freq = getFreq(this.gloChannels, prn, band);
|
|
14435
14555
|
if (cVal != null && cVal !== 0 && lVal != null && lVal !== 0 && freq) {
|
|
@@ -14437,7 +14557,7 @@ var IonoAccumulator = class {
|
|
|
14437
14557
|
C: cVal,
|
|
14438
14558
|
L: lVal,
|
|
14439
14559
|
f: freq,
|
|
14440
|
-
code: codes[
|
|
14560
|
+
code: codes[C2] ?? `C${band}`
|
|
14441
14561
|
});
|
|
14442
14562
|
}
|
|
14443
14563
|
}
|
|
@@ -16150,6 +16270,8 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
16150
16270
|
ecefToAzEl,
|
|
16151
16271
|
ecefToGeodetic,
|
|
16152
16272
|
ephInfoToEphemeris,
|
|
16273
|
+
estimateNarrowlaneFcb,
|
|
16274
|
+
estimateNetworkFcbs,
|
|
16153
16275
|
estimateWidelaneFcb,
|
|
16154
16276
|
euclidean3D,
|
|
16155
16277
|
extractWidelaneArcs,
|
package/dist/index.d.cts
CHANGED
|
@@ -17,7 +17,7 @@ export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, Trimb
|
|
|
17
17
|
export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.cjs';
|
|
18
18
|
export { AllPositionsData, AlmanacPosition, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.cjs';
|
|
19
19
|
export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.cjs';
|
|
20
|
-
export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, DgnssOptions, DgnssSolution, EphemerisSource, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, PppAntennaModel, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, SatGeom, SppOptions, SppSolution, TropoMapping, WlArc, WlFcbOptions, WlFcbResult, WlObs, buildPppAntenna, createPppCorrections, estimateWidelaneFcb, extractWidelaneArcs, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.cjs';
|
|
20
|
+
export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, DgnssOptions, DgnssSolution, EphemerisSource, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, NetworkFcbResult, NetworkFcbSummary, NlArc, NlFcbResult, PppAntennaModel, PppArc, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, SatGeom, SppOptions, SppSolution, TropoMapping, WlArc, WlFcbOptions, WlFcbResult, WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.cjs';
|
|
21
21
|
export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.cjs';
|
|
22
22
|
export { CompleteSatSignal, CompleteSignalStats, CompletenessAccumulator, CompletenessResult, CycleSlipAccumulator, CycleSlipEvent, CycleSlipResult, CycleSlipSignalStats, IonoAccumulator, IonoDcbResult, IonoPoint, IonoRatePoint, IonoRateSeries, IonoResult, IonoSeries, MultipathAccumulator, MultipathPoint, MultipathResult, MultipathSeries, MultipathSignalStat, QualityResult, SatDcbMap, analyzeQuality, applyIonoDcb, computeIonoRate, detrendIonoArcs, parseSinexBiasDcb } from './analysis.cjs';
|
|
23
23
|
export { AntennaEntry, AntexFile, FrequencyData, frequencyLabel, parseAntex } from './antex.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, Trimb
|
|
|
17
17
|
export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.js';
|
|
18
18
|
export { AllPositionsData, AlmanacPosition, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.js';
|
|
19
19
|
export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.js';
|
|
20
|
-
export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, DgnssOptions, DgnssSolution, EphemerisSource, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, PppAntennaModel, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, SatGeom, SppOptions, SppSolution, TropoMapping, WlArc, WlFcbOptions, WlFcbResult, WlObs, buildPppAntenna, createPppCorrections, estimateWidelaneFcb, extractWidelaneArcs, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.js';
|
|
20
|
+
export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, DgnssOptions, DgnssSolution, EphemerisSource, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, NetworkFcbResult, NetworkFcbSummary, NlArc, NlFcbResult, PppAntennaModel, PppArc, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, SatGeom, SppOptions, SppSolution, TropoMapping, WlArc, WlFcbOptions, WlFcbResult, WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.js';
|
|
21
21
|
export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.js';
|
|
22
22
|
export { CompleteSatSignal, CompleteSignalStats, CompletenessAccumulator, CompletenessResult, CycleSlipAccumulator, CycleSlipEvent, CycleSlipResult, CycleSlipSignalStats, IonoAccumulator, IonoDcbResult, IonoPoint, IonoRatePoint, IonoRateSeries, IonoResult, IonoSeries, MultipathAccumulator, MultipathPoint, MultipathResult, MultipathSeries, MultipathSignalStat, QualityResult, SatDcbMap, analyzeQuality, applyIonoDcb, computeIonoRate, detrendIonoArcs, parseSinexBiasDcb } from './analysis.js';
|
|
23
23
|
export { AntennaEntry, AntexFile, FrequencyData, frequencyLabel, parseAntex } from './antex.js';
|
package/dist/index.js
CHANGED
|
@@ -146,6 +146,8 @@ import {
|
|
|
146
146
|
RtkFloatEngine,
|
|
147
147
|
buildPppAntenna,
|
|
148
148
|
createPppCorrections,
|
|
149
|
+
estimateNarrowlaneFcb,
|
|
150
|
+
estimateNetworkFcbs,
|
|
149
151
|
estimateWidelaneFcb,
|
|
150
152
|
extractWidelaneArcs,
|
|
151
153
|
gimSlantIonoDelayL1,
|
|
@@ -167,7 +169,7 @@ import {
|
|
|
167
169
|
sunEcef,
|
|
168
170
|
toRtkEpoch,
|
|
169
171
|
wlWavelength
|
|
170
|
-
} from "./chunk-
|
|
172
|
+
} from "./chunk-BLGBMRX7.js";
|
|
171
173
|
import {
|
|
172
174
|
almanacEpochMs,
|
|
173
175
|
almanacSatPosition,
|
|
@@ -474,6 +476,8 @@ export {
|
|
|
474
476
|
ecefToAzEl,
|
|
475
477
|
ecefToGeodetic,
|
|
476
478
|
ephInfoToEphemeris,
|
|
479
|
+
estimateNarrowlaneFcb,
|
|
480
|
+
estimateNetworkFcbs,
|
|
477
481
|
estimateWidelaneFcb,
|
|
478
482
|
euclidean3D,
|
|
479
483
|
extractWidelaneArcs,
|
package/dist/positioning.cjs
CHANGED
|
@@ -24,6 +24,8 @@ __export(positioning_exports, {
|
|
|
24
24
|
RtkFloatEngine: () => RtkFloatEngine,
|
|
25
25
|
buildPppAntenna: () => buildPppAntenna,
|
|
26
26
|
createPppCorrections: () => createPppCorrections,
|
|
27
|
+
estimateNarrowlaneFcb: () => estimateNarrowlaneFcb,
|
|
28
|
+
estimateNetworkFcbs: () => estimateNetworkFcbs,
|
|
27
29
|
estimateWidelaneFcb: () => estimateWidelaneFcb,
|
|
28
30
|
extractWidelaneArcs: () => extractWidelaneArcs,
|
|
29
31
|
gimSlantIonoDelayL1: () => gimSlantIonoDelayL1,
|
|
@@ -913,15 +915,15 @@ function matMul(A, B) {
|
|
|
913
915
|
const n = A.length;
|
|
914
916
|
const k = B.length;
|
|
915
917
|
const m = B[0]?.length ?? 0;
|
|
916
|
-
const
|
|
918
|
+
const C2 = zeros(n, m);
|
|
917
919
|
for (let i = 0; i < n; i++) {
|
|
918
920
|
for (let l = 0; l < k; l++) {
|
|
919
921
|
const a = A[i][l];
|
|
920
922
|
if (a === 0) continue;
|
|
921
|
-
for (let j = 0; j < m; j++)
|
|
923
|
+
for (let j = 0; j < m; j++) C2[i][j] += a * B[l][j];
|
|
922
924
|
}
|
|
923
925
|
}
|
|
924
|
-
return
|
|
926
|
+
return C2;
|
|
925
927
|
}
|
|
926
928
|
function transpose(A) {
|
|
927
929
|
const n = A.length;
|
|
@@ -2173,6 +2175,24 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2173
2175
|
const clockSeeded = /* @__PURE__ */ new Set();
|
|
2174
2176
|
const ambIdx = /* @__PURE__ */ new Map();
|
|
2175
2177
|
const lastSeen = /* @__PURE__ */ new Map();
|
|
2178
|
+
const arcs = [];
|
|
2179
|
+
const arcSnap = /* @__PURE__ */ new Map();
|
|
2180
|
+
const flushArc = (prn, minEpochs = 10) => {
|
|
2181
|
+
const s = arcSnap.get(prn);
|
|
2182
|
+
arcSnap.delete(prn);
|
|
2183
|
+
if (!s || s.nEpochs < minEpochs) return;
|
|
2184
|
+
arcs.push({
|
|
2185
|
+
prn,
|
|
2186
|
+
aIF: s.aIF,
|
|
2187
|
+
mwCyc: s.mwCyc,
|
|
2188
|
+
f1: s.f1,
|
|
2189
|
+
f2: s.f2,
|
|
2190
|
+
meanElevDeg: s.elevSum / s.nEpochs,
|
|
2191
|
+
nEpochs: s.nEpochs,
|
|
2192
|
+
startMs: s.startMs,
|
|
2193
|
+
endMs: s.endMs
|
|
2194
|
+
});
|
|
2195
|
+
};
|
|
2176
2196
|
const mwState = /* @__PURE__ */ new Map();
|
|
2177
2197
|
const detectSlip = (o, ei) => {
|
|
2178
2198
|
const lamW = C_LIGHT / (o.f1 - o.f2);
|
|
@@ -2290,7 +2310,9 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2290
2310
|
tropoFixed: zhd * mh + corr.rangeM,
|
|
2291
2311
|
mw,
|
|
2292
2312
|
windupM: corr.phaseWindupM,
|
|
2293
|
-
slip
|
|
2313
|
+
slip,
|
|
2314
|
+
f1: o.f1,
|
|
2315
|
+
f2: o.f2
|
|
2294
2316
|
});
|
|
2295
2317
|
}
|
|
2296
2318
|
const zwd0 = x[IDX_ZWD];
|
|
@@ -2315,6 +2337,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2315
2337
|
for (const v of vis) {
|
|
2316
2338
|
const ci = clockOf(v.prn[0]);
|
|
2317
2339
|
const common = v.range + x[ci] - v.satClkM + v.tropoFixed + zwd0 * v.mw;
|
|
2340
|
+
if (v.slip) flushArc(v.prn);
|
|
2318
2341
|
let ai = ambIdx.get(v.prn);
|
|
2319
2342
|
if (ai === void 0 || v.slip) {
|
|
2320
2343
|
const bInit = v.lIf - (common + v.windupM);
|
|
@@ -2348,6 +2371,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2348
2371
|
const commonPh = v.range + x[ci] - v.satClkM + v.tropoFixed + x[IDX_ZWD] * v.mw;
|
|
2349
2372
|
const innov = v.lIf - (commonPh + v.windupM + x[ai]);
|
|
2350
2373
|
if (Math.abs(innov) > 0.15) {
|
|
2374
|
+
flushArc(v.prn);
|
|
2351
2375
|
x[ai] = v.lIf - (commonPh + v.windupM);
|
|
2352
2376
|
for (let j = 0; j < P.length; j++) {
|
|
2353
2377
|
P[ai][j] = 0;
|
|
@@ -2365,6 +2389,29 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2365
2389
|
ekfUpdateScalar(x, P, h, innov, rPhase, 4);
|
|
2366
2390
|
}
|
|
2367
2391
|
}
|
|
2392
|
+
{
|
|
2393
|
+
const elevDeg = v.elRad * 180 / Math.PI;
|
|
2394
|
+
const mwMean = mwState.get(v.prn)?.mean ?? 0;
|
|
2395
|
+
const s = arcSnap.get(v.prn);
|
|
2396
|
+
if (s) {
|
|
2397
|
+
s.aIF = x[ai];
|
|
2398
|
+
s.mwCyc = mwMean;
|
|
2399
|
+
s.elevSum += elevDeg;
|
|
2400
|
+
s.nEpochs++;
|
|
2401
|
+
s.endMs = epoch.timeMs;
|
|
2402
|
+
} else {
|
|
2403
|
+
arcSnap.set(v.prn, {
|
|
2404
|
+
aIF: x[ai],
|
|
2405
|
+
mwCyc: mwMean,
|
|
2406
|
+
f1: v.f1,
|
|
2407
|
+
f2: v.f2,
|
|
2408
|
+
elevSum: elevDeg,
|
|
2409
|
+
nEpochs: 1,
|
|
2410
|
+
startMs: epoch.timeMs,
|
|
2411
|
+
endMs: epoch.timeMs
|
|
2412
|
+
});
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2368
2415
|
lastSeen.set(v.prn, ei);
|
|
2369
2416
|
nSats++;
|
|
2370
2417
|
}
|
|
@@ -2398,6 +2445,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2398
2445
|
const idx = ambIdx.get(prn);
|
|
2399
2446
|
if (idx !== void 0) dropState(idx);
|
|
2400
2447
|
lastSeen.delete(prn);
|
|
2448
|
+
flushArc(prn);
|
|
2401
2449
|
}
|
|
2402
2450
|
}
|
|
2403
2451
|
const pos = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
@@ -2437,6 +2485,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2437
2485
|
phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0
|
|
2438
2486
|
});
|
|
2439
2487
|
}
|
|
2488
|
+
for (const prn of [...arcSnap.keys()]) flushArc(prn);
|
|
2440
2489
|
const finalPos = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
2441
2490
|
const llh = ecefToGeodetic(finalPos[0], finalPos[1], finalPos[2]);
|
|
2442
2491
|
const finalError3d = truth ? Math.hypot(
|
|
@@ -2451,7 +2500,8 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
2451
2500
|
ztdWet: x[IDX_ZWD],
|
|
2452
2501
|
epochsUsed: epochs.length,
|
|
2453
2502
|
convergenceSec,
|
|
2454
|
-
finalError3d
|
|
2503
|
+
finalError3d,
|
|
2504
|
+
arcs
|
|
2455
2505
|
};
|
|
2456
2506
|
}
|
|
2457
2507
|
|
|
@@ -2592,34 +2642,34 @@ function circMean(vals, weights) {
|
|
|
2592
2642
|
if (s === 0 && c === 0) return 0;
|
|
2593
2643
|
return wrapHalf(Math.atan2(s, c) / (2 * Math.PI));
|
|
2594
2644
|
}
|
|
2595
|
-
function
|
|
2645
|
+
function decomposeFcb(entries, opts = {}) {
|
|
2596
2646
|
const maxIter = opts.maxIter ?? 50;
|
|
2597
2647
|
const tol = opts.tol ?? 1e-4;
|
|
2598
2648
|
const fixWindow = opts.fixWindow ?? 0.25;
|
|
2599
|
-
const sats = [...new Set(
|
|
2600
|
-
const stations = [...new Set(
|
|
2649
|
+
const sats = [...new Set(entries.map((e) => e.sat))].sort();
|
|
2650
|
+
const stations = [...new Set(entries.map((e) => e.station))].sort();
|
|
2601
2651
|
const refStation = stations[0] ?? "";
|
|
2602
2652
|
const satFcb = new Map(sats.map((s) => [s, 0]));
|
|
2603
2653
|
const rcvBias = new Map(stations.map((s) => [s, 0]));
|
|
2604
|
-
const nInt = new Array(
|
|
2654
|
+
const nInt = new Array(entries.length).fill(0);
|
|
2605
2655
|
let iterations = 0;
|
|
2606
2656
|
for (let it = 0; it < maxIter; it++) {
|
|
2607
2657
|
iterations = it + 1;
|
|
2608
|
-
for (let i = 0; i <
|
|
2609
|
-
const
|
|
2658
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2659
|
+
const e = entries[i];
|
|
2610
2660
|
nInt[i] = Math.round(
|
|
2611
|
-
|
|
2661
|
+
e.value - rcvBias.get(e.station) - satFcb.get(e.sat)
|
|
2612
2662
|
);
|
|
2613
2663
|
}
|
|
2614
2664
|
let maxChange = 0;
|
|
2615
2665
|
for (const s of sats) {
|
|
2616
2666
|
const vals = [];
|
|
2617
2667
|
const w = [];
|
|
2618
|
-
for (let i = 0; i <
|
|
2619
|
-
const
|
|
2620
|
-
if (
|
|
2621
|
-
vals.push(
|
|
2622
|
-
w.push(
|
|
2668
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2669
|
+
const e = entries[i];
|
|
2670
|
+
if (e.sat !== s) continue;
|
|
2671
|
+
vals.push(e.value - nInt[i] - rcvBias.get(e.station));
|
|
2672
|
+
w.push(e.weight);
|
|
2623
2673
|
}
|
|
2624
2674
|
if (!vals.length) continue;
|
|
2625
2675
|
const nv = circMean(vals, w);
|
|
@@ -2629,11 +2679,11 @@ function estimateWidelaneFcb(arcs, opts = {}) {
|
|
|
2629
2679
|
for (const r of stations) {
|
|
2630
2680
|
const vals = [];
|
|
2631
2681
|
const w = [];
|
|
2632
|
-
for (let i = 0; i <
|
|
2633
|
-
const
|
|
2634
|
-
if (
|
|
2635
|
-
vals.push(
|
|
2636
|
-
w.push(
|
|
2682
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2683
|
+
const e = entries[i];
|
|
2684
|
+
if (e.station !== r) continue;
|
|
2685
|
+
vals.push(e.value - nInt[i] - satFcb.get(e.sat));
|
|
2686
|
+
w.push(e.weight);
|
|
2637
2687
|
}
|
|
2638
2688
|
if (!vals.length) continue;
|
|
2639
2689
|
rcvBias.set(r, circMean(vals, w));
|
|
@@ -2648,18 +2698,88 @@ function estimateWidelaneFcb(arcs, opts = {}) {
|
|
|
2648
2698
|
}
|
|
2649
2699
|
let sumSq = 0;
|
|
2650
2700
|
let fixed = 0;
|
|
2651
|
-
for (let i = 0; i <
|
|
2652
|
-
const
|
|
2701
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2702
|
+
const e = entries[i];
|
|
2653
2703
|
const resid = wrapHalf(
|
|
2654
|
-
|
|
2704
|
+
e.value - nInt[i] - rcvBias.get(e.station) - satFcb.get(e.sat)
|
|
2655
2705
|
);
|
|
2656
2706
|
sumSq += resid * resid;
|
|
2657
2707
|
if (Math.abs(resid) <= fixWindow) fixed++;
|
|
2658
2708
|
}
|
|
2659
|
-
const residRms =
|
|
2660
|
-
const fixRate =
|
|
2709
|
+
const residRms = entries.length ? Math.sqrt(sumSq / entries.length) : 0;
|
|
2710
|
+
const fixRate = entries.length ? fixed / entries.length : 0;
|
|
2661
2711
|
return { satFcb, rcvBias, residRms, fixRate, refStation, iterations };
|
|
2662
2712
|
}
|
|
2713
|
+
function estimateWidelaneFcb(arcs, opts = {}) {
|
|
2714
|
+
return decomposeFcb(
|
|
2715
|
+
arcs.map((a) => ({
|
|
2716
|
+
station: a.station,
|
|
2717
|
+
sat: a.prn,
|
|
2718
|
+
value: a.wlFloat,
|
|
2719
|
+
weight: a.nObs
|
|
2720
|
+
})),
|
|
2721
|
+
opts
|
|
2722
|
+
);
|
|
2723
|
+
}
|
|
2724
|
+
var C = 299792458;
|
|
2725
|
+
function estimateNarrowlaneFcb(arcs, wl, opts = {}) {
|
|
2726
|
+
const entries = [];
|
|
2727
|
+
let wlRejected = 0;
|
|
2728
|
+
for (const a of arcs) {
|
|
2729
|
+
const satWl = wl.satFcb.get(a.prn);
|
|
2730
|
+
const rcvWl = wl.rcvBias.get(a.station);
|
|
2731
|
+
if (satWl === void 0 || rcvWl === void 0) continue;
|
|
2732
|
+
const wlFloat = a.mwCyc - satWl - rcvWl;
|
|
2733
|
+
const nWl = Math.round(wlFloat);
|
|
2734
|
+
if (Math.abs(wlFloat - nWl) > (opts.fixWindow ?? 0.25)) {
|
|
2735
|
+
wlRejected++;
|
|
2736
|
+
continue;
|
|
2737
|
+
}
|
|
2738
|
+
const lamNl = C / (a.f1 + a.f2);
|
|
2739
|
+
const n1Float = a.aIF / lamNl - a.f2 / (a.f1 - a.f2) * nWl;
|
|
2740
|
+
entries.push({
|
|
2741
|
+
station: a.station,
|
|
2742
|
+
sat: a.prn,
|
|
2743
|
+
value: n1Float,
|
|
2744
|
+
weight: a.nEpochs
|
|
2745
|
+
});
|
|
2746
|
+
}
|
|
2747
|
+
const res = decomposeFcb(entries, { fixWindow: 0.15, ...opts });
|
|
2748
|
+
return { ...res, usedArcs: entries.length, wlRejected };
|
|
2749
|
+
}
|
|
2750
|
+
function estimateNetworkFcbs(arcs, opts = {}) {
|
|
2751
|
+
const minArcEpochs = opts.minArcEpochs ?? 120;
|
|
2752
|
+
const minWlObs = opts.minWlObs ?? 40;
|
|
2753
|
+
const fixWindow = opts.fixWindow ?? 0.15;
|
|
2754
|
+
const satWlFcb = /* @__PURE__ */ new Map();
|
|
2755
|
+
const satNlFcb = /* @__PURE__ */ new Map();
|
|
2756
|
+
const perSystem = {};
|
|
2757
|
+
const systems = [...new Set(arcs.map((a) => a.prn[0]))].sort();
|
|
2758
|
+
for (const sys of systems) {
|
|
2759
|
+
const sysArcs = arcs.filter((a) => a.prn[0] === sys);
|
|
2760
|
+
const wlArcs = sysArcs.filter((a) => a.nEpochs >= minWlObs).map((a) => ({
|
|
2761
|
+
station: a.station,
|
|
2762
|
+
prn: a.prn,
|
|
2763
|
+
wlFloat: a.mwCyc,
|
|
2764
|
+
nObs: a.nEpochs
|
|
2765
|
+
}));
|
|
2766
|
+
if (wlArcs.length < 3) continue;
|
|
2767
|
+
const wl = estimateWidelaneFcb(wlArcs, { fixWindow });
|
|
2768
|
+
const nlInput = sysArcs.filter((a) => a.nEpochs >= minArcEpochs);
|
|
2769
|
+
const nl = estimateNarrowlaneFcb(nlInput, wl, { fixWindow });
|
|
2770
|
+
for (const [prn, v] of wl.satFcb) satWlFcb.set(prn, v);
|
|
2771
|
+
for (const [prn, v] of nl.satFcb) satNlFcb.set(prn, v);
|
|
2772
|
+
perSystem[sys] = {
|
|
2773
|
+
wlFixRate: wl.fixRate,
|
|
2774
|
+
wlResidRms: wl.residRms,
|
|
2775
|
+
nlUsedArcs: nl.usedArcs,
|
|
2776
|
+
nlFixRate: nl.fixRate,
|
|
2777
|
+
nlResidRms: nl.residRms,
|
|
2778
|
+
wlRejected: nl.wlRejected
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2781
|
+
return { satWlFcb, satNlFcb, perSystem };
|
|
2782
|
+
}
|
|
2663
2783
|
|
|
2664
2784
|
// src/positioning/index.ts
|
|
2665
2785
|
var GM_GPS2 = 3986005e8;
|
|
@@ -2894,6 +3014,8 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
|
|
|
2894
3014
|
RtkFloatEngine,
|
|
2895
3015
|
buildPppAntenna,
|
|
2896
3016
|
createPppCorrections,
|
|
3017
|
+
estimateNarrowlaneFcb,
|
|
3018
|
+
estimateNetworkFcbs,
|
|
2897
3019
|
estimateWidelaneFcb,
|
|
2898
3020
|
extractWidelaneArcs,
|
|
2899
3021
|
gimSlantIonoDelayL1,
|
package/dist/positioning.d.cts
CHANGED
|
@@ -666,6 +666,26 @@ interface PppSolution {
|
|
|
666
666
|
convergenceSec: number | null;
|
|
667
667
|
/** Final 3D error vs ground truth (m), if given. */
|
|
668
668
|
finalError3d: number | null;
|
|
669
|
+
/** Per-arc converged float ambiguities — one per continuous satellite
|
|
670
|
+
* tracking arc — the raw material for ambiguity resolution (PPP-AR). */
|
|
671
|
+
arcs: PppArc[];
|
|
672
|
+
}
|
|
673
|
+
/** A converged carrier-phase arc: the float ionosphere-free ambiguity plus
|
|
674
|
+
* the wide-lane, for integer resolution / FCB estimation. */
|
|
675
|
+
interface PppArc {
|
|
676
|
+
prn: string;
|
|
677
|
+
/** Final float ionosphere-free ambiguity (m). */
|
|
678
|
+
aIF: number;
|
|
679
|
+
/** Arc-averaged Melbourne–Wübbena wide-lane (cycles). */
|
|
680
|
+
mwCyc: number;
|
|
681
|
+
f1: number;
|
|
682
|
+
f2: number;
|
|
683
|
+
/** Mean satellite elevation over the arc (deg). */
|
|
684
|
+
meanElevDeg: number;
|
|
685
|
+
/** Epochs in the arc. */
|
|
686
|
+
nEpochs: number;
|
|
687
|
+
startMs: number;
|
|
688
|
+
endMs: number;
|
|
669
689
|
}
|
|
670
690
|
declare function solvePpp(epochs: PppEpoch[], sp3: Sp3File, opts: PppOptions): PppSolution;
|
|
671
691
|
|
|
@@ -879,6 +899,73 @@ interface WlFcbResult {
|
|
|
879
899
|
* integer/bias entanglement.
|
|
880
900
|
*/
|
|
881
901
|
declare function estimateWidelaneFcb(arcs: WlArc[], opts?: WlFcbOptions): WlFcbResult;
|
|
902
|
+
/** One converged arc (from `solvePpp`) tagged with its station, for NL FCB. */
|
|
903
|
+
interface NlArc {
|
|
904
|
+
station: string;
|
|
905
|
+
prn: string;
|
|
906
|
+
/** Float ionosphere-free ambiguity (m). */
|
|
907
|
+
aIF: number;
|
|
908
|
+
/** Arc-averaged Melbourne–Wübbena wide-lane (cycles). */
|
|
909
|
+
mwCyc: number;
|
|
910
|
+
f1: number;
|
|
911
|
+
f2: number;
|
|
912
|
+
nEpochs: number;
|
|
913
|
+
}
|
|
914
|
+
interface NlFcbResult extends WlFcbResult {
|
|
915
|
+
/** Arcs whose wide-lane fixed and were used in the narrow-lane estimation. */
|
|
916
|
+
usedArcs: number;
|
|
917
|
+
/** Arcs dropped because the wide-lane did not round confidently. */
|
|
918
|
+
wlRejected: number;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Estimate per-satellite **narrow-lane** FCBs — the centimetre half of
|
|
922
|
+
* PPP-AR. Needs the wide-lane FCBs already solved (`wl`, from the same
|
|
923
|
+
* network) to fix each arc's N_WL, from which the float narrow-lane
|
|
924
|
+
* ambiguity is recovered:
|
|
925
|
+
*
|
|
926
|
+
* A_IF = λ_NL·N1 + λ_NL·(f2/(f1−f2))·N_WL
|
|
927
|
+
* ⇒ N1_float = A_IF/λ_NL − (f2/(f1−f2))·N_WL, λ_NL = c/(f1+f2)
|
|
928
|
+
*
|
|
929
|
+
* then decomposed across the network exactly like the wide-lane. The
|
|
930
|
+
* narrow-lane wavelength is ~10.7 cm, so this is far more sensitive to
|
|
931
|
+
* residual orbit/clock/troposphere/position error than the ~86 cm wide-lane
|
|
932
|
+
* — the fix rate is the honest measure of how close the network is to cm.
|
|
933
|
+
*/
|
|
934
|
+
declare function estimateNarrowlaneFcb(arcs: NlArc[], wl: WlFcbResult, opts?: WlFcbOptions): NlFcbResult;
|
|
935
|
+
interface NetworkFcbSummary {
|
|
936
|
+
wlFixRate: number;
|
|
937
|
+
wlResidRms: number;
|
|
938
|
+
nlUsedArcs: number;
|
|
939
|
+
nlFixRate: number;
|
|
940
|
+
nlResidRms: number;
|
|
941
|
+
wlRejected: number;
|
|
942
|
+
}
|
|
943
|
+
interface NetworkFcbResult {
|
|
944
|
+
/** Per-satellite wide-lane FCB (cycles), all constellations merged. */
|
|
945
|
+
satWlFcb: Map<string, number>;
|
|
946
|
+
/** Per-satellite narrow-lane FCB (cycles), all constellations merged. */
|
|
947
|
+
satNlFcb: Map<string, number>;
|
|
948
|
+
/** Per-constellation fix-rate / residual summary, keyed by system letter. */
|
|
949
|
+
perSystem: Record<string, NetworkFcbSummary>;
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Full network FCB calibration for PPP-AR from a set of `solvePpp` arcs (each
|
|
953
|
+
* tagged with its station), **per constellation** — the receiver wide- and
|
|
954
|
+
* narrow-lane biases are system-specific, so lumping GPS/Galileo/BeiDou under
|
|
955
|
+
* one datum corrupts the fit. Runs the wide-lane then narrow-lane
|
|
956
|
+
* decomposition for each system and merges the per-satellite biases.
|
|
957
|
+
*
|
|
958
|
+
* The satellite FCBs (`satWlFcb`/`satNlFcb`) are the reusable product: a rover
|
|
959
|
+
* applies them and solves only its own receiver bias. Multi-GNSS input
|
|
960
|
+
* multiplies the fixable arcs (Galileo roughly doubles GPS-only) without
|
|
961
|
+
* changing per-arc behaviour — each satellite's arc length is independent of
|
|
962
|
+
* how many constellations are present.
|
|
963
|
+
*/
|
|
964
|
+
declare function estimateNetworkFcbs(arcs: NlArc[], opts?: {
|
|
965
|
+
minArcEpochs?: number;
|
|
966
|
+
minWlObs?: number;
|
|
967
|
+
fixWindow?: number;
|
|
968
|
+
}): NetworkFcbResult;
|
|
882
969
|
|
|
883
970
|
/**
|
|
884
971
|
* Single-point positioning (SPP) from pseudoranges and broadcast
|
|
@@ -969,4 +1056,4 @@ declare function ionoFree(p1: number, p2: number, f1: number, f2: number): numbe
|
|
|
969
1056
|
*/
|
|
970
1057
|
declare function solveSpp(pseudoranges: Map<string, number>, ephemerides: Map<string, Ephemeris>, timeMs: number, opts?: SppOptions): SppSolution | null;
|
|
971
1058
|
|
|
972
|
-
export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, type DgnssOptions, type DgnssSolution, type EphemerisSource, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type PppAntennaModel, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type SatGeom, type SppOptions, type SppSolution, type TropoMapping, type WlArc, type WlFcbOptions, type WlFcbResult, type WlObs, buildPppAntenna, createPppCorrections, estimateWidelaneFcb, extractWidelaneArcs, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
|
|
1059
|
+
export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, type DgnssOptions, type DgnssSolution, type EphemerisSource, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type NetworkFcbResult, type NetworkFcbSummary, type NlArc, type NlFcbResult, type PppAntennaModel, type PppArc, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type SatGeom, type SppOptions, type SppSolution, type TropoMapping, type WlArc, type WlFcbOptions, type WlFcbResult, type WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
|
package/dist/positioning.d.ts
CHANGED
|
@@ -666,6 +666,26 @@ interface PppSolution {
|
|
|
666
666
|
convergenceSec: number | null;
|
|
667
667
|
/** Final 3D error vs ground truth (m), if given. */
|
|
668
668
|
finalError3d: number | null;
|
|
669
|
+
/** Per-arc converged float ambiguities — one per continuous satellite
|
|
670
|
+
* tracking arc — the raw material for ambiguity resolution (PPP-AR). */
|
|
671
|
+
arcs: PppArc[];
|
|
672
|
+
}
|
|
673
|
+
/** A converged carrier-phase arc: the float ionosphere-free ambiguity plus
|
|
674
|
+
* the wide-lane, for integer resolution / FCB estimation. */
|
|
675
|
+
interface PppArc {
|
|
676
|
+
prn: string;
|
|
677
|
+
/** Final float ionosphere-free ambiguity (m). */
|
|
678
|
+
aIF: number;
|
|
679
|
+
/** Arc-averaged Melbourne–Wübbena wide-lane (cycles). */
|
|
680
|
+
mwCyc: number;
|
|
681
|
+
f1: number;
|
|
682
|
+
f2: number;
|
|
683
|
+
/** Mean satellite elevation over the arc (deg). */
|
|
684
|
+
meanElevDeg: number;
|
|
685
|
+
/** Epochs in the arc. */
|
|
686
|
+
nEpochs: number;
|
|
687
|
+
startMs: number;
|
|
688
|
+
endMs: number;
|
|
669
689
|
}
|
|
670
690
|
declare function solvePpp(epochs: PppEpoch[], sp3: Sp3File, opts: PppOptions): PppSolution;
|
|
671
691
|
|
|
@@ -879,6 +899,73 @@ interface WlFcbResult {
|
|
|
879
899
|
* integer/bias entanglement.
|
|
880
900
|
*/
|
|
881
901
|
declare function estimateWidelaneFcb(arcs: WlArc[], opts?: WlFcbOptions): WlFcbResult;
|
|
902
|
+
/** One converged arc (from `solvePpp`) tagged with its station, for NL FCB. */
|
|
903
|
+
interface NlArc {
|
|
904
|
+
station: string;
|
|
905
|
+
prn: string;
|
|
906
|
+
/** Float ionosphere-free ambiguity (m). */
|
|
907
|
+
aIF: number;
|
|
908
|
+
/** Arc-averaged Melbourne–Wübbena wide-lane (cycles). */
|
|
909
|
+
mwCyc: number;
|
|
910
|
+
f1: number;
|
|
911
|
+
f2: number;
|
|
912
|
+
nEpochs: number;
|
|
913
|
+
}
|
|
914
|
+
interface NlFcbResult extends WlFcbResult {
|
|
915
|
+
/** Arcs whose wide-lane fixed and were used in the narrow-lane estimation. */
|
|
916
|
+
usedArcs: number;
|
|
917
|
+
/** Arcs dropped because the wide-lane did not round confidently. */
|
|
918
|
+
wlRejected: number;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Estimate per-satellite **narrow-lane** FCBs — the centimetre half of
|
|
922
|
+
* PPP-AR. Needs the wide-lane FCBs already solved (`wl`, from the same
|
|
923
|
+
* network) to fix each arc's N_WL, from which the float narrow-lane
|
|
924
|
+
* ambiguity is recovered:
|
|
925
|
+
*
|
|
926
|
+
* A_IF = λ_NL·N1 + λ_NL·(f2/(f1−f2))·N_WL
|
|
927
|
+
* ⇒ N1_float = A_IF/λ_NL − (f2/(f1−f2))·N_WL, λ_NL = c/(f1+f2)
|
|
928
|
+
*
|
|
929
|
+
* then decomposed across the network exactly like the wide-lane. The
|
|
930
|
+
* narrow-lane wavelength is ~10.7 cm, so this is far more sensitive to
|
|
931
|
+
* residual orbit/clock/troposphere/position error than the ~86 cm wide-lane
|
|
932
|
+
* — the fix rate is the honest measure of how close the network is to cm.
|
|
933
|
+
*/
|
|
934
|
+
declare function estimateNarrowlaneFcb(arcs: NlArc[], wl: WlFcbResult, opts?: WlFcbOptions): NlFcbResult;
|
|
935
|
+
interface NetworkFcbSummary {
|
|
936
|
+
wlFixRate: number;
|
|
937
|
+
wlResidRms: number;
|
|
938
|
+
nlUsedArcs: number;
|
|
939
|
+
nlFixRate: number;
|
|
940
|
+
nlResidRms: number;
|
|
941
|
+
wlRejected: number;
|
|
942
|
+
}
|
|
943
|
+
interface NetworkFcbResult {
|
|
944
|
+
/** Per-satellite wide-lane FCB (cycles), all constellations merged. */
|
|
945
|
+
satWlFcb: Map<string, number>;
|
|
946
|
+
/** Per-satellite narrow-lane FCB (cycles), all constellations merged. */
|
|
947
|
+
satNlFcb: Map<string, number>;
|
|
948
|
+
/** Per-constellation fix-rate / residual summary, keyed by system letter. */
|
|
949
|
+
perSystem: Record<string, NetworkFcbSummary>;
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Full network FCB calibration for PPP-AR from a set of `solvePpp` arcs (each
|
|
953
|
+
* tagged with its station), **per constellation** — the receiver wide- and
|
|
954
|
+
* narrow-lane biases are system-specific, so lumping GPS/Galileo/BeiDou under
|
|
955
|
+
* one datum corrupts the fit. Runs the wide-lane then narrow-lane
|
|
956
|
+
* decomposition for each system and merges the per-satellite biases.
|
|
957
|
+
*
|
|
958
|
+
* The satellite FCBs (`satWlFcb`/`satNlFcb`) are the reusable product: a rover
|
|
959
|
+
* applies them and solves only its own receiver bias. Multi-GNSS input
|
|
960
|
+
* multiplies the fixable arcs (Galileo roughly doubles GPS-only) without
|
|
961
|
+
* changing per-arc behaviour — each satellite's arc length is independent of
|
|
962
|
+
* how many constellations are present.
|
|
963
|
+
*/
|
|
964
|
+
declare function estimateNetworkFcbs(arcs: NlArc[], opts?: {
|
|
965
|
+
minArcEpochs?: number;
|
|
966
|
+
minWlObs?: number;
|
|
967
|
+
fixWindow?: number;
|
|
968
|
+
}): NetworkFcbResult;
|
|
882
969
|
|
|
883
970
|
/**
|
|
884
971
|
* Single-point positioning (SPP) from pseudoranges and broadcast
|
|
@@ -969,4 +1056,4 @@ declare function ionoFree(p1: number, p2: number, f1: number, f2: number): numbe
|
|
|
969
1056
|
*/
|
|
970
1057
|
declare function solveSpp(pseudoranges: Map<string, number>, ephemerides: Map<string, Ephemeris>, timeMs: number, opts?: SppOptions): SppSolution | null;
|
|
971
1058
|
|
|
972
|
-
export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, type DgnssOptions, type DgnssSolution, type EphemerisSource, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type PppAntennaModel, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type SatGeom, type SppOptions, type SppSolution, type TropoMapping, type WlArc, type WlFcbOptions, type WlFcbResult, type WlObs, buildPppAntenna, createPppCorrections, estimateWidelaneFcb, extractWidelaneArcs, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
|
|
1059
|
+
export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, type DgnssOptions, type DgnssSolution, type EphemerisSource, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type NetworkFcbResult, type NetworkFcbSummary, type NlArc, type NlFcbResult, type PppAntennaModel, type PppArc, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type SatGeom, type SppOptions, type SppSolution, type TropoMapping, type WlArc, type WlFcbOptions, type WlFcbResult, type WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
|
package/dist/positioning.js
CHANGED
|
@@ -3,6 +3,8 @@ import {
|
|
|
3
3
|
RtkFloatEngine,
|
|
4
4
|
buildPppAntenna,
|
|
5
5
|
createPppCorrections,
|
|
6
|
+
estimateNarrowlaneFcb,
|
|
7
|
+
estimateNetworkFcbs,
|
|
6
8
|
estimateWidelaneFcb,
|
|
7
9
|
extractWidelaneArcs,
|
|
8
10
|
gimSlantIonoDelayL1,
|
|
@@ -24,7 +26,7 @@ import {
|
|
|
24
26
|
sunEcef,
|
|
25
27
|
toRtkEpoch,
|
|
26
28
|
wlWavelength
|
|
27
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-BLGBMRX7.js";
|
|
28
30
|
import "./chunk-MHGNKSSH.js";
|
|
29
31
|
import "./chunk-37QNKGTC.js";
|
|
30
32
|
import "./chunk-6FAL6P4G.js";
|
|
@@ -37,6 +39,8 @@ export {
|
|
|
37
39
|
RtkFloatEngine,
|
|
38
40
|
buildPppAntenna,
|
|
39
41
|
createPppCorrections,
|
|
42
|
+
estimateNarrowlaneFcb,
|
|
43
|
+
estimateNetworkFcbs,
|
|
40
44
|
estimateWidelaneFcb,
|
|
41
45
|
extractWidelaneArcs,
|
|
42
46
|
gimSlantIonoDelayL1,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gnss-js",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.35.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,
|