gnss-js 2.0.0 → 2.2.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-2CMAFEHI.js → chunk-DWUQRJ37.js} +284 -139
- package/dist/{chunk-WVTDVPKA.js → chunk-XPQ4BU6W.js} +2 -1
- package/dist/has-BaXnQarR.d.cts +123 -0
- package/dist/has-BaXnQarR.d.ts +123 -0
- package/dist/index.cjs +294 -144
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +10 -2
- package/dist/positioning.cjs +286 -137
- package/dist/positioning.d.cts +161 -2
- package/dist/positioning.d.ts +161 -2
- package/dist/positioning.js +9 -1
- package/dist/rtcm3.cjs +2 -1
- package/dist/rtcm3.d.cts +4 -1
- package/dist/rtcm3.d.ts +4 -1
- package/dist/rtcm3.js +1 -1
- package/dist/sbf.d.cts +2 -123
- package/dist/sbf.d.ts +2 -123
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -79,6 +79,7 @@ __export(src_exports, {
|
|
|
79
79
|
MultipathAccumulator: () => MultipathAccumulator,
|
|
80
80
|
OEM4_HLEN: () => OEM4_HLEN,
|
|
81
81
|
OMEGA_E: () => OMEGA_E,
|
|
82
|
+
PppEngine: () => PppEngine,
|
|
82
83
|
REFERENCE_FRAMES: () => REFERENCE_FRAMES,
|
|
83
84
|
RINEX_CODES: () => RINEX_CODES,
|
|
84
85
|
RTCM2_MESSAGE_NAMES: () => RTCM2_MESSAGE_NAMES,
|
|
@@ -106,6 +107,7 @@ __export(src_exports, {
|
|
|
106
107
|
SYS_SHORT: () => SYS_SHORT,
|
|
107
108
|
SbasProcessor: () => SbasProcessor,
|
|
108
109
|
Scale: () => Scale,
|
|
110
|
+
Sp3EphemerisSource: () => Sp3EphemerisSource,
|
|
109
111
|
WGS84_ECCENTRICITY_SQUARED: () => WGS84_ECCENTRICITY_SQUARED,
|
|
110
112
|
WGS84_FLATTENING: () => WGS84_FLATTENING,
|
|
111
113
|
WGS84_SEMI_MAJOR_AXIS: () => WGS84_SEMI_MAJOR_AXIS,
|
|
@@ -116,6 +118,7 @@ __export(src_exports, {
|
|
|
116
118
|
analyzeQuality: () => analyzeQuality,
|
|
117
119
|
applyHelmert: () => applyHelmert,
|
|
118
120
|
applyIonoDcb: () => applyIonoDcb,
|
|
121
|
+
applyOrbitClock: () => applyOrbitClock,
|
|
119
122
|
biasMetres: () => biasMetres,
|
|
120
123
|
binexCrc16: () => binexCrc16,
|
|
121
124
|
binexCrc32: () => binexCrc32,
|
|
@@ -240,6 +243,7 @@ __export(src_exports, {
|
|
|
240
243
|
glonassPosition: () => glonassPosition,
|
|
241
244
|
gmst: () => gmst,
|
|
242
245
|
greatCircleMidpoint: () => greatCircleMidpoint,
|
|
246
|
+
hasToOrbitClock: () => hasToOrbitClock,
|
|
243
247
|
hdrLine: () => hdrLine,
|
|
244
248
|
horizonDistance: () => horizonDistance,
|
|
245
249
|
ionoFree: () => ionoFree,
|
|
@@ -4069,7 +4073,7 @@ function parseBiasSinex(text) {
|
|
|
4069
4073
|
const endMs = parseEpoch(line.slice(50, 64), Infinity);
|
|
4070
4074
|
const tail = line.slice(65).trim().split(/\s+/);
|
|
4071
4075
|
if (tail.length < 2) continue;
|
|
4072
|
-
const
|
|
4076
|
+
const unit2 = tail[0];
|
|
4073
4077
|
const value = Number(tail[1]);
|
|
4074
4078
|
if (!Number.isFinite(value)) continue;
|
|
4075
4079
|
records.push({
|
|
@@ -4081,7 +4085,7 @@ function parseBiasSinex(text) {
|
|
|
4081
4085
|
startMs,
|
|
4082
4086
|
endMs,
|
|
4083
4087
|
value,
|
|
4084
|
-
unit
|
|
4088
|
+
unit: unit2
|
|
4085
4089
|
});
|
|
4086
4090
|
}
|
|
4087
4091
|
const bySat = /* @__PURE__ */ new Map();
|
|
@@ -6568,7 +6572,8 @@ function updateStreamStats(stats, frames, rawBytes) {
|
|
|
6568
6572
|
stats.satellites.set(obs.prn, {
|
|
6569
6573
|
prn: obs.prn,
|
|
6570
6574
|
system: obs.system,
|
|
6571
|
-
cn0: bestCn0,
|
|
6575
|
+
cn0: bestCn0 > 0 ? bestCn0 : null,
|
|
6576
|
+
// null = no C/N0 reported
|
|
6572
6577
|
lastSeen: now,
|
|
6573
6578
|
signals
|
|
6574
6579
|
});
|
|
@@ -9115,14 +9120,14 @@ function parseOrbitBlock(c, masks) {
|
|
|
9115
9120
|
const gnssIod = c.u(IOD_BITS[sys.system]);
|
|
9116
9121
|
const rad = c.s(13);
|
|
9117
9122
|
const inT = c.s(12);
|
|
9118
|
-
const
|
|
9123
|
+
const cross3 = c.s(12);
|
|
9119
9124
|
corrections.push({
|
|
9120
9125
|
system: sys.system,
|
|
9121
9126
|
prn,
|
|
9122
9127
|
gnssIod,
|
|
9123
9128
|
deltaRadial: rad === -4096 ? null : rad * 25e-4,
|
|
9124
9129
|
deltaInTrack: inT === -2048 ? null : inT * 8e-3,
|
|
9125
|
-
deltaCrossTrack:
|
|
9130
|
+
deltaCrossTrack: cross3 === -2048 ? null : cross3 * 8e-3
|
|
9126
9131
|
});
|
|
9127
9132
|
}
|
|
9128
9133
|
}
|
|
@@ -14837,6 +14842,55 @@ var SbasProcessor = class {
|
|
|
14837
14842
|
}
|
|
14838
14843
|
};
|
|
14839
14844
|
|
|
14845
|
+
// src/positioning/ssr-apply.ts
|
|
14846
|
+
var cross = (a, b) => [
|
|
14847
|
+
a[1] * b[2] - a[2] * b[1],
|
|
14848
|
+
a[2] * b[0] - a[0] * b[2],
|
|
14849
|
+
a[0] * b[1] - a[1] * b[0]
|
|
14850
|
+
];
|
|
14851
|
+
var norm = (a) => Math.hypot(a[0], a[1], a[2]);
|
|
14852
|
+
var unit = (a) => {
|
|
14853
|
+
const n = norm(a);
|
|
14854
|
+
return n > 0 ? [a[0] / n, a[1] / n, a[2] / n] : [0, 0, 0];
|
|
14855
|
+
};
|
|
14856
|
+
function applyOrbitClock(eph, corr, timeMs) {
|
|
14857
|
+
if (eph.system === "R" || eph.system === "S") return null;
|
|
14858
|
+
if (eph.iode !== corr.iod) return null;
|
|
14859
|
+
const age = (timeMs - corr.refTimeMs) / 1e3;
|
|
14860
|
+
if (corr.validitySeconds != null && (age < -1 || age > corr.validitySeconds))
|
|
14861
|
+
return null;
|
|
14862
|
+
const s = computeSatPosition(eph, timeMs);
|
|
14863
|
+
if (!Number.isFinite(s.x)) return null;
|
|
14864
|
+
const p = [s.x, s.y, s.z];
|
|
14865
|
+
const v = [s.vx, s.vy, s.vz];
|
|
14866
|
+
const er = unit(p);
|
|
14867
|
+
const en = unit(cross(p, v));
|
|
14868
|
+
const ea = cross(en, er);
|
|
14869
|
+
const dr = corr.radial + (corr.dotRadial ?? 0) * age;
|
|
14870
|
+
const da = corr.along + (corr.dotAlong ?? 0) * age;
|
|
14871
|
+
const dc = corr.cross + (corr.dotCross ?? 0) * age;
|
|
14872
|
+
const x = s.x + dr * er[0] + da * ea[0] + dc * en[0];
|
|
14873
|
+
const y = s.y + dr * er[1] + da * ea[1] + dc * en[1];
|
|
14874
|
+
const z = s.z + dr * er[2] + da * ea[2] + dc * en[2];
|
|
14875
|
+
const clockM = corr.clockC0 + (corr.clockC1 ?? 0) * age + (corr.clockC2 ?? 0) * age * age + (corr.highRateClock ?? 0);
|
|
14876
|
+
return { x, y, z, clockOffsetS: clockM / C_LIGHT };
|
|
14877
|
+
}
|
|
14878
|
+
function hasToOrbitClock(orbit, clock, refTimeMs, validitySeconds) {
|
|
14879
|
+
if (orbit.deltaRadial == null || orbit.deltaInTrack == null || orbit.deltaCrossTrack == null)
|
|
14880
|
+
return null;
|
|
14881
|
+
const clockC0 = clock && clock.deltaClock != null && !clock.notUsable ? clock.deltaClock : 0;
|
|
14882
|
+
return {
|
|
14883
|
+
prn: orbit.prn,
|
|
14884
|
+
iod: orbit.gnssIod,
|
|
14885
|
+
refTimeMs,
|
|
14886
|
+
radial: orbit.deltaRadial,
|
|
14887
|
+
along: orbit.deltaInTrack,
|
|
14888
|
+
cross: orbit.deltaCrossTrack,
|
|
14889
|
+
clockC0,
|
|
14890
|
+
validitySeconds
|
|
14891
|
+
};
|
|
14892
|
+
}
|
|
14893
|
+
|
|
14840
14894
|
// src/positioning/ppp-tropo.ts
|
|
14841
14895
|
var HYD_AVG_A = [
|
|
14842
14896
|
0.0012769934,
|
|
@@ -15094,14 +15148,14 @@ function buildPppAntenna(antex) {
|
|
|
15094
15148
|
}
|
|
15095
15149
|
};
|
|
15096
15150
|
}
|
|
15097
|
-
function
|
|
15151
|
+
function cross2(a, b) {
|
|
15098
15152
|
return [
|
|
15099
15153
|
a[1] * b[2] - a[2] * b[1],
|
|
15100
15154
|
a[2] * b[0] - a[0] * b[2],
|
|
15101
15155
|
a[0] * b[1] - a[1] * b[0]
|
|
15102
15156
|
];
|
|
15103
15157
|
}
|
|
15104
|
-
function
|
|
15158
|
+
function norm2(a) {
|
|
15105
15159
|
const n = Math.hypot(a[0], a[1], a[2]) || 1;
|
|
15106
15160
|
return [a[0] / n, a[1] / n, a[2] / n];
|
|
15107
15161
|
}
|
|
@@ -15109,14 +15163,14 @@ function dot(a, b) {
|
|
|
15109
15163
|
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
15110
15164
|
}
|
|
15111
15165
|
function satBodyFrame(satEcef, sunEcef2) {
|
|
15112
|
-
const z =
|
|
15113
|
-
const eSun =
|
|
15166
|
+
const z = norm2([-satEcef[0], -satEcef[1], -satEcef[2]]);
|
|
15167
|
+
const eSun = norm2([
|
|
15114
15168
|
sunEcef2[0] - satEcef[0],
|
|
15115
15169
|
sunEcef2[1] - satEcef[1],
|
|
15116
15170
|
sunEcef2[2] - satEcef[2]
|
|
15117
15171
|
]);
|
|
15118
|
-
const y =
|
|
15119
|
-
const x =
|
|
15172
|
+
const y = norm2(cross2(z, eSun));
|
|
15173
|
+
const x = norm2(cross2(y, z));
|
|
15120
15174
|
return { x, y, z };
|
|
15121
15175
|
}
|
|
15122
15176
|
function satPcoToEcef(pcoBody, frame) {
|
|
@@ -15157,7 +15211,7 @@ function phaseWindup(prn, losRcvToSat, satFrame, latRad, lonRad, state) {
|
|
|
15157
15211
|
const kx = satFrame.x;
|
|
15158
15212
|
const ky = satFrame.y;
|
|
15159
15213
|
const kdotx = dot(k, kx);
|
|
15160
|
-
const kcrossY =
|
|
15214
|
+
const kcrossY = cross2(k, ky);
|
|
15161
15215
|
const dS = [
|
|
15162
15216
|
kx[0] - k[0] * kdotx - kcrossY[0],
|
|
15163
15217
|
kx[1] - k[1] * kdotx - kcrossY[1],
|
|
@@ -15166,7 +15220,7 @@ function phaseWindup(prn, losRcvToSat, satFrame, latRad, lonRad, state) {
|
|
|
15166
15220
|
const north = enuToEcef([0, 1, 0], latRad, lonRad);
|
|
15167
15221
|
const east = enuToEcef([1, 0, 0], latRad, lonRad);
|
|
15168
15222
|
const kdotn = dot(k, north);
|
|
15169
|
-
const kcrossE =
|
|
15223
|
+
const kcrossE = cross2(k, east);
|
|
15170
15224
|
const dR = [
|
|
15171
15225
|
north[0] - k[0] * kdotn + kcrossE[0],
|
|
15172
15226
|
north[1] - k[1] * kdotn + kcrossE[1],
|
|
@@ -15176,7 +15230,7 @@ function phaseWindup(prn, losRcvToSat, satFrame, latRad, lonRad, state) {
|
|
|
15176
15230
|
const nR = Math.hypot(dR[0], dR[1], dR[2]) || 1;
|
|
15177
15231
|
let cosPhi = dot(dS, dR) / (nS * nR);
|
|
15178
15232
|
cosPhi = Math.max(-1, Math.min(1, cosPhi));
|
|
15179
|
-
const zeta =
|
|
15233
|
+
const zeta = cross2(dS, dR);
|
|
15180
15234
|
const sign = dot(k, zeta) >= 0 ? 1 : -1;
|
|
15181
15235
|
const dphi = sign * Math.acos(cosPhi) / (2 * Math.PI);
|
|
15182
15236
|
const prev = state.get(prn);
|
|
@@ -15314,13 +15368,35 @@ function ifCoeffs(f1, f2) {
|
|
|
15314
15368
|
const lambdaIf = C_LIGHT / (f1 + f2);
|
|
15315
15369
|
return { g, lambdaIf };
|
|
15316
15370
|
}
|
|
15371
|
+
var Sp3EphemerisSource = class {
|
|
15372
|
+
constructor(sp3, clk) {
|
|
15373
|
+
this.sp3 = sp3;
|
|
15374
|
+
this.clk = clk;
|
|
15375
|
+
}
|
|
15376
|
+
satState(prn, tEmitMs) {
|
|
15377
|
+
const p = sp3Position(this.sp3, prn, tEmitMs);
|
|
15378
|
+
if (!p || p.clk == null) return null;
|
|
15379
|
+
const pPlus = sp3Position(this.sp3, prn, tEmitMs + 500);
|
|
15380
|
+
const pMinus = sp3Position(this.sp3, prn, tEmitMs - 500);
|
|
15381
|
+
let vx = 0;
|
|
15382
|
+
let vy = 0;
|
|
15383
|
+
let vz = 0;
|
|
15384
|
+
if (pPlus && pMinus) {
|
|
15385
|
+
vx = pPlus.x - pMinus.x;
|
|
15386
|
+
vy = pPlus.y - pMinus.y;
|
|
15387
|
+
vz = pPlus.z - pMinus.z;
|
|
15388
|
+
}
|
|
15389
|
+
const clkS = (this.clk ? clkBias(this.clk, prn, tEmitMs) : null) ?? p.clk;
|
|
15390
|
+
return { x: p.x, y: p.y, z: p.z, vx, vy, vz, clkS };
|
|
15391
|
+
}
|
|
15392
|
+
};
|
|
15317
15393
|
function sagnacRotate(x, y, z, travelS) {
|
|
15318
15394
|
const theta = OMEGA_E * travelS;
|
|
15319
15395
|
const c = Math.cos(theta);
|
|
15320
15396
|
const s = Math.sin(theta);
|
|
15321
15397
|
return [x * c + y * s, -x * s + y * c, z];
|
|
15322
15398
|
}
|
|
15323
|
-
function satStateAtEmission(
|
|
15399
|
+
function satStateAtEmission(source, prn, recvTimeMs, rcv) {
|
|
15324
15400
|
let travelS = 0.075;
|
|
15325
15401
|
let sx = 0;
|
|
15326
15402
|
let sy = 0;
|
|
@@ -15329,18 +15405,11 @@ function satStateAtEmission(sp3, prn, recvTimeMs, rcv, clk) {
|
|
|
15329
15405
|
let velDotPos = 0;
|
|
15330
15406
|
for (let iter = 0; iter < 3; iter++) {
|
|
15331
15407
|
const tEmit = recvTimeMs - travelS * 1e3;
|
|
15332
|
-
const
|
|
15333
|
-
if (!
|
|
15334
|
-
|
|
15335
|
-
|
|
15336
|
-
|
|
15337
|
-
const vx = (pPlus.x - pMinus.x) / 1;
|
|
15338
|
-
const vy = (pPlus.y - pMinus.y) / 1;
|
|
15339
|
-
const vz = (pPlus.z - pMinus.z) / 1;
|
|
15340
|
-
velDotPos = p.x * vx + p.y * vy + p.z * vz;
|
|
15341
|
-
}
|
|
15342
|
-
clkS = (clk && clkBias(clk, prn, tEmit)) ?? p.clk;
|
|
15343
|
-
const [rx, ry, rz] = sagnacRotate(p.x, p.y, p.z, travelS);
|
|
15408
|
+
const s = source.satState(prn, tEmit);
|
|
15409
|
+
if (!s) return null;
|
|
15410
|
+
velDotPos = s.x * s.vx + s.y * s.vy + s.z * s.vz;
|
|
15411
|
+
clkS = s.clkS;
|
|
15412
|
+
const [rx, ry, rz] = sagnacRotate(s.x, s.y, s.z, travelS);
|
|
15344
15413
|
sx = rx;
|
|
15345
15414
|
sy = ry;
|
|
15346
15415
|
sz = rz;
|
|
@@ -15362,39 +15431,72 @@ var IDX_ZWD = 3;
|
|
|
15362
15431
|
var NBASE = 4;
|
|
15363
15432
|
var CLK_VAR = 1e10;
|
|
15364
15433
|
var POS_VAR = 60 * 60;
|
|
15365
|
-
|
|
15366
|
-
|
|
15367
|
-
|
|
15368
|
-
|
|
15369
|
-
|
|
15370
|
-
|
|
15371
|
-
|
|
15372
|
-
|
|
15373
|
-
|
|
15374
|
-
|
|
15375
|
-
|
|
15376
|
-
|
|
15377
|
-
|
|
15378
|
-
|
|
15379
|
-
|
|
15380
|
-
|
|
15381
|
-
|
|
15382
|
-
|
|
15383
|
-
|
|
15384
|
-
|
|
15385
|
-
|
|
15386
|
-
|
|
15387
|
-
|
|
15388
|
-
|
|
15389
|
-
|
|
15390
|
-
|
|
15391
|
-
|
|
15392
|
-
|
|
15393
|
-
|
|
15394
|
-
|
|
15395
|
-
|
|
15434
|
+
var PppEngine = class {
|
|
15435
|
+
source;
|
|
15436
|
+
opts;
|
|
15437
|
+
elevMask;
|
|
15438
|
+
codeSigma;
|
|
15439
|
+
phaseSigma;
|
|
15440
|
+
ztdQ;
|
|
15441
|
+
kinematic;
|
|
15442
|
+
corrections;
|
|
15443
|
+
truth;
|
|
15444
|
+
// Filter state (reset() initialises; mutated in place across epochs).
|
|
15445
|
+
x;
|
|
15446
|
+
P;
|
|
15447
|
+
clkIdx;
|
|
15448
|
+
clockSeeded;
|
|
15449
|
+
ambIdx;
|
|
15450
|
+
lastSeen;
|
|
15451
|
+
arcs;
|
|
15452
|
+
arcSnap;
|
|
15453
|
+
mwState;
|
|
15454
|
+
series;
|
|
15455
|
+
ei = 0;
|
|
15456
|
+
t0 = 0;
|
|
15457
|
+
convergenceSec = null;
|
|
15458
|
+
convergedStreak = 0;
|
|
15459
|
+
constructor(opts, source) {
|
|
15460
|
+
this.opts = opts;
|
|
15461
|
+
this.source = source;
|
|
15462
|
+
this.elevMask = (opts.elevationMaskDeg ?? 10) * Math.PI / 180;
|
|
15463
|
+
this.codeSigma = opts.codeSigma ?? 3;
|
|
15464
|
+
this.phaseSigma = opts.phaseSigma ?? 0.01;
|
|
15465
|
+
this.ztdQ = opts.ztdProcessNoise ?? 1e-8;
|
|
15466
|
+
this.kinematic = opts.mode === "kinematic";
|
|
15467
|
+
this.corrections = opts.corrections;
|
|
15468
|
+
this.truth = opts.groundTruth;
|
|
15469
|
+
this.reset();
|
|
15470
|
+
}
|
|
15471
|
+
/** Reinitialise the filter (fresh session). */
|
|
15472
|
+
reset() {
|
|
15473
|
+
const { opts } = this;
|
|
15474
|
+
this.x = [opts.aprioriPos[0], opts.aprioriPos[1], opts.aprioriPos[2], 0.1];
|
|
15475
|
+
const P = [];
|
|
15476
|
+
for (let i = 0; i < NBASE; i++) P.push(new Array(NBASE).fill(0));
|
|
15477
|
+
P[IDX_X][IDX_X] = 100 * 100;
|
|
15478
|
+
P[IDX_Y][IDX_Y] = 100 * 100;
|
|
15479
|
+
P[IDX_Z][IDX_Z] = 100 * 100;
|
|
15480
|
+
P[IDX_ZWD][IDX_ZWD] = 0.5 * 0.5;
|
|
15481
|
+
this.P = P;
|
|
15482
|
+
this.clkIdx = /* @__PURE__ */ new Map();
|
|
15483
|
+
this.clockSeeded = /* @__PURE__ */ new Set();
|
|
15484
|
+
this.ambIdx = /* @__PURE__ */ new Map();
|
|
15485
|
+
this.lastSeen = /* @__PURE__ */ new Map();
|
|
15486
|
+
this.arcs = [];
|
|
15487
|
+
this.arcSnap = /* @__PURE__ */ new Map();
|
|
15488
|
+
this.mwState = /* @__PURE__ */ new Map();
|
|
15489
|
+
this.series = [];
|
|
15490
|
+
this.ei = 0;
|
|
15491
|
+
this.t0 = 0;
|
|
15492
|
+
this.convergenceSec = null;
|
|
15493
|
+
this.convergedStreak = 0;
|
|
15494
|
+
}
|
|
15495
|
+
flushArc(prn, minEpochs = 10) {
|
|
15496
|
+
const s = this.arcSnap.get(prn);
|
|
15497
|
+
this.arcSnap.delete(prn);
|
|
15396
15498
|
if (!s || s.nEpochs < minEpochs) return;
|
|
15397
|
-
arcs.push({
|
|
15499
|
+
this.arcs.push({
|
|
15398
15500
|
prn,
|
|
15399
15501
|
aIF: s.aIF,
|
|
15400
15502
|
mwCyc: s.mwCyc,
|
|
@@ -15405,64 +15507,88 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
15405
15507
|
startMs: s.startMs,
|
|
15406
15508
|
endMs: s.endMs
|
|
15407
15509
|
});
|
|
15408
|
-
}
|
|
15409
|
-
|
|
15410
|
-
|
|
15510
|
+
}
|
|
15511
|
+
/** Detect a cycle slip via the Melbourne–Wübbena wide-lane ambiguity. */
|
|
15512
|
+
detectSlip(o, ei) {
|
|
15411
15513
|
const lamW = C_LIGHT / (o.f1 - o.f2);
|
|
15412
15514
|
const lw = o.l1 - o.l2;
|
|
15413
15515
|
const pn = (o.f1 * o.c1 + o.f2 * o.c2) / (o.f1 + o.f2);
|
|
15414
15516
|
const mw = lw - pn / lamW;
|
|
15415
|
-
const st = mwState.get(o.prn);
|
|
15517
|
+
const st = this.mwState.get(o.prn);
|
|
15416
15518
|
let slip = o.slip;
|
|
15417
15519
|
if (!st || ei - st.lastEi > 2)
|
|
15418
15520
|
slip = true;
|
|
15419
15521
|
else if (Math.abs(mw - st.mean) > 4) slip = true;
|
|
15420
|
-
if (slip) mwState.set(o.prn, { mean: mw, n: 1, lastEi: ei });
|
|
15522
|
+
if (slip) this.mwState.set(o.prn, { mean: mw, n: 1, lastEi: ei });
|
|
15421
15523
|
else {
|
|
15422
15524
|
const n = st.n + 1;
|
|
15423
|
-
mwState.set(o.prn, {
|
|
15525
|
+
this.mwState.set(o.prn, {
|
|
15424
15526
|
mean: st.mean + (mw - st.mean) / Math.min(n, 100),
|
|
15425
15527
|
n,
|
|
15426
15528
|
lastEi: ei
|
|
15427
15529
|
});
|
|
15428
15530
|
}
|
|
15429
15531
|
return slip;
|
|
15430
|
-
}
|
|
15431
|
-
|
|
15432
|
-
const idx = x.length;
|
|
15433
|
-
x.push(initVal);
|
|
15434
|
-
for (const row of P) row.push(0);
|
|
15435
|
-
P.push(new Array(x.length).fill(0));
|
|
15436
|
-
P[idx][idx] = initVar;
|
|
15532
|
+
}
|
|
15533
|
+
growState(initVal, initVar) {
|
|
15534
|
+
const idx = this.x.length;
|
|
15535
|
+
this.x.push(initVal);
|
|
15536
|
+
for (const row of this.P) row.push(0);
|
|
15537
|
+
this.P.push(new Array(this.x.length).fill(0));
|
|
15538
|
+
this.P[idx][idx] = initVar;
|
|
15437
15539
|
return idx;
|
|
15438
|
-
}
|
|
15439
|
-
|
|
15440
|
-
x.splice(idx, 1);
|
|
15441
|
-
P.splice(idx, 1);
|
|
15442
|
-
for (const row of P) row.splice(idx, 1);
|
|
15443
|
-
for (const [prn, i] of ambIdx) {
|
|
15444
|
-
if (i === idx) ambIdx.delete(prn);
|
|
15445
|
-
else if (i > idx) ambIdx.set(prn, i - 1);
|
|
15540
|
+
}
|
|
15541
|
+
dropState(idx) {
|
|
15542
|
+
this.x.splice(idx, 1);
|
|
15543
|
+
this.P.splice(idx, 1);
|
|
15544
|
+
for (const row of this.P) row.splice(idx, 1);
|
|
15545
|
+
for (const [prn, i] of this.ambIdx) {
|
|
15546
|
+
if (i === idx) this.ambIdx.delete(prn);
|
|
15547
|
+
else if (i > idx) this.ambIdx.set(prn, i - 1);
|
|
15446
15548
|
}
|
|
15447
|
-
for (const [sys, i] of clkIdx) {
|
|
15448
|
-
if (i > idx) clkIdx.set(sys, i - 1);
|
|
15549
|
+
for (const [sys, i] of this.clkIdx) {
|
|
15550
|
+
if (i > idx) this.clkIdx.set(sys, i - 1);
|
|
15449
15551
|
}
|
|
15450
|
-
}
|
|
15451
|
-
|
|
15452
|
-
|
|
15552
|
+
}
|
|
15553
|
+
/** State index of a constellation's receiver clock, creating it lazily. */
|
|
15554
|
+
clockOf(sys) {
|
|
15555
|
+
let i = this.clkIdx.get(sys);
|
|
15453
15556
|
if (i === void 0) {
|
|
15454
|
-
i = growState(0, CLK_VAR);
|
|
15455
|
-
clkIdx.set(sys, i);
|
|
15557
|
+
i = this.growState(0, CLK_VAR);
|
|
15558
|
+
this.clkIdx.set(sys, i);
|
|
15456
15559
|
}
|
|
15457
15560
|
return i;
|
|
15458
|
-
}
|
|
15459
|
-
|
|
15460
|
-
|
|
15461
|
-
|
|
15462
|
-
|
|
15463
|
-
|
|
15464
|
-
|
|
15465
|
-
|
|
15561
|
+
}
|
|
15562
|
+
/** Process one epoch, carrying the filter forward; returns its result. */
|
|
15563
|
+
process(epoch) {
|
|
15564
|
+
const {
|
|
15565
|
+
source,
|
|
15566
|
+
opts,
|
|
15567
|
+
elevMask,
|
|
15568
|
+
codeSigma,
|
|
15569
|
+
phaseSigma,
|
|
15570
|
+
ztdQ,
|
|
15571
|
+
kinematic,
|
|
15572
|
+
corrections,
|
|
15573
|
+
truth,
|
|
15574
|
+
x,
|
|
15575
|
+
P,
|
|
15576
|
+
clkIdx,
|
|
15577
|
+
clockSeeded,
|
|
15578
|
+
ambIdx,
|
|
15579
|
+
lastSeen,
|
|
15580
|
+
arcSnap,
|
|
15581
|
+
mwState,
|
|
15582
|
+
series
|
|
15583
|
+
} = this;
|
|
15584
|
+
const flushArc = this.flushArc.bind(this);
|
|
15585
|
+
const detectSlip = this.detectSlip.bind(this);
|
|
15586
|
+
const growState = this.growState.bind(this);
|
|
15587
|
+
const dropState = this.dropState.bind(this);
|
|
15588
|
+
const clockOf = this.clockOf.bind(this);
|
|
15589
|
+
const ei = this.ei;
|
|
15590
|
+
if (ei === 0) this.t0 = epoch.timeMs;
|
|
15591
|
+
const t0 = this.t0;
|
|
15466
15592
|
if (kinematic && ei > 0) {
|
|
15467
15593
|
for (const p of [IDX_X, IDX_Y, IDX_Z]) {
|
|
15468
15594
|
for (let j = 0; j < x.length; j++) {
|
|
@@ -15483,7 +15609,7 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
15483
15609
|
for (const o of epoch.obs) {
|
|
15484
15610
|
if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
|
|
15485
15611
|
const slip = detectSlip(o, ei);
|
|
15486
|
-
const sat = satStateAtEmission(
|
|
15612
|
+
const sat = satStateAtEmission(source, o.prn, epoch.timeMs, rcv);
|
|
15487
15613
|
if (!sat) continue;
|
|
15488
15614
|
const [elRad, azRad] = getAer(
|
|
15489
15615
|
sat.state.x,
|
|
@@ -15503,7 +15629,9 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
15503
15629
|
const lam1 = C_LIGHT / o.f1;
|
|
15504
15630
|
const lam2 = C_LIGHT / o.f2;
|
|
15505
15631
|
if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
|
|
15506
|
-
const
|
|
15632
|
+
const b1 = source.codeBias?.(o.prn, o.code1 ?? "", epoch.timeMs) ?? 0;
|
|
15633
|
+
const b2 = source.codeBias?.(o.prn, o.code2 ?? "", epoch.timeMs) ?? 0;
|
|
15634
|
+
const pIf = g * (o.c1 - b1) - (g - 1) * (o.c2 - b2);
|
|
15507
15635
|
const lIf = g * (o.l1 * lam1) - (g - 1) * (o.l2 * lam2);
|
|
15508
15636
|
if (!Number.isFinite(pIf) || !Number.isFinite(lIf)) continue;
|
|
15509
15637
|
const trop = opts.troposphere ?? true ? niellMapping(elRad, latRad, heightM, epoch.timeMs) : { zhd: 0, mh: 0, mw: 0 };
|
|
@@ -15690,16 +15818,16 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
15690
15818
|
pos[2] - truth[2]
|
|
15691
15819
|
);
|
|
15692
15820
|
if (error3d < 0.1) {
|
|
15693
|
-
convergedStreak++;
|
|
15694
|
-
if (convergedStreak >= 10 && convergenceSec == null) {
|
|
15695
|
-
convergenceSec = (epoch.timeMs - t0) / 1e3;
|
|
15821
|
+
this.convergedStreak++;
|
|
15822
|
+
if (this.convergedStreak >= 10 && this.convergenceSec == null) {
|
|
15823
|
+
this.convergenceSec = (epoch.timeMs - t0) / 1e3;
|
|
15696
15824
|
}
|
|
15697
15825
|
} else {
|
|
15698
|
-
convergedStreak = 0;
|
|
15699
|
-
convergenceSec = null;
|
|
15826
|
+
this.convergedStreak = 0;
|
|
15827
|
+
this.convergenceSec = null;
|
|
15700
15828
|
}
|
|
15701
15829
|
}
|
|
15702
|
-
|
|
15830
|
+
const result = {
|
|
15703
15831
|
timeMs: epoch.timeMs,
|
|
15704
15832
|
enu,
|
|
15705
15833
|
error3d,
|
|
@@ -15708,50 +15836,68 @@ function solvePpp(epochs, sp3, opts) {
|
|
|
15708
15836
|
ztdWet: x[IDX_ZWD],
|
|
15709
15837
|
ztdHydrostatic: epochZhd,
|
|
15710
15838
|
phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0
|
|
15711
|
-
}
|
|
15712
|
-
|
|
15713
|
-
|
|
15714
|
-
|
|
15715
|
-
|
|
15716
|
-
|
|
15717
|
-
|
|
15718
|
-
|
|
15719
|
-
|
|
15720
|
-
|
|
15721
|
-
|
|
15722
|
-
|
|
15723
|
-
|
|
15724
|
-
|
|
15725
|
-
|
|
15726
|
-
|
|
15727
|
-
|
|
15839
|
+
};
|
|
15840
|
+
series.push(result);
|
|
15841
|
+
this.ei = ei + 1;
|
|
15842
|
+
return result;
|
|
15843
|
+
}
|
|
15844
|
+
/** Finalise the session: capture the AR state, flush open arcs, assemble. */
|
|
15845
|
+
solution() {
|
|
15846
|
+
const { opts, x, P, ambIdx, arcSnap, mwState, arcs, series, truth } = this;
|
|
15847
|
+
const flushArc = this.flushArc.bind(this);
|
|
15848
|
+
let finalState;
|
|
15849
|
+
if (opts.exposeState) {
|
|
15850
|
+
const ambs = [];
|
|
15851
|
+
for (const [prn, index] of ambIdx) {
|
|
15852
|
+
const s = arcSnap.get(prn);
|
|
15853
|
+
if (!s || s.nEpochs < 10) continue;
|
|
15854
|
+
ambs.push({
|
|
15855
|
+
prn,
|
|
15856
|
+
index,
|
|
15857
|
+
aIF: x[index],
|
|
15858
|
+
mwCyc: mwState.get(prn)?.mean ?? s.mwCyc,
|
|
15859
|
+
f1: s.f1,
|
|
15860
|
+
f2: s.f2,
|
|
15861
|
+
elevDeg: s.elevSum / s.nEpochs
|
|
15862
|
+
});
|
|
15863
|
+
}
|
|
15864
|
+
finalState = {
|
|
15865
|
+
position: [x[IDX_X], x[IDX_Y], x[IDX_Z]],
|
|
15866
|
+
covariance: P.map((row) => row.slice()),
|
|
15867
|
+
ambiguities: ambs
|
|
15868
|
+
};
|
|
15728
15869
|
}
|
|
15729
|
-
|
|
15730
|
-
|
|
15731
|
-
|
|
15732
|
-
|
|
15870
|
+
for (const prn of [...arcSnap.keys()]) flushArc(prn);
|
|
15871
|
+
const finalPos = [
|
|
15872
|
+
x[IDX_X],
|
|
15873
|
+
x[IDX_Y],
|
|
15874
|
+
x[IDX_Z]
|
|
15875
|
+
];
|
|
15876
|
+
const llh = ecefToGeodetic(finalPos[0], finalPos[1], finalPos[2]);
|
|
15877
|
+
const finalError3d = truth ? Math.hypot(
|
|
15878
|
+
finalPos[0] - truth[0],
|
|
15879
|
+
finalPos[1] - truth[1],
|
|
15880
|
+
finalPos[2] - truth[2]
|
|
15881
|
+
) : null;
|
|
15882
|
+
return {
|
|
15883
|
+
position: finalPos,
|
|
15884
|
+
llh,
|
|
15885
|
+
series,
|
|
15886
|
+
ztdWet: x[IDX_ZWD],
|
|
15887
|
+
ztdHydrostatic: series.length ? series[series.length - 1].ztdHydrostatic : 0,
|
|
15888
|
+
epochsUsed: series.length,
|
|
15889
|
+
convergenceSec: this.convergenceSec,
|
|
15890
|
+
finalError3d,
|
|
15891
|
+
arcs,
|
|
15892
|
+
finalState
|
|
15733
15893
|
};
|
|
15734
15894
|
}
|
|
15735
|
-
|
|
15736
|
-
|
|
15737
|
-
const
|
|
15738
|
-
const
|
|
15739
|
-
|
|
15740
|
-
|
|
15741
|
-
finalPos[2] - truth[2]
|
|
15742
|
-
) : null;
|
|
15743
|
-
return {
|
|
15744
|
-
position: finalPos,
|
|
15745
|
-
llh,
|
|
15746
|
-
series,
|
|
15747
|
-
ztdWet: x[IDX_ZWD],
|
|
15748
|
-
ztdHydrostatic: series.length ? series[series.length - 1].ztdHydrostatic : 0,
|
|
15749
|
-
epochsUsed: epochs.length,
|
|
15750
|
-
convergenceSec,
|
|
15751
|
-
finalError3d,
|
|
15752
|
-
arcs,
|
|
15753
|
-
finalState
|
|
15754
|
-
};
|
|
15895
|
+
};
|
|
15896
|
+
function solvePpp(epochs, sp3OrSource, opts) {
|
|
15897
|
+
const source = "satState" in sp3OrSource ? sp3OrSource : new Sp3EphemerisSource(sp3OrSource, opts.clk);
|
|
15898
|
+
const eng = new PppEngine(opts, source);
|
|
15899
|
+
for (const epoch of epochs) eng.process(epoch);
|
|
15900
|
+
return eng.solution();
|
|
15755
15901
|
}
|
|
15756
15902
|
|
|
15757
15903
|
// src/positioning/ppp-ar.ts
|
|
@@ -18806,6 +18952,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
18806
18952
|
MultipathAccumulator,
|
|
18807
18953
|
OEM4_HLEN,
|
|
18808
18954
|
OMEGA_E,
|
|
18955
|
+
PppEngine,
|
|
18809
18956
|
REFERENCE_FRAMES,
|
|
18810
18957
|
RINEX_CODES,
|
|
18811
18958
|
RTCM2_MESSAGE_NAMES,
|
|
@@ -18833,6 +18980,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
18833
18980
|
SYS_SHORT,
|
|
18834
18981
|
SbasProcessor,
|
|
18835
18982
|
Scale,
|
|
18983
|
+
Sp3EphemerisSource,
|
|
18836
18984
|
WGS84_ECCENTRICITY_SQUARED,
|
|
18837
18985
|
WGS84_FLATTENING,
|
|
18838
18986
|
WGS84_SEMI_MAJOR_AXIS,
|
|
@@ -18843,6 +18991,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
18843
18991
|
analyzeQuality,
|
|
18844
18992
|
applyHelmert,
|
|
18845
18993
|
applyIonoDcb,
|
|
18994
|
+
applyOrbitClock,
|
|
18846
18995
|
biasMetres,
|
|
18847
18996
|
binexCrc16,
|
|
18848
18997
|
binexCrc32,
|
|
@@ -18967,6 +19116,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
18967
19116
|
glonassPosition,
|
|
18968
19117
|
gmst,
|
|
18969
19118
|
greatCircleMidpoint,
|
|
19119
|
+
hasToOrbitClock,
|
|
18970
19120
|
hdrLine,
|
|
18971
19121
|
horizonDistance,
|
|
18972
19122
|
ionoFree,
|