gnss-js 2.10.1 → 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -1
- package/dist/analysis.cjs +24 -25
- package/dist/analysis.js +2 -2
- package/dist/{clk-DGVBGRzA.d.cts → bias-sinex-OGMw9xEZ.d.cts} +66 -1
- package/dist/{clk-DGVBGRzA.d.ts → bias-sinex-OGMw9xEZ.d.ts} +66 -1
- package/dist/binex.d.cts +1 -1
- package/dist/binex.d.ts +1 -1
- package/dist/{chunk-56HM5B6T.js → chunk-2DJ4XENO.js} +177 -9
- package/dist/{chunk-GH7MYXON.js → chunk-2KQMCJ5Z.js} +7 -5
- package/dist/chunk-E3Y6YKQM.js +65 -0
- package/dist/{chunk-3U5AX7PY.js → chunk-FEABDV5P.js} +24 -25
- package/dist/{chunk-WQX354KD.js → chunk-H3AKFD25.js} +1 -1
- package/dist/{chunk-YUW33VXK.js → chunk-HUXQABJI.js} +2 -0
- package/dist/{chunk-74IVYOQV.js → chunk-HWHD5E6V.js} +128 -78
- package/dist/{chunk-KUSUN7DP.js → chunk-MFCPYUEI.js} +1 -1
- package/dist/{chunk-3KSDL3CO.js → chunk-NIJ6WFQJ.js} +6 -321
- package/dist/chunk-NL2ORX75.js +319 -0
- package/dist/{chunk-K3GLUWZI.js → chunk-RWFJEVLJ.js} +590 -296
- package/dist/{chunk-SEYH4BEN.js → chunk-SZP4TLYR.js} +2 -2
- package/dist/chunk-TWGZTRBL.js +323 -0
- package/dist/index.cjs +1315 -460
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +20 -12
- package/dist/{nav-DImXUdbp.d.cts → nav-COp0Vmlw.d.cts} +83 -2
- package/dist/{nav-DImXUdbp.d.ts → nav-COp0Vmlw.d.ts} +83 -2
- package/dist/{nav-BYmYoh9A.d.cts → nav-CvZXmumD.d.cts} +1 -1
- package/dist/{nav-CN8rxL4h.d.ts → nav-D2DFlVpa.d.ts} +1 -1
- package/dist/novatel.d.cts +1 -1
- package/dist/novatel.d.ts +1 -1
- package/dist/novatel.js +3 -3
- package/dist/orbit.d.cts +2 -2
- package/dist/orbit.d.ts +2 -2
- package/dist/osnma.cjs +1336 -0
- package/dist/osnma.d.cts +273 -0
- package/dist/osnma.d.ts +273 -0
- package/dist/osnma.js +1216 -0
- package/dist/positioning.cjs +585 -291
- package/dist/positioning.d.cts +116 -6
- package/dist/positioning.d.ts +116 -6
- package/dist/positioning.js +3 -3
- package/dist/rinex.cjs +210 -36
- package/dist/rinex.d.cts +10 -55
- package/dist/rinex.d.ts +10 -55
- package/dist/rinex.js +6 -3
- package/dist/sbf.cjs +420 -24
- package/dist/sbf.d.cts +46 -5
- package/dist/sbf.d.ts +46 -5
- package/dist/sbf.js +12 -6
- package/dist/trimble.d.cts +1 -1
- package/dist/trimble.d.ts +1 -1
- package/dist/ubx.d.cts +1 -1
- package/dist/ubx.d.ts +1 -1
- package/dist/ubx.js +5 -4
- package/package.json +6 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
sbasMessageType
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-H3AKFD25.js";
|
|
4
4
|
import {
|
|
5
5
|
computeDop,
|
|
6
6
|
computeSatPosition,
|
|
@@ -265,6 +265,12 @@ function solveZt(n, m, Z, E) {
|
|
|
265
265
|
for (let cIdx = 0; cIdx < m; cIdx++) X[r + cIdx * n] = M[r * w + n + cIdx];
|
|
266
266
|
return X;
|
|
267
267
|
}
|
|
268
|
+
function normCdf(x) {
|
|
269
|
+
const z = Math.abs(x) / Math.SQRT2;
|
|
270
|
+
const t = 1 / (1 + 0.3275911 * z);
|
|
271
|
+
const erf = 1 - ((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t - 0.284496736) * t + 0.254829592) * t * Math.exp(-z * z);
|
|
272
|
+
return x >= 0 ? 0.5 * (1 + erf) : 0.5 * (1 - erf);
|
|
273
|
+
}
|
|
268
274
|
function lambdaSearch(a, Q, n, m = 2) {
|
|
269
275
|
if (n <= 0 || m <= 0 || a.length < n || Q.length < n * n) return null;
|
|
270
276
|
const L = new Float64Array(n * n);
|
|
@@ -291,7 +297,10 @@ function lambdaSearch(a, Q, n, m = 2) {
|
|
|
291
297
|
candidates.push(v);
|
|
292
298
|
}
|
|
293
299
|
const ratio = m >= 2 && s[0] > 0 ? s[1] / s[0] : Infinity;
|
|
294
|
-
|
|
300
|
+
let successRate = 1;
|
|
301
|
+
for (let i = 0; i < n; i++)
|
|
302
|
+
successRate *= 2 * normCdf(1 / (2 * Math.sqrt(D[i]))) - 1;
|
|
303
|
+
return { candidates, residuals: s, ratio, successRate };
|
|
295
304
|
}
|
|
296
305
|
function lambdaReduction(Q, n) {
|
|
297
306
|
if (n <= 0 || Q.length < n * n) return null;
|
|
@@ -306,7 +315,7 @@ function lambdaReduction(Q, n) {
|
|
|
306
315
|
|
|
307
316
|
// src/positioning/ppp-antenna.ts
|
|
308
317
|
function parseAntexTime(s) {
|
|
309
|
-
const p = s.trim().split(
|
|
318
|
+
const p = s.trim().split(/[\s:-]+/).map(Number);
|
|
310
319
|
if (p.length < 3 || p.some((v) => Number.isNaN(v))) return null;
|
|
311
320
|
return Date.UTC(
|
|
312
321
|
p[0],
|
|
@@ -356,11 +365,21 @@ function buildPppAntenna(antex) {
|
|
|
356
365
|
satOffset(prn, dateMs, band1, band2, f1, f2) {
|
|
357
366
|
const list = sats.get(prn);
|
|
358
367
|
if (!list) return null;
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
368
|
+
let entry;
|
|
369
|
+
let bestDist = Infinity;
|
|
370
|
+
for (const e of list) {
|
|
371
|
+
const from = parseAntexTime(e.validFrom) ?? -Infinity;
|
|
372
|
+
const until = parseAntexTime(e.validUntil) ?? Infinity;
|
|
373
|
+
if (dateMs >= from && dateMs <= until) {
|
|
374
|
+
entry = e;
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
const dist = dateMs < from ? from - dateMs : dateMs - until;
|
|
378
|
+
if (dist < bestDist) {
|
|
379
|
+
bestDist = dist;
|
|
380
|
+
entry = e;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
364
383
|
if (!entry) return null;
|
|
365
384
|
const a = freqOf(entry, band1);
|
|
366
385
|
const b = freqOf(entry, band2);
|
|
@@ -368,10 +387,14 @@ function buildPppAntenna(antex) {
|
|
|
368
387
|
return withZen(entry, combineIf(a, b, f1, f2));
|
|
369
388
|
},
|
|
370
389
|
rcvOffset(antType, band1, band2, f1, f2) {
|
|
371
|
-
const entry = rcvs.get(antType);
|
|
390
|
+
const entry = rcvs.get(antType) ?? rcvs.get(antType.substring(0, 16).padEnd(16, " ") + "NONE");
|
|
372
391
|
if (!entry) return null;
|
|
373
|
-
|
|
374
|
-
|
|
392
|
+
let a = freqOf(entry, band1);
|
|
393
|
+
let b = freqOf(entry, band2);
|
|
394
|
+
if (!a || !b) {
|
|
395
|
+
a = freqOf(entry, "G01");
|
|
396
|
+
b = freqOf(entry, "G02");
|
|
397
|
+
}
|
|
375
398
|
if (!a || !b) return null;
|
|
376
399
|
return withZen(entry, combineIf(a, b, f1, f2));
|
|
377
400
|
}
|
|
@@ -447,13 +470,13 @@ function phaseWindup(prn, losRcvToSat, satFrame, latRad, lonRad, state) {
|
|
|
447
470
|
kx[2] - k[2] * kdotx - kcrossY[2]
|
|
448
471
|
];
|
|
449
472
|
const north = enuToEcef([0, 1, 0], latRad, lonRad);
|
|
450
|
-
const
|
|
473
|
+
const west = enuToEcef([-1, 0, 0], latRad, lonRad);
|
|
451
474
|
const kdotn = dot(k, north);
|
|
452
|
-
const
|
|
475
|
+
const kcrossW = cross(k, west);
|
|
453
476
|
const dR = [
|
|
454
|
-
north[0] - k[0] * kdotn +
|
|
455
|
-
north[1] - k[1] * kdotn +
|
|
456
|
-
north[2] - k[2] * kdotn +
|
|
477
|
+
north[0] - k[0] * kdotn + kcrossW[0],
|
|
478
|
+
north[1] - k[1] * kdotn + kcrossW[1],
|
|
479
|
+
north[2] - k[2] * kdotn + kcrossW[2]
|
|
457
480
|
];
|
|
458
481
|
const nS = Math.hypot(dS[0], dS[1], dS[2]) || 1;
|
|
459
482
|
const nR = Math.hypot(dR[0], dR[1], dR[2]) || 1;
|
|
@@ -580,9 +603,11 @@ function buildGeometry(rover, base, basePos, ephemerides, timeMs, maskRad, tropo
|
|
|
580
603
|
let baseLatRad = 0;
|
|
581
604
|
let baseLonRad = 0;
|
|
582
605
|
if (antenna?.base) {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
606
|
+
[baseLatRad, baseLonRad] = ecefToGeodetic(
|
|
607
|
+
basePos[0],
|
|
608
|
+
basePos[1],
|
|
609
|
+
basePos[2]
|
|
610
|
+
);
|
|
586
611
|
}
|
|
587
612
|
for (const [prn, mR] of rover) {
|
|
588
613
|
const sys = prn[0];
|
|
@@ -678,12 +703,12 @@ function roverTerms(g, x, y, z, troposphere) {
|
|
|
678
703
|
dTropo = tropoDelay(Math.max(elR, 0.05)) - g.tropoB;
|
|
679
704
|
}
|
|
680
705
|
if (g.offR) {
|
|
681
|
-
const [
|
|
706
|
+
const [latRad, lonRad] = ecefToGeodetic(x, y, z);
|
|
682
707
|
rho += rcvAntennaRangeM(
|
|
683
708
|
g.offR,
|
|
684
709
|
[-u[0], -u[1], -u[2]],
|
|
685
|
-
|
|
686
|
-
|
|
710
|
+
latRad,
|
|
711
|
+
lonRad,
|
|
687
712
|
elR,
|
|
688
713
|
g.roverDelta
|
|
689
714
|
);
|
|
@@ -2498,6 +2523,234 @@ function hasToOrbitClock(orbit, clock, refTimeMs, validitySeconds) {
|
|
|
2498
2523
|
};
|
|
2499
2524
|
}
|
|
2500
2525
|
|
|
2526
|
+
// src/positioning/ppp-ar.ts
|
|
2527
|
+
function wlWavelength(f1, f2) {
|
|
2528
|
+
return C_LIGHT / (f1 - f2);
|
|
2529
|
+
}
|
|
2530
|
+
function nlWavelength(f1, f2) {
|
|
2531
|
+
return C_LIGHT / (f1 + f2);
|
|
2532
|
+
}
|
|
2533
|
+
function resolvePppAmbiguities(sats, Qaif, opts = {}) {
|
|
2534
|
+
const wlThreshold = opts.wlThreshold ?? 0.25;
|
|
2535
|
+
const ratioThreshold = opts.ratioThreshold ?? 3;
|
|
2536
|
+
const minPartial = opts.minPartial ?? 4;
|
|
2537
|
+
const minSuccess = opts.minSuccessRate ?? 0;
|
|
2538
|
+
const n = sats.length;
|
|
2539
|
+
const none = (rejectedWl2, ratio = 0) => ({
|
|
2540
|
+
fixed: false,
|
|
2541
|
+
ratio,
|
|
2542
|
+
refPrn: null,
|
|
2543
|
+
refPrns: [],
|
|
2544
|
+
sats: [],
|
|
2545
|
+
rejectedWl: rejectedWl2
|
|
2546
|
+
});
|
|
2547
|
+
const elev = (i) => sats[i].elevDeg ?? -1;
|
|
2548
|
+
const wlOf = (i) => sats[i].mwCyc - (sats[i].wlBiasCyc ?? 0);
|
|
2549
|
+
const refOfSys = /* @__PURE__ */ new Map();
|
|
2550
|
+
for (let i = 0; i < n; i++) {
|
|
2551
|
+
const sys = sats[i].prn[0];
|
|
2552
|
+
const r = refOfSys.get(sys);
|
|
2553
|
+
if (r === void 0 || elev(i) > elev(r)) refOfSys.set(sys, i);
|
|
2554
|
+
}
|
|
2555
|
+
const nWlOf = /* @__PURE__ */ new Map();
|
|
2556
|
+
const refIdx = /* @__PURE__ */ new Map();
|
|
2557
|
+
const rejectedWl = [];
|
|
2558
|
+
for (const r of refOfSys.values()) {
|
|
2559
|
+
nWlOf.set(r, Math.round(wlOf(r)));
|
|
2560
|
+
refIdx.set(r, r);
|
|
2561
|
+
}
|
|
2562
|
+
for (let i = 0; i < n; i++) {
|
|
2563
|
+
if (refIdx.has(i)) continue;
|
|
2564
|
+
const r = refOfSys.get(sats[i].prn[0]);
|
|
2565
|
+
const sdWl = wlOf(i) - wlOf(r);
|
|
2566
|
+
const k = Math.round(sdWl);
|
|
2567
|
+
if (Math.abs(sdWl - k) <= wlThreshold) {
|
|
2568
|
+
nWlOf.set(i, nWlOf.get(r) + k);
|
|
2569
|
+
refIdx.set(i, r);
|
|
2570
|
+
} else rejectedWl.push(sats[i].prn);
|
|
2571
|
+
}
|
|
2572
|
+
const lamNl = (i) => nlWavelength(sats[i].f1, sats[i].f2);
|
|
2573
|
+
const n1Float = (i) => {
|
|
2574
|
+
const s = sats[i];
|
|
2575
|
+
return s.aIF / lamNl(i) - s.f2 / (s.f1 - s.f2) * nWlOf.get(i) - (s.nlBiasCyc ?? 0);
|
|
2576
|
+
};
|
|
2577
|
+
const qN1 = (a, b) => Qaif[a * n + b] / (lamNl(a) * lamNl(b));
|
|
2578
|
+
let cand = [...refIdx.keys()].filter((i) => refIdx.get(i) !== i).sort((a, b) => elev(b) - elev(a));
|
|
2579
|
+
if (cand.length < 1) return none(rejectedWl);
|
|
2580
|
+
let best = null;
|
|
2581
|
+
let firstRatio = 0;
|
|
2582
|
+
for (; ; ) {
|
|
2583
|
+
const m = cand.length;
|
|
2584
|
+
const sd = new Float64Array(m);
|
|
2585
|
+
const Qsd = new Float64Array(m * m);
|
|
2586
|
+
for (let a = 0; a < m; a++) {
|
|
2587
|
+
const ia = cand[a];
|
|
2588
|
+
const ra = refIdx.get(ia);
|
|
2589
|
+
sd[a] = n1Float(ia) - n1Float(ra);
|
|
2590
|
+
for (let b = 0; b < m; b++) {
|
|
2591
|
+
const ib = cand[b];
|
|
2592
|
+
const rb = refIdx.get(ib);
|
|
2593
|
+
Qsd[a * m + b] = qN1(ia, ib) - qN1(ia, rb) - qN1(ra, ib) + qN1(ra, rb);
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
const res = lambdaSearch(sd, Qsd, m, 2);
|
|
2597
|
+
const ratio = res ? Math.min(res.ratio, 999.9) : 0;
|
|
2598
|
+
if (best === null && firstRatio === 0) firstRatio = ratio;
|
|
2599
|
+
if (res && ratio >= ratioThreshold && res.successRate >= minSuccess) {
|
|
2600
|
+
best = { set: cand, ratio, fix: Float64Array.from(res.candidates[0]) };
|
|
2601
|
+
break;
|
|
2602
|
+
}
|
|
2603
|
+
if (m <= minPartial) break;
|
|
2604
|
+
cand = cand.slice(0, -1);
|
|
2605
|
+
}
|
|
2606
|
+
if (!best) return { ...none(rejectedWl, firstRatio), refPrn: null };
|
|
2607
|
+
const refN1 = /* @__PURE__ */ new Map();
|
|
2608
|
+
for (const r of refOfSys.values()) refN1.set(r, Math.round(n1Float(r)));
|
|
2609
|
+
const out = [];
|
|
2610
|
+
const emit = (i, n1) => {
|
|
2611
|
+
const s = sats[i];
|
|
2612
|
+
const l = lamNl(i);
|
|
2613
|
+
const nWl = nWlOf.get(i);
|
|
2614
|
+
out.push({
|
|
2615
|
+
prn: s.prn,
|
|
2616
|
+
nWl,
|
|
2617
|
+
n1,
|
|
2618
|
+
aIF: l * n1 + l * (s.f2 / (s.f1 - s.f2)) * nWl,
|
|
2619
|
+
ref: sats[refIdx.get(i)].prn
|
|
2620
|
+
});
|
|
2621
|
+
};
|
|
2622
|
+
const usedRefs = new Set(best.set.map((i) => refIdx.get(i)));
|
|
2623
|
+
for (const r of usedRefs) emit(r, refN1.get(r));
|
|
2624
|
+
best.set.forEach(
|
|
2625
|
+
(i, a) => emit(i, refN1.get(refIdx.get(i)) + Math.round(best.fix[a]))
|
|
2626
|
+
);
|
|
2627
|
+
const refPrns = [...usedRefs].map((r) => sats[r].prn);
|
|
2628
|
+
return {
|
|
2629
|
+
fixed: true,
|
|
2630
|
+
ratio: best.ratio,
|
|
2631
|
+
refPrn: refPrns[0] ?? null,
|
|
2632
|
+
refPrns,
|
|
2633
|
+
sats: out,
|
|
2634
|
+
rejectedWl
|
|
2635
|
+
};
|
|
2636
|
+
}
|
|
2637
|
+
function solveSpd(A, b) {
|
|
2638
|
+
const n = b.length;
|
|
2639
|
+
const L = Array.from({ length: n }, () => new Array(n).fill(0));
|
|
2640
|
+
for (let i = 0; i < n; i++) {
|
|
2641
|
+
for (let j = 0; j <= i; j++) {
|
|
2642
|
+
let s = A[i][j];
|
|
2643
|
+
for (let k = 0; k < j; k++) s -= L[i][k] * L[j][k];
|
|
2644
|
+
if (i === j) {
|
|
2645
|
+
if (s <= 0) return null;
|
|
2646
|
+
L[i][j] = Math.sqrt(s);
|
|
2647
|
+
} else {
|
|
2648
|
+
L[i][j] = s / L[j][j];
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
const y = new Array(n).fill(0);
|
|
2653
|
+
for (let i = 0; i < n; i++) {
|
|
2654
|
+
let s = b[i];
|
|
2655
|
+
for (let k = 0; k < i; k++) s -= L[i][k] * y[k];
|
|
2656
|
+
y[i] = s / L[i][i];
|
|
2657
|
+
}
|
|
2658
|
+
const x = new Array(n).fill(0);
|
|
2659
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
2660
|
+
let s = y[i];
|
|
2661
|
+
for (let k = i + 1; k < n; k++) s -= L[k][i] * x[k];
|
|
2662
|
+
x[i] = s / L[i][i];
|
|
2663
|
+
}
|
|
2664
|
+
return x;
|
|
2665
|
+
}
|
|
2666
|
+
function fixPppPosition(state, fcb, opts = {}) {
|
|
2667
|
+
const floatPos = state.position;
|
|
2668
|
+
const noFix = {
|
|
2669
|
+
fixed: false,
|
|
2670
|
+
position: floatPos,
|
|
2671
|
+
floatPosition: floatPos,
|
|
2672
|
+
shift: [0, 0, 0],
|
|
2673
|
+
nFixed: 0,
|
|
2674
|
+
ratio: 0,
|
|
2675
|
+
refPrn: null
|
|
2676
|
+
};
|
|
2677
|
+
const amb = state.ambiguities;
|
|
2678
|
+
if (amb.length < 3) return noFix;
|
|
2679
|
+
const sats = amb.map((a) => ({
|
|
2680
|
+
prn: a.prn,
|
|
2681
|
+
aIF: a.aIF,
|
|
2682
|
+
mwCyc: a.mwCyc,
|
|
2683
|
+
f1: a.f1,
|
|
2684
|
+
f2: a.f2,
|
|
2685
|
+
wlBiasCyc: fcb.satWlFcb.get(a.prn) ?? 0,
|
|
2686
|
+
nlBiasCyc: fcb.satNlFcb.get(a.prn) ?? 0,
|
|
2687
|
+
elevDeg: a.elevDeg
|
|
2688
|
+
}));
|
|
2689
|
+
const n = sats.length;
|
|
2690
|
+
const Qaif = new Float64Array(n * n);
|
|
2691
|
+
for (let i = 0; i < n; i++)
|
|
2692
|
+
for (let j = 0; j < n; j++)
|
|
2693
|
+
Qaif[i * n + j] = state.covariance[amb[i].index][amb[j].index];
|
|
2694
|
+
const res = resolvePppAmbiguities(sats, Qaif, {
|
|
2695
|
+
...opts,
|
|
2696
|
+
minPartial: opts.minPartial ?? Math.max(4, opts.minFixed ?? 0)
|
|
2697
|
+
});
|
|
2698
|
+
if (!res.fixed || res.refPrn === null) {
|
|
2699
|
+
return { ...noFix, ratio: res.ratio, refPrn: res.refPrn };
|
|
2700
|
+
}
|
|
2701
|
+
const idxOfPrn = new Map(amb.map((a) => [a.prn, a.index]));
|
|
2702
|
+
const floatOfPrn = new Map(amb.map((a) => [a.prn, a.aIF]));
|
|
2703
|
+
const fixedOf = new Map(res.sats.map((s) => [s.prn, s.aIF]));
|
|
2704
|
+
const pairs = res.sats.filter(
|
|
2705
|
+
(s) => s.ref !== s.prn && idxOfPrn.has(s.prn) && idxOfPrn.has(s.ref)
|
|
2706
|
+
).map((s) => ({ prn: s.prn, ref: s.ref }));
|
|
2707
|
+
const m = pairs.length;
|
|
2708
|
+
if (m < Math.max(1, opts.minFixed ?? 1))
|
|
2709
|
+
return { ...noFix, ratio: res.ratio, refPrn: res.refPrn };
|
|
2710
|
+
const P = state.covariance;
|
|
2711
|
+
const ix = (prn) => idxOfPrn.get(prn);
|
|
2712
|
+
const qAA = (i, j) => P[ix(i)][ix(j)];
|
|
2713
|
+
const qXA = (r, i) => P[r][ix(i)];
|
|
2714
|
+
const Qzz = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
2715
|
+
const z = new Array(m).fill(0);
|
|
2716
|
+
for (let a = 0; a < m; a++) {
|
|
2717
|
+
const { prn: ia, ref: ra } = pairs[a];
|
|
2718
|
+
z[a] = floatOfPrn.get(ia) - floatOfPrn.get(ra) - (fixedOf.get(ia) - fixedOf.get(ra));
|
|
2719
|
+
for (let b = 0; b < m; b++) {
|
|
2720
|
+
const { prn: ib, ref: rb } = pairs[b];
|
|
2721
|
+
Qzz[a][b] = qAA(ia, ib) - qAA(ia, rb) - qAA(ra, ib) + qAA(ra, rb);
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
const Qxz = [0, 1, 2].map(
|
|
2725
|
+
(r) => pairs.map(({ prn, ref }) => qXA(r, prn) - qXA(r, ref))
|
|
2726
|
+
);
|
|
2727
|
+
const y = solveSpd(Qzz, z);
|
|
2728
|
+
if (!y) return { ...noFix, ratio: res.ratio, refPrn: res.refPrn };
|
|
2729
|
+
let chi2 = 0;
|
|
2730
|
+
for (let a = 0; a < m; a++) chi2 += z[a] * y[a];
|
|
2731
|
+
if (chi2 / m > (opts.maxChi2 ?? Infinity))
|
|
2732
|
+
return { ...noFix, ratio: res.ratio, refPrn: res.refPrn };
|
|
2733
|
+
const shift = [0, 0, 0];
|
|
2734
|
+
for (let r = 0; r < 3; r++) {
|
|
2735
|
+
let s = 0;
|
|
2736
|
+
for (let a = 0; a < m; a++) s += Qxz[r][a] * y[a];
|
|
2737
|
+
shift[r] = -s;
|
|
2738
|
+
}
|
|
2739
|
+
return {
|
|
2740
|
+
fixed: true,
|
|
2741
|
+
position: [
|
|
2742
|
+
floatPos[0] + shift[0],
|
|
2743
|
+
floatPos[1] + shift[1],
|
|
2744
|
+
floatPos[2] + shift[2]
|
|
2745
|
+
],
|
|
2746
|
+
floatPosition: floatPos,
|
|
2747
|
+
shift,
|
|
2748
|
+
nFixed: m,
|
|
2749
|
+
ratio: res.ratio,
|
|
2750
|
+
refPrn: res.refPrn
|
|
2751
|
+
};
|
|
2752
|
+
}
|
|
2753
|
+
|
|
2501
2754
|
// src/positioning/ppp-tropo.ts
|
|
2502
2755
|
var HYD_AVG_A = [
|
|
2503
2756
|
0.0012769934,
|
|
@@ -2705,13 +2958,11 @@ function createPppCorrections(cfg) {
|
|
|
2705
2958
|
let rangeM = 0;
|
|
2706
2959
|
let phaseWindupM = 0;
|
|
2707
2960
|
const e = geom.los;
|
|
2708
|
-
const [
|
|
2961
|
+
const [latRad, lonRad] = ecefToGeodetic(
|
|
2709
2962
|
geom.rcvEcef[0],
|
|
2710
2963
|
geom.rcvEcef[1],
|
|
2711
2964
|
geom.rcvEcef[2]
|
|
2712
2965
|
);
|
|
2713
|
-
const latRad = latDeg * Math.PI / 180;
|
|
2714
|
-
const lonRad = lonDeg * Math.PI / 180;
|
|
2715
2966
|
const frame = ctx ? satBodyFrame(geom.satEcef, ctx.sun) : null;
|
|
2716
2967
|
if (useSat && frame && geom.band1 && geom.band2) {
|
|
2717
2968
|
const off = cfg.antenna.satOffset(
|
|
@@ -2769,6 +3020,10 @@ function createPppCorrections(cfg) {
|
|
|
2769
3020
|
}
|
|
2770
3021
|
|
|
2771
3022
|
// src/positioning/ppp.ts
|
|
3023
|
+
var NO_FCB = {
|
|
3024
|
+
satWlFcb: /* @__PURE__ */ new Map(),
|
|
3025
|
+
satNlFcb: /* @__PURE__ */ new Map()
|
|
3026
|
+
};
|
|
2772
3027
|
function matVec(P, h) {
|
|
2773
3028
|
const n = P.length;
|
|
2774
3029
|
const out = new Array(n).fill(0);
|
|
@@ -2780,6 +3035,34 @@ function matVec(P, h) {
|
|
|
2780
3035
|
}
|
|
2781
3036
|
return out;
|
|
2782
3037
|
}
|
|
3038
|
+
function tdLsq(qs) {
|
|
3039
|
+
const M = [0, 1, 2, 3].map(() => [0, 0, 0, 0, 0]);
|
|
3040
|
+
for (const q of qs) {
|
|
3041
|
+
const a = [-q.v.e[0], -q.v.e[1], -q.v.e[2], 1];
|
|
3042
|
+
for (let i = 0; i < 4; i++) {
|
|
3043
|
+
M[i][4] += a[i] * q.d;
|
|
3044
|
+
for (let j = 0; j < 4; j++) M[i][j] += a[i] * a[j];
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
for (let c = 0; c < 4; c++) {
|
|
3048
|
+
let p = c;
|
|
3049
|
+
for (let r = c + 1; r < 4; r++)
|
|
3050
|
+
if (Math.abs(M[r][c]) > Math.abs(M[p][c])) p = r;
|
|
3051
|
+
if (Math.abs(M[p][c]) < 1e-9) return null;
|
|
3052
|
+
[M[c], M[p]] = [M[p], M[c]];
|
|
3053
|
+
for (let r = 0; r < 4; r++) {
|
|
3054
|
+
if (r === c) continue;
|
|
3055
|
+
const f = M[r][c] / M[c][c];
|
|
3056
|
+
for (let k = c; k < 5; k++) M[r][k] -= f * M[c][k];
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
return [0, 1, 2, 3].map((i) => M[i][4] / M[i][i]);
|
|
3060
|
+
}
|
|
3061
|
+
function tdResidual(q, s) {
|
|
3062
|
+
return q.d - (-q.v.e[0] * s[0] - q.v.e[1] * s[1] - q.v.e[2] * s[2] + s[3]);
|
|
3063
|
+
}
|
|
3064
|
+
var TD_SLIP_M = 0.08;
|
|
3065
|
+
var CODE_GATE_M = 15;
|
|
2783
3066
|
function ekfUpdateScalar(x, P, h, innovation, r, rejectK = 0) {
|
|
2784
3067
|
const n = x.length;
|
|
2785
3068
|
const Ph = matVec(P, h);
|
|
@@ -2812,10 +3095,17 @@ function ifCoeffs(f1, f2) {
|
|
|
2812
3095
|
return { g, lambdaIf };
|
|
2813
3096
|
}
|
|
2814
3097
|
var Sp3EphemerisSource = class {
|
|
2815
|
-
constructor(sp3, clk) {
|
|
3098
|
+
constructor(sp3, clk, osb) {
|
|
2816
3099
|
this.sp3 = sp3;
|
|
2817
3100
|
this.clk = clk;
|
|
3101
|
+
this.osb = osb;
|
|
3102
|
+
if (osb) {
|
|
3103
|
+
this.codeBias = (prn, code, t) => osb.get(prn, "C" + code, t);
|
|
3104
|
+
this.phaseBias = (prn, code, t) => osb.get(prn, "L" + code, t);
|
|
3105
|
+
}
|
|
2818
3106
|
}
|
|
3107
|
+
codeBias;
|
|
3108
|
+
phaseBias;
|
|
2819
3109
|
satState(prn, tEmitMs) {
|
|
2820
3110
|
const p = sp3Position(this.sp3, prn, tEmitMs);
|
|
2821
3111
|
if (!p || p.clk == null) return null;
|
|
@@ -2833,6 +3123,21 @@ var Sp3EphemerisSource = class {
|
|
|
2833
3123
|
return { x: p.x, y: p.y, z: p.z, vx, vy, vz, clkS };
|
|
2834
3124
|
}
|
|
2835
3125
|
};
|
|
3126
|
+
function applySatBiases(source, o, tMs) {
|
|
3127
|
+
if (!source.codeBias && !source.phaseBias) return o;
|
|
3128
|
+
const b1 = source.codeBias?.(o.prn, o.code1 ?? "", tMs) ?? 0;
|
|
3129
|
+
const b2 = source.codeBias?.(o.prn, o.code2 ?? "", tMs) ?? 0;
|
|
3130
|
+
let l1 = o.l1;
|
|
3131
|
+
let l2 = o.l2;
|
|
3132
|
+
if (source.phaseBias) {
|
|
3133
|
+
const p1 = source.phaseBias(o.prn, o.phase1 ?? o.code1 ?? "", tMs);
|
|
3134
|
+
const p2 = source.phaseBias(o.prn, o.phase2 ?? o.code2 ?? "", tMs);
|
|
3135
|
+
if (p1 == null || p2 == null) return null;
|
|
3136
|
+
l1 -= p1 / (C_LIGHT / o.f1);
|
|
3137
|
+
l2 -= p2 / (C_LIGHT / o.f2);
|
|
3138
|
+
}
|
|
3139
|
+
return { ...o, c1: o.c1 - b1, c2: o.c2 - b2, l1, l2 };
|
|
3140
|
+
}
|
|
2836
3141
|
function sagnacRotate(x, y, z, travelS) {
|
|
2837
3142
|
const theta = OMEGA_E * travelS;
|
|
2838
3143
|
const c = Math.cos(theta);
|
|
@@ -2894,6 +3199,16 @@ var PppEngine = class {
|
|
|
2894
3199
|
arcs;
|
|
2895
3200
|
arcSnap;
|
|
2896
3201
|
mwState;
|
|
3202
|
+
/** Previous epoch's phase terms per satellite, for the time-differenced
|
|
3203
|
+
* (clock-free) cycle-slip test. */
|
|
3204
|
+
tdPrev;
|
|
3205
|
+
/** Consecutive gated-out phase updates per satellite. */
|
|
3206
|
+
phaseRejects;
|
|
3207
|
+
/** PPP-AR: the latest accepted fix (null: float). */
|
|
3208
|
+
lastFix;
|
|
3209
|
+
lastArMs;
|
|
3210
|
+
firstFixMs;
|
|
3211
|
+
fixedEpochs;
|
|
2897
3212
|
series;
|
|
2898
3213
|
ei = 0;
|
|
2899
3214
|
t0 = 0;
|
|
@@ -2929,6 +3244,12 @@ var PppEngine = class {
|
|
|
2929
3244
|
this.arcs = [];
|
|
2930
3245
|
this.arcSnap = /* @__PURE__ */ new Map();
|
|
2931
3246
|
this.mwState = /* @__PURE__ */ new Map();
|
|
3247
|
+
this.tdPrev = /* @__PURE__ */ new Map();
|
|
3248
|
+
this.phaseRejects = /* @__PURE__ */ new Map();
|
|
3249
|
+
this.lastFix = null;
|
|
3250
|
+
this.lastArMs = -Infinity;
|
|
3251
|
+
this.firstFixMs = null;
|
|
3252
|
+
this.fixedEpochs = 0;
|
|
2932
3253
|
this.series = [];
|
|
2933
3254
|
this.ei = 0;
|
|
2934
3255
|
this.t0 = 0;
|
|
@@ -3022,7 +3343,9 @@ var PppEngine = class {
|
|
|
3022
3343
|
lastSeen,
|
|
3023
3344
|
arcSnap,
|
|
3024
3345
|
mwState,
|
|
3025
|
-
series
|
|
3346
|
+
series,
|
|
3347
|
+
tdPrev,
|
|
3348
|
+
phaseRejects
|
|
3026
3349
|
} = this;
|
|
3027
3350
|
const flushArc = this.flushArc.bind(this);
|
|
3028
3351
|
const detectSlip = this.detectSlip.bind(this);
|
|
@@ -3044,13 +3367,15 @@ var PppEngine = class {
|
|
|
3044
3367
|
for (const ci of clkIdx.values()) P[ci][ci] = CLK_VAR;
|
|
3045
3368
|
P[IDX_ZWD][IDX_ZWD] += ztdQ * (ei > 0 ? 1 : 0);
|
|
3046
3369
|
const rcv = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
3047
|
-
const [
|
|
3048
|
-
const latRad = latDeg * Math.PI / 180;
|
|
3370
|
+
const [latRad, , heightM] = ecefToGeodetic(rcv[0], rcv[1], rcv[2]);
|
|
3049
3371
|
const epochCtx = corrections?.epochContext?.(epoch.timeMs, rcv) ?? null;
|
|
3050
3372
|
const vis = [];
|
|
3051
3373
|
let epochZhd = 0;
|
|
3052
|
-
for (const
|
|
3053
|
-
if (
|
|
3374
|
+
for (const raw of epoch.obs) {
|
|
3375
|
+
if (raw.c1 === 0 || raw.c2 === 0 || raw.l1 === 0 || raw.l2 === 0)
|
|
3376
|
+
continue;
|
|
3377
|
+
const o = applySatBiases(source, raw, epoch.timeMs);
|
|
3378
|
+
if (!o) continue;
|
|
3054
3379
|
const slip = detectSlip(o, ei);
|
|
3055
3380
|
const sat = satStateAtEmission(source, o.prn, epoch.timeMs, rcv);
|
|
3056
3381
|
if (!sat) continue;
|
|
@@ -3072,9 +3397,7 @@ var PppEngine = class {
|
|
|
3072
3397
|
const lam1 = C_LIGHT / o.f1;
|
|
3073
3398
|
const lam2 = C_LIGHT / o.f2;
|
|
3074
3399
|
if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
|
|
3075
|
-
const
|
|
3076
|
-
const b2 = source.codeBias?.(o.prn, o.code2 ?? "", epoch.timeMs) ?? 0;
|
|
3077
|
-
const pIf = g * (o.c1 - b1) - (g - 1) * (o.c2 - b2);
|
|
3400
|
+
const pIf = g * o.c1 - (g - 1) * o.c2;
|
|
3078
3401
|
const lIf = g * (o.l1 * lam1) - (g - 1) * (o.l2 * lam2);
|
|
3079
3402
|
if (!Number.isFinite(pIf) || !Number.isFinite(lIf)) continue;
|
|
3080
3403
|
const trop = opts.troposphere ?? true ? niellMapping(elRad, latRad, heightM, epoch.timeMs) : { zhd: 0, mh: 0, mw: 0 };
|
|
@@ -3107,9 +3430,63 @@ var PppEngine = class {
|
|
|
3107
3430
|
windupM: corr.phaseWindupM,
|
|
3108
3431
|
slip,
|
|
3109
3432
|
f1: o.f1,
|
|
3110
|
-
f2: o.f2
|
|
3433
|
+
f2: o.f2,
|
|
3434
|
+
sat: [sat.state.x, sat.state.y, sat.state.z]
|
|
3111
3435
|
});
|
|
3112
3436
|
}
|
|
3437
|
+
{
|
|
3438
|
+
const dq = [];
|
|
3439
|
+
for (const v of vis) {
|
|
3440
|
+
const prev = tdPrev.get(v.prn);
|
|
3441
|
+
const model = -v.satClkM + v.tropoFixed + v.windupM;
|
|
3442
|
+
if (prev && prev.ei === ei - 1 && !v.slip) {
|
|
3443
|
+
const r0 = Math.hypot(
|
|
3444
|
+
prev.sat[0] - rcv[0],
|
|
3445
|
+
prev.sat[1] - rcv[1],
|
|
3446
|
+
prev.sat[2] - rcv[2]
|
|
3447
|
+
);
|
|
3448
|
+
dq.push({
|
|
3449
|
+
v,
|
|
3450
|
+
d: v.lIf - prev.lIf - (v.range - r0) - (model - prev.model)
|
|
3451
|
+
});
|
|
3452
|
+
}
|
|
3453
|
+
tdPrev.set(v.prn, { ei, lIf: v.lIf, sat: v.sat, model });
|
|
3454
|
+
}
|
|
3455
|
+
if (!kinematic) {
|
|
3456
|
+
if (dq.length >= 4) {
|
|
3457
|
+
const sorted = dq.map((q) => q.d).sort((a, b) => a - b);
|
|
3458
|
+
const med = sorted[Math.floor(sorted.length / 2)];
|
|
3459
|
+
for (const q of dq)
|
|
3460
|
+
if (Math.abs(q.d - med) > TD_SLIP_M) q.v.slip = true;
|
|
3461
|
+
}
|
|
3462
|
+
} else if (dq.length >= 6) {
|
|
3463
|
+
let use = dq;
|
|
3464
|
+
for (let iter = 0; iter < 6; iter++) {
|
|
3465
|
+
const sol = use.length >= 6 ? tdLsq(use) : null;
|
|
3466
|
+
if (!sol) {
|
|
3467
|
+
for (const q of dq) q.v.slip = true;
|
|
3468
|
+
break;
|
|
3469
|
+
}
|
|
3470
|
+
let worst = -1;
|
|
3471
|
+
let worstR = 0;
|
|
3472
|
+
use.forEach((q, k) => {
|
|
3473
|
+
const r = Math.abs(tdResidual(q, sol));
|
|
3474
|
+
if (r > worstR) {
|
|
3475
|
+
worstR = r;
|
|
3476
|
+
worst = k;
|
|
3477
|
+
}
|
|
3478
|
+
});
|
|
3479
|
+
if (worstR <= TD_SLIP_M || iter === 5) {
|
|
3480
|
+
for (const q of dq)
|
|
3481
|
+
if (Math.abs(tdResidual(q, sol)) > TD_SLIP_M) q.v.slip = true;
|
|
3482
|
+
break;
|
|
3483
|
+
}
|
|
3484
|
+
use = use.filter((_, k) => k !== worst);
|
|
3485
|
+
}
|
|
3486
|
+
} else {
|
|
3487
|
+
for (const q of dq) q.v.slip = true;
|
|
3488
|
+
}
|
|
3489
|
+
}
|
|
3113
3490
|
const zwd0 = x[IDX_ZWD];
|
|
3114
3491
|
const bySys = /* @__PURE__ */ new Map();
|
|
3115
3492
|
for (const v of vis) {
|
|
@@ -3119,6 +3496,20 @@ var PppEngine = class {
|
|
|
3119
3496
|
if (arr) arr.push(r);
|
|
3120
3497
|
else bySys.set(sys, [r]);
|
|
3121
3498
|
}
|
|
3499
|
+
const posSigma = Math.sqrt(
|
|
3500
|
+
P[IDX_X][IDX_X] + P[IDX_Y][IDX_Y] + P[IDX_Z][IDX_Z]
|
|
3501
|
+
);
|
|
3502
|
+
const codeGate = CODE_GATE_M + 3 * posSigma;
|
|
3503
|
+
const screened = /* @__PURE__ */ new Set();
|
|
3504
|
+
for (const [sys, res] of bySys) {
|
|
3505
|
+
if (res.length < 4) continue;
|
|
3506
|
+
const med = [...res].sort((a, b) => a - b)[Math.floor(res.length / 2)];
|
|
3507
|
+
for (const v of vis) {
|
|
3508
|
+
if (v.prn[0] !== sys) continue;
|
|
3509
|
+
const r = v.pIf - (v.range - v.satClkM + v.tropoFixed + zwd0 * v.mw);
|
|
3510
|
+
if (Math.abs(r - med) > codeGate) screened.add(v.prn);
|
|
3511
|
+
}
|
|
3512
|
+
}
|
|
3122
3513
|
for (const [sys, res] of bySys) {
|
|
3123
3514
|
const ci = clockOf(sys);
|
|
3124
3515
|
if (!clockSeeded.has(sys)) {
|
|
@@ -3129,9 +3520,11 @@ var PppEngine = class {
|
|
|
3129
3520
|
P[ci][ci] = CLK_VAR;
|
|
3130
3521
|
}
|
|
3131
3522
|
let nSats = 0;
|
|
3132
|
-
|
|
3523
|
+
const live = vis.filter((v) => !screened.has(v.prn));
|
|
3524
|
+
const rangeNow = (v) => v.range - (v.e[0] * (x[IDX_X] - rcv[0]) + v.e[1] * (x[IDX_Y] - rcv[1]) + v.e[2] * (x[IDX_Z] - rcv[2]));
|
|
3525
|
+
const prepAmbiguity = (v) => {
|
|
3133
3526
|
const ci = clockOf(v.prn[0]);
|
|
3134
|
-
const common = v
|
|
3527
|
+
const common = rangeNow(v) + x[ci] - v.satClkM + v.tropoFixed + zwd0 * v.mw;
|
|
3135
3528
|
if (v.slip) flushArc(v.prn);
|
|
3136
3529
|
let ai = ambIdx.get(v.prn);
|
|
3137
3530
|
if (ai === void 0 || v.slip) {
|
|
@@ -3148,67 +3541,91 @@ var PppEngine = class {
|
|
|
3148
3541
|
}
|
|
3149
3542
|
ambIdx.set(v.prn, ai);
|
|
3150
3543
|
}
|
|
3151
|
-
|
|
3544
|
+
return ai;
|
|
3545
|
+
};
|
|
3546
|
+
const codeUpdate = (v) => {
|
|
3547
|
+
const ci = clockOf(v.prn[0]);
|
|
3548
|
+
const common = rangeNow(v) + x[ci] - v.satClkM + v.tropoFixed + x[IDX_ZWD] * v.mw;
|
|
3549
|
+
const sinEl = Math.max(Math.sin(v.elRad), 0.1);
|
|
3550
|
+
const h = new Array(x.length).fill(0);
|
|
3551
|
+
h[IDX_X] = -v.e[0];
|
|
3552
|
+
h[IDX_Y] = -v.e[1];
|
|
3553
|
+
h[IDX_Z] = -v.e[2];
|
|
3554
|
+
h[ci] = 1;
|
|
3555
|
+
h[IDX_ZWD] = v.mw;
|
|
3556
|
+
const innov = v.pIf - common;
|
|
3557
|
+
if (Math.abs(innov) < 1e6)
|
|
3558
|
+
ekfUpdateScalar(x, P, h, innov, (codeSigma / sinEl) ** 2, 4);
|
|
3559
|
+
};
|
|
3560
|
+
const phaseUpdate = (v, ai) => {
|
|
3561
|
+
const ci = clockOf(v.prn[0]);
|
|
3152
3562
|
const sinEl = Math.max(Math.sin(v.elRad), 0.1);
|
|
3153
|
-
const rCode = (codeSigma / sinEl) ** 2;
|
|
3154
3563
|
const rPhase = (phaseSigma / sinEl) ** 2;
|
|
3155
|
-
|
|
3156
|
-
|
|
3564
|
+
const commonPh = rangeNow(v) + x[ci] - v.satClkM + v.tropoFixed + x[IDX_ZWD] * v.mw;
|
|
3565
|
+
const innov = v.lIf - (commonPh + v.windupM + x[ai]);
|
|
3566
|
+
const reinit = (phaseRejects.get(v.prn) ?? 0) >= 3;
|
|
3567
|
+
let used = false;
|
|
3568
|
+
if (!reinit) {
|
|
3569
|
+
const h = new Array(x.length).fill(0);
|
|
3157
3570
|
h[IDX_X] = -v.e[0];
|
|
3158
3571
|
h[IDX_Y] = -v.e[1];
|
|
3159
3572
|
h[IDX_Z] = -v.e[2];
|
|
3160
3573
|
h[ci] = 1;
|
|
3161
3574
|
h[IDX_ZWD] = v.mw;
|
|
3162
|
-
|
|
3163
|
-
|
|
3575
|
+
h[ai] = 1;
|
|
3576
|
+
used = ekfUpdateScalar(x, P, h, innov, rPhase, 4);
|
|
3164
3577
|
}
|
|
3165
|
-
{
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
for (let j = 0; j < P.length; j++) {
|
|
3172
|
-
P[ai][j] = 0;
|
|
3173
|
-
P[j][ai] = 0;
|
|
3174
|
-
}
|
|
3175
|
-
P[ai][ai] = 100 * 100;
|
|
3176
|
-
} else {
|
|
3177
|
-
const h = new Array(n).fill(0);
|
|
3178
|
-
h[IDX_X] = -v.e[0];
|
|
3179
|
-
h[IDX_Y] = -v.e[1];
|
|
3180
|
-
h[IDX_Z] = -v.e[2];
|
|
3181
|
-
h[ci] = 1;
|
|
3182
|
-
h[IDX_ZWD] = v.mw;
|
|
3183
|
-
h[ai] = 1;
|
|
3184
|
-
ekfUpdateScalar(x, P, h, innov, rPhase, 4);
|
|
3185
|
-
}
|
|
3186
|
-
}
|
|
3187
|
-
{
|
|
3188
|
-
const elevDeg = v.elRad * 180 / Math.PI;
|
|
3189
|
-
const mwMean = mwState.get(v.prn)?.mean ?? 0;
|
|
3190
|
-
const s = arcSnap.get(v.prn);
|
|
3191
|
-
if (s) {
|
|
3192
|
-
s.aIF = x[ai];
|
|
3193
|
-
s.mwCyc = mwMean;
|
|
3194
|
-
s.elevSum += elevDeg;
|
|
3195
|
-
s.nEpochs++;
|
|
3196
|
-
s.endMs = epoch.timeMs;
|
|
3197
|
-
} else {
|
|
3198
|
-
arcSnap.set(v.prn, {
|
|
3199
|
-
aIF: x[ai],
|
|
3200
|
-
mwCyc: mwMean,
|
|
3201
|
-
f1: v.f1,
|
|
3202
|
-
f2: v.f2,
|
|
3203
|
-
elevSum: elevDeg,
|
|
3204
|
-
nEpochs: 1,
|
|
3205
|
-
startMs: epoch.timeMs,
|
|
3206
|
-
endMs: epoch.timeMs
|
|
3207
|
-
});
|
|
3578
|
+
if (reinit) {
|
|
3579
|
+
flushArc(v.prn);
|
|
3580
|
+
x[ai] = v.lIf - (commonPh + v.windupM);
|
|
3581
|
+
for (let j = 0; j < P.length; j++) {
|
|
3582
|
+
P[ai][j] = 0;
|
|
3583
|
+
P[j][ai] = 0;
|
|
3208
3584
|
}
|
|
3585
|
+
P[ai][ai] = 100 * 100;
|
|
3586
|
+
phaseRejects.delete(v.prn);
|
|
3587
|
+
} else if (used) phaseRejects.delete(v.prn);
|
|
3588
|
+
else phaseRejects.set(v.prn, (phaseRejects.get(v.prn) ?? 0) + 1);
|
|
3589
|
+
};
|
|
3590
|
+
const snapshot = (v, ai) => {
|
|
3591
|
+
const elevDeg = v.elRad * 180 / Math.PI;
|
|
3592
|
+
const mwMean = mwState.get(v.prn)?.mean ?? 0;
|
|
3593
|
+
const s = arcSnap.get(v.prn);
|
|
3594
|
+
if (s) {
|
|
3595
|
+
s.aIF = x[ai];
|
|
3596
|
+
s.mwCyc = mwMean;
|
|
3597
|
+
s.elevSum += elevDeg;
|
|
3598
|
+
s.nEpochs++;
|
|
3599
|
+
s.endMs = epoch.timeMs;
|
|
3600
|
+
} else {
|
|
3601
|
+
arcSnap.set(v.prn, {
|
|
3602
|
+
aIF: x[ai],
|
|
3603
|
+
mwCyc: mwMean,
|
|
3604
|
+
f1: v.f1,
|
|
3605
|
+
f2: v.f2,
|
|
3606
|
+
elevSum: elevDeg,
|
|
3607
|
+
nEpochs: 1,
|
|
3608
|
+
startMs: epoch.timeMs,
|
|
3609
|
+
endMs: epoch.timeMs
|
|
3610
|
+
});
|
|
3209
3611
|
}
|
|
3210
3612
|
lastSeen.set(v.prn, ei);
|
|
3211
3613
|
nSats++;
|
|
3614
|
+
};
|
|
3615
|
+
if (kinematic) {
|
|
3616
|
+
for (const v of live) codeUpdate(v);
|
|
3617
|
+
for (const v of live) {
|
|
3618
|
+
const ai = prepAmbiguity(v);
|
|
3619
|
+
phaseUpdate(v, ai);
|
|
3620
|
+
snapshot(v, ai);
|
|
3621
|
+
}
|
|
3622
|
+
} else {
|
|
3623
|
+
for (const v of live) {
|
|
3624
|
+
const ai = prepAmbiguity(v);
|
|
3625
|
+
codeUpdate(v);
|
|
3626
|
+
phaseUpdate(v, ai);
|
|
3627
|
+
snapshot(v, ai);
|
|
3628
|
+
}
|
|
3212
3629
|
}
|
|
3213
3630
|
let sumPhaseResSq = 0;
|
|
3214
3631
|
let nPhaseRes = 0;
|
|
@@ -3219,7 +3636,7 @@ var PppEngine = class {
|
|
|
3219
3636
|
if (ai === void 0) continue;
|
|
3220
3637
|
const sys = v.prn[0];
|
|
3221
3638
|
const ci = clockOf(sys);
|
|
3222
|
-
const commonPh = v
|
|
3639
|
+
const commonPh = rangeNow(v) + x[ci] - v.satClkM + v.tropoFixed + x[IDX_ZWD] * v.mw;
|
|
3223
3640
|
const innov = v.lIf - (commonPh + v.windupM + x[ai]);
|
|
3224
3641
|
if (Math.abs(innov) >= 0.15) continue;
|
|
3225
3642
|
const arr = bySysRes.get(sys);
|
|
@@ -3243,6 +3660,8 @@ var PppEngine = class {
|
|
|
3243
3660
|
flushArc(prn);
|
|
3244
3661
|
}
|
|
3245
3662
|
}
|
|
3663
|
+
this.tryFix(epoch.timeMs, vis);
|
|
3664
|
+
if (this.lastFix) this.fixedEpochs++;
|
|
3246
3665
|
const pos = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
3247
3666
|
let enu = null;
|
|
3248
3667
|
let error3d = null;
|
|
@@ -3278,12 +3697,75 @@ var PppEngine = class {
|
|
|
3278
3697
|
nSats,
|
|
3279
3698
|
ztdWet: x[IDX_ZWD],
|
|
3280
3699
|
ztdHydrostatic: epochZhd,
|
|
3281
|
-
phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0
|
|
3700
|
+
phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0,
|
|
3701
|
+
nFixed: this.lastFix?.nFixed ?? 0,
|
|
3702
|
+
fixedPosition: this.lastFix?.position ?? null
|
|
3282
3703
|
};
|
|
3283
3704
|
series.push(result);
|
|
3284
3705
|
this.ei = ei + 1;
|
|
3285
3706
|
return result;
|
|
3286
3707
|
}
|
|
3708
|
+
/**
|
|
3709
|
+
* PPP-AR. Every `everyS`, resolve the converged ambiguities of the
|
|
3710
|
+
* satellites in view (between satellites of one constellation) and, when
|
|
3711
|
+
* the fix passes the ratio, success-rate and χ² tests, condition the
|
|
3712
|
+
* float position on it ({@link fixPppPosition}). The float filter itself
|
|
3713
|
+
* is never constrained — a wrong fix can't contaminate later epochs, and
|
|
3714
|
+
* the next attempt starts clean. Between attempts the last fix carries
|
|
3715
|
+
* over (static) or is dropped (kinematic).
|
|
3716
|
+
*/
|
|
3717
|
+
tryFix(tMs, vis) {
|
|
3718
|
+
const ar = this.opts.ar;
|
|
3719
|
+
if (!ar || !this.source.phaseBias) return;
|
|
3720
|
+
const cfg = ar === true ? {} : ar;
|
|
3721
|
+
if (tMs - this.lastArMs < (cfg.everyS ?? 120) * 1e3) {
|
|
3722
|
+
if (this.kinematic) this.lastFix = null;
|
|
3723
|
+
return;
|
|
3724
|
+
}
|
|
3725
|
+
this.lastArMs = tMs;
|
|
3726
|
+
this.lastFix = null;
|
|
3727
|
+
const { x, P, ambIdx, arcSnap, mwState } = this;
|
|
3728
|
+
const minArcMs = (cfg.minArcS ?? 600) * 1e3;
|
|
3729
|
+
const ambiguities = [];
|
|
3730
|
+
for (const v of vis) {
|
|
3731
|
+
const index = ambIdx.get(v.prn);
|
|
3732
|
+
const snap = arcSnap.get(v.prn);
|
|
3733
|
+
const mw = mwState.get(v.prn);
|
|
3734
|
+
if (index === void 0 || !snap || !mw) continue;
|
|
3735
|
+
if (tMs - snap.startMs < minArcMs || snap.nEpochs < 20) continue;
|
|
3736
|
+
ambiguities.push({
|
|
3737
|
+
prn: v.prn,
|
|
3738
|
+
index,
|
|
3739
|
+
aIF: x[index],
|
|
3740
|
+
mwCyc: mw.mean,
|
|
3741
|
+
f1: v.f1,
|
|
3742
|
+
f2: v.f2,
|
|
3743
|
+
elevDeg: v.elRad * 180 / Math.PI
|
|
3744
|
+
});
|
|
3745
|
+
}
|
|
3746
|
+
const fx = fixPppPosition(
|
|
3747
|
+
{
|
|
3748
|
+
position: [x[IDX_X], x[IDX_Y], x[IDX_Z]],
|
|
3749
|
+
covariance: P,
|
|
3750
|
+
ambiguities
|
|
3751
|
+
},
|
|
3752
|
+
NO_FCB,
|
|
3753
|
+
{
|
|
3754
|
+
ratioThreshold: cfg.ratio ?? 3,
|
|
3755
|
+
wlThreshold: cfg.wlThreshold ?? 0.15,
|
|
3756
|
+
minSuccessRate: cfg.successRate ?? 0.999,
|
|
3757
|
+
minFixed: cfg.minFixed ?? 5,
|
|
3758
|
+
maxChi2: cfg.maxChi2 ?? 20
|
|
3759
|
+
}
|
|
3760
|
+
);
|
|
3761
|
+
if (!fx.fixed) return;
|
|
3762
|
+
this.lastFix = {
|
|
3763
|
+
position: fx.position,
|
|
3764
|
+
nFixed: fx.nFixed,
|
|
3765
|
+
ratio: fx.ratio
|
|
3766
|
+
};
|
|
3767
|
+
this.firstFixMs ??= tMs;
|
|
3768
|
+
}
|
|
3287
3769
|
/** Finalise the session: capture the AR state, flush open arcs, assemble. */
|
|
3288
3770
|
solution() {
|
|
3289
3771
|
const { opts, x, P, ambIdx, arcSnap, mwState, arcs, series, truth } = this;
|
|
@@ -3316,7 +3798,12 @@ var PppEngine = class {
|
|
|
3316
3798
|
x[IDX_Y],
|
|
3317
3799
|
x[IDX_Z]
|
|
3318
3800
|
];
|
|
3319
|
-
const
|
|
3801
|
+
const geo = ecefToGeodetic(finalPos[0], finalPos[1], finalPos[2]);
|
|
3802
|
+
const llh = [
|
|
3803
|
+
geo[0] * 180 / Math.PI,
|
|
3804
|
+
geo[1] * 180 / Math.PI,
|
|
3805
|
+
geo[2]
|
|
3806
|
+
];
|
|
3320
3807
|
const finalError3d = truth ? Math.hypot(
|
|
3321
3808
|
finalPos[0] - truth[0],
|
|
3322
3809
|
finalPos[1] - truth[1],
|
|
@@ -3332,218 +3819,25 @@ var PppEngine = class {
|
|
|
3332
3819
|
convergenceSec: this.convergenceSec,
|
|
3333
3820
|
finalError3d,
|
|
3334
3821
|
arcs,
|
|
3335
|
-
finalState
|
|
3822
|
+
finalState,
|
|
3823
|
+
...opts.ar && this.source.phaseBias ? {
|
|
3824
|
+
ar: {
|
|
3825
|
+
firstFixSec: this.firstFixMs === null || !series.length ? null : (this.firstFixMs - series[0].timeMs) / 1e3,
|
|
3826
|
+
nFixedEnd: this.lastFix?.nFixed ?? 0,
|
|
3827
|
+
position: this.lastFix?.position ?? null,
|
|
3828
|
+
fixedEpochShare: series.length ? this.fixedEpochs / series.length : 0
|
|
3829
|
+
}
|
|
3830
|
+
} : {}
|
|
3336
3831
|
};
|
|
3337
3832
|
}
|
|
3338
3833
|
};
|
|
3339
3834
|
function solvePpp(epochs, sp3OrSource, opts) {
|
|
3340
|
-
const source = "satState" in sp3OrSource ? sp3OrSource : new Sp3EphemerisSource(sp3OrSource, opts.clk);
|
|
3835
|
+
const source = "satState" in sp3OrSource ? sp3OrSource : new Sp3EphemerisSource(sp3OrSource, opts.clk, opts.osb);
|
|
3341
3836
|
const eng = new PppEngine(opts, source);
|
|
3342
3837
|
for (const epoch of epochs) eng.process(epoch);
|
|
3343
3838
|
return eng.solution();
|
|
3344
3839
|
}
|
|
3345
3840
|
|
|
3346
|
-
// src/positioning/ppp-ar.ts
|
|
3347
|
-
function wlWavelength(f1, f2) {
|
|
3348
|
-
return C_LIGHT / (f1 - f2);
|
|
3349
|
-
}
|
|
3350
|
-
function nlWavelength(f1, f2) {
|
|
3351
|
-
return C_LIGHT / (f1 + f2);
|
|
3352
|
-
}
|
|
3353
|
-
function resolvePppAmbiguities(sats, Qaif, opts = {}) {
|
|
3354
|
-
const wlThreshold = opts.wlThreshold ?? 0.25;
|
|
3355
|
-
const ratioThreshold = opts.ratioThreshold ?? 3;
|
|
3356
|
-
const kept = [];
|
|
3357
|
-
const nWl = [];
|
|
3358
|
-
const rejectedWl = [];
|
|
3359
|
-
for (let i = 0; i < sats.length; i++) {
|
|
3360
|
-
const s = sats[i];
|
|
3361
|
-
const wlFloat = s.mwCyc - (s.wlBiasCyc ?? 0);
|
|
3362
|
-
const r = Math.round(wlFloat);
|
|
3363
|
-
if (Math.abs(wlFloat - r) <= wlThreshold) {
|
|
3364
|
-
kept.push(i);
|
|
3365
|
-
nWl.push(r);
|
|
3366
|
-
} else {
|
|
3367
|
-
rejectedWl.push(s.prn);
|
|
3368
|
-
}
|
|
3369
|
-
}
|
|
3370
|
-
if (kept.length < 2) {
|
|
3371
|
-
return {
|
|
3372
|
-
fixed: false,
|
|
3373
|
-
ratio: 0,
|
|
3374
|
-
refPrn: null,
|
|
3375
|
-
sats: [],
|
|
3376
|
-
rejectedWl
|
|
3377
|
-
};
|
|
3378
|
-
}
|
|
3379
|
-
const n1Float = [];
|
|
3380
|
-
const lamNl = [];
|
|
3381
|
-
for (let k = 0; k < kept.length; k++) {
|
|
3382
|
-
const s = sats[kept[k]];
|
|
3383
|
-
const lNl = nlWavelength(s.f1, s.f2);
|
|
3384
|
-
lamNl.push(lNl);
|
|
3385
|
-
const n1 = s.aIF / lNl - s.f2 / (s.f1 - s.f2) * nWl[k] - (s.nlBiasCyc ?? 0);
|
|
3386
|
-
n1Float.push(n1);
|
|
3387
|
-
}
|
|
3388
|
-
let ref = 0;
|
|
3389
|
-
for (let k = 1; k < kept.length; k++) {
|
|
3390
|
-
const e = sats[kept[k]].elevDeg ?? -1;
|
|
3391
|
-
if (e > (sats[kept[ref]].elevDeg ?? -1)) ref = k;
|
|
3392
|
-
}
|
|
3393
|
-
const m = kept.length - 1;
|
|
3394
|
-
const sd = new Float64Array(m);
|
|
3395
|
-
const Qsd = new Float64Array(m * m);
|
|
3396
|
-
const others = [];
|
|
3397
|
-
for (let k = 0; k < kept.length; k++) if (k !== ref) others.push(k);
|
|
3398
|
-
const n = sats.length;
|
|
3399
|
-
const qN1 = (ka, kb) => Qaif[kept[ka] * n + kept[kb]] / (lamNl[ka] * lamNl[kb]);
|
|
3400
|
-
for (let a = 0; a < m; a++) {
|
|
3401
|
-
const ka = others[a];
|
|
3402
|
-
sd[a] = n1Float[ka] - n1Float[ref];
|
|
3403
|
-
for (let b = 0; b < m; b++) {
|
|
3404
|
-
const kb = others[b];
|
|
3405
|
-
Qsd[a * m + b] = qN1(ka, kb) - qN1(ka, ref) - qN1(ref, kb) + qN1(ref, ref);
|
|
3406
|
-
}
|
|
3407
|
-
}
|
|
3408
|
-
const res = lambdaSearch(sd, Qsd, m, 2);
|
|
3409
|
-
const ratio = res ? Math.min(res.ratio, 999.9) : 0;
|
|
3410
|
-
const fixed = !!res && ratio >= ratioThreshold;
|
|
3411
|
-
const refN1 = Math.round(n1Float[ref]);
|
|
3412
|
-
const sdFix = res?.candidates[0];
|
|
3413
|
-
const outSats = [];
|
|
3414
|
-
for (let k = 0; k < kept.length; k++) {
|
|
3415
|
-
const s = sats[kept[k]];
|
|
3416
|
-
let n1;
|
|
3417
|
-
if (k === ref) {
|
|
3418
|
-
n1 = refN1;
|
|
3419
|
-
} else {
|
|
3420
|
-
const a = others.indexOf(k);
|
|
3421
|
-
n1 = fixed && sdFix ? refN1 + Math.round(sdFix[a]) : Math.round(n1Float[k]);
|
|
3422
|
-
}
|
|
3423
|
-
const lNl = lamNl[k];
|
|
3424
|
-
const aIF = lNl * n1 + lNl * (s.f2 / (s.f1 - s.f2)) * nWl[k];
|
|
3425
|
-
outSats.push({ prn: s.prn, nWl: nWl[k], n1, aIF });
|
|
3426
|
-
}
|
|
3427
|
-
return {
|
|
3428
|
-
fixed,
|
|
3429
|
-
ratio,
|
|
3430
|
-
refPrn: sats[kept[ref]].prn,
|
|
3431
|
-
sats: outSats,
|
|
3432
|
-
rejectedWl
|
|
3433
|
-
};
|
|
3434
|
-
}
|
|
3435
|
-
function solveSpd(A, b) {
|
|
3436
|
-
const n = b.length;
|
|
3437
|
-
const L = Array.from({ length: n }, () => new Array(n).fill(0));
|
|
3438
|
-
for (let i = 0; i < n; i++) {
|
|
3439
|
-
for (let j = 0; j <= i; j++) {
|
|
3440
|
-
let s = A[i][j];
|
|
3441
|
-
for (let k = 0; k < j; k++) s -= L[i][k] * L[j][k];
|
|
3442
|
-
if (i === j) {
|
|
3443
|
-
if (s <= 0) return null;
|
|
3444
|
-
L[i][j] = Math.sqrt(s);
|
|
3445
|
-
} else {
|
|
3446
|
-
L[i][j] = s / L[j][j];
|
|
3447
|
-
}
|
|
3448
|
-
}
|
|
3449
|
-
}
|
|
3450
|
-
const y = new Array(n).fill(0);
|
|
3451
|
-
for (let i = 0; i < n; i++) {
|
|
3452
|
-
let s = b[i];
|
|
3453
|
-
for (let k = 0; k < i; k++) s -= L[i][k] * y[k];
|
|
3454
|
-
y[i] = s / L[i][i];
|
|
3455
|
-
}
|
|
3456
|
-
const x = new Array(n).fill(0);
|
|
3457
|
-
for (let i = n - 1; i >= 0; i--) {
|
|
3458
|
-
let s = y[i];
|
|
3459
|
-
for (let k = i + 1; k < n; k++) s -= L[k][i] * x[k];
|
|
3460
|
-
x[i] = s / L[i][i];
|
|
3461
|
-
}
|
|
3462
|
-
return x;
|
|
3463
|
-
}
|
|
3464
|
-
function fixPppPosition(state, fcb, opts = {}) {
|
|
3465
|
-
const floatPos = state.position;
|
|
3466
|
-
const noFix = {
|
|
3467
|
-
fixed: false,
|
|
3468
|
-
position: floatPos,
|
|
3469
|
-
floatPosition: floatPos,
|
|
3470
|
-
shift: [0, 0, 0],
|
|
3471
|
-
nFixed: 0,
|
|
3472
|
-
ratio: 0,
|
|
3473
|
-
refPrn: null
|
|
3474
|
-
};
|
|
3475
|
-
const amb = state.ambiguities;
|
|
3476
|
-
if (amb.length < 3) return noFix;
|
|
3477
|
-
const sats = amb.map((a) => ({
|
|
3478
|
-
prn: a.prn,
|
|
3479
|
-
aIF: a.aIF,
|
|
3480
|
-
mwCyc: a.mwCyc,
|
|
3481
|
-
f1: a.f1,
|
|
3482
|
-
f2: a.f2,
|
|
3483
|
-
wlBiasCyc: fcb.satWlFcb.get(a.prn) ?? 0,
|
|
3484
|
-
nlBiasCyc: fcb.satNlFcb.get(a.prn) ?? 0,
|
|
3485
|
-
elevDeg: a.elevDeg
|
|
3486
|
-
}));
|
|
3487
|
-
const n = sats.length;
|
|
3488
|
-
const Qaif = new Float64Array(n * n);
|
|
3489
|
-
for (let i = 0; i < n; i++)
|
|
3490
|
-
for (let j = 0; j < n; j++)
|
|
3491
|
-
Qaif[i * n + j] = state.covariance[amb[i].index][amb[j].index];
|
|
3492
|
-
const res = resolvePppAmbiguities(sats, Qaif, opts);
|
|
3493
|
-
if (!res.fixed || res.refPrn === null) {
|
|
3494
|
-
return { ...noFix, ratio: res.ratio, refPrn: res.refPrn };
|
|
3495
|
-
}
|
|
3496
|
-
const idxOfPrn = new Map(amb.map((a) => [a.prn, a.index]));
|
|
3497
|
-
const floatOfPrn = new Map(amb.map((a) => [a.prn, a.aIF]));
|
|
3498
|
-
const kept = res.sats.filter((s) => idxOfPrn.has(s.prn));
|
|
3499
|
-
const refPos = kept.findIndex((s) => s.prn === res.refPrn);
|
|
3500
|
-
if (refPos < 0 || kept.length < 2) {
|
|
3501
|
-
return { ...noFix, ratio: res.ratio, refPrn: res.refPrn };
|
|
3502
|
-
}
|
|
3503
|
-
const ambIdx = kept.map((s) => idxOfPrn.get(s.prn));
|
|
3504
|
-
const aFloat = kept.map((s) => floatOfPrn.get(s.prn));
|
|
3505
|
-
const aFixed = kept.map((s) => s.aIF);
|
|
3506
|
-
const others = kept.map((_, i) => i).filter((i) => i !== refPos);
|
|
3507
|
-
const m = others.length;
|
|
3508
|
-
const P = state.covariance;
|
|
3509
|
-
const qAA = (i, j) => P[ambIdx[i]][ambIdx[j]];
|
|
3510
|
-
const qXA = (r, i) => P[r][ambIdx[i]];
|
|
3511
|
-
const Qzz = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
3512
|
-
const z = new Array(m).fill(0);
|
|
3513
|
-
for (let a = 0; a < m; a++) {
|
|
3514
|
-
const ia = others[a];
|
|
3515
|
-
z[a] = aFloat[ia] - aFloat[refPos] - (aFixed[ia] - aFixed[refPos]);
|
|
3516
|
-
for (let b = 0; b < m; b++) {
|
|
3517
|
-
const ib = others[b];
|
|
3518
|
-
Qzz[a][b] = qAA(ia, ib) - qAA(ia, refPos) - qAA(refPos, ib) + qAA(refPos, refPos);
|
|
3519
|
-
}
|
|
3520
|
-
}
|
|
3521
|
-
const Qxz = [0, 1, 2].map(
|
|
3522
|
-
(r) => others.map((ia) => qXA(r, ia) - qXA(r, refPos))
|
|
3523
|
-
);
|
|
3524
|
-
const y = solveSpd(Qzz, z);
|
|
3525
|
-
if (!y) return { ...noFix, ratio: res.ratio, refPrn: res.refPrn };
|
|
3526
|
-
const shift = [0, 0, 0];
|
|
3527
|
-
for (let r = 0; r < 3; r++) {
|
|
3528
|
-
let s = 0;
|
|
3529
|
-
for (let a = 0; a < m; a++) s += Qxz[r][a] * y[a];
|
|
3530
|
-
shift[r] = -s;
|
|
3531
|
-
}
|
|
3532
|
-
return {
|
|
3533
|
-
fixed: true,
|
|
3534
|
-
position: [
|
|
3535
|
-
floatPos[0] + shift[0],
|
|
3536
|
-
floatPos[1] + shift[1],
|
|
3537
|
-
floatPos[2] + shift[2]
|
|
3538
|
-
],
|
|
3539
|
-
floatPosition: floatPos,
|
|
3540
|
-
shift,
|
|
3541
|
-
nFixed: m,
|
|
3542
|
-
ratio: res.ratio,
|
|
3543
|
-
refPrn: res.refPrn
|
|
3544
|
-
};
|
|
3545
|
-
}
|
|
3546
|
-
|
|
3547
3841
|
// src/positioning/ppp-fcb.ts
|
|
3548
3842
|
function extractWidelaneArcs(station, epochs, opts = {}) {
|
|
3549
3843
|
const slipCyc = opts.slipCyc ?? 4;
|
|
@@ -4077,6 +4371,10 @@ export {
|
|
|
4077
4371
|
SbasProcessor,
|
|
4078
4372
|
applyOrbitClock,
|
|
4079
4373
|
hasToOrbitClock,
|
|
4374
|
+
wlWavelength,
|
|
4375
|
+
nlWavelength,
|
|
4376
|
+
resolvePppAmbiguities,
|
|
4377
|
+
fixPppPosition,
|
|
4080
4378
|
niellMapping,
|
|
4081
4379
|
gmst,
|
|
4082
4380
|
sunEcef,
|
|
@@ -4086,10 +4384,6 @@ export {
|
|
|
4086
4384
|
Sp3EphemerisSource,
|
|
4087
4385
|
PppEngine,
|
|
4088
4386
|
solvePpp,
|
|
4089
|
-
wlWavelength,
|
|
4090
|
-
nlWavelength,
|
|
4091
|
-
resolvePppAmbiguities,
|
|
4092
|
-
fixPppPosition,
|
|
4093
4387
|
extractWidelaneArcs,
|
|
4094
4388
|
estimateWidelaneFcb,
|
|
4095
4389
|
estimateNarrowlaneFcb,
|