gnss-js 2.13.0 → 2.14.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.
@@ -2935,6 +2935,103 @@ function solidEarthTide(rcv, sun, moon) {
2935
2935
  return disp;
2936
2936
  }
2937
2937
 
2938
+ // src/positioning/ocean-loading.ts
2939
+ var BLQ_CONSTITUENTS = [
2940
+ "M2",
2941
+ "S2",
2942
+ "N2",
2943
+ "K2",
2944
+ "K1",
2945
+ "O1",
2946
+ "P1",
2947
+ "Q1",
2948
+ "Mf",
2949
+ "Mm",
2950
+ "Ssa"
2951
+ ];
2952
+ var ARGS = [
2953
+ [140519e-9, 2, -2, 0, 0],
2954
+ // M2
2955
+ [145444e-9, 0, 0, 0, 0],
2956
+ // S2
2957
+ [13788e-8, 2, -3, 1, 0],
2958
+ // N2
2959
+ [145842e-9, 2, 0, 0, 0],
2960
+ // K2
2961
+ [72921e-9, 1, 0, 0, 0.25],
2962
+ // K1
2963
+ [67598e-9, 1, -2, 0, -0.25],
2964
+ // O1
2965
+ [72523e-9, -1, 0, 0, -0.25],
2966
+ // P1
2967
+ [64959e-9, 1, -3, 1, -0.25],
2968
+ // Q1
2969
+ [53234e-10, 0, 2, 0, 0],
2970
+ // Mf
2971
+ [26392e-10, 0, 1, -1, 0],
2972
+ // Mm
2973
+ [3982e-10, 2, 0, 0, 0]
2974
+ // Ssa
2975
+ ];
2976
+ var D2R2 = Math.PI / 180;
2977
+ function oceanLoadingEnu(c, utcMs) {
2978
+ const day = Math.floor(utcMs / 864e5);
2979
+ const fday = (utcMs - day * 864e5) / 1e3;
2980
+ const days = day - Date.UTC(1975, 0, 1) / 864e5 + 1;
2981
+ const t = (27392.500528 + 1.000000035 * days) / 36525;
2982
+ const t2 = t * t;
2983
+ const t3 = t2 * t;
2984
+ const a = [
2985
+ fday,
2986
+ (279.69668 + 36000.768930485 * t + 303e-6 * t2) * D2R2,
2987
+ // H0
2988
+ (270.434358 + 481267.88314137 * t - 1133e-6 * t2 + 19e-7 * t3) * D2R2,
2989
+ // S0
2990
+ (334.329653 + 4069.0340329577 * t - 0.010325 * t2 - 12e-6 * t3) * D2R2,
2991
+ // P0
2992
+ 2 * Math.PI
2993
+ ];
2994
+ const dp = [0, 0, 0];
2995
+ for (let i = 0; i < ARGS.length; i++) {
2996
+ let ang = 0;
2997
+ for (let j = 0; j < 5; j++) ang += a[j] * ARGS[i][j];
2998
+ for (let k = 0; k < 3; k++)
2999
+ dp[k] += c.amplitude[i][k] * Math.cos(ang - c.phase[i][k] * D2R2);
3000
+ }
3001
+ return [-dp[1], -dp[2], dp[0]];
3002
+ }
3003
+ function parseBlq(text) {
3004
+ const out = /* @__PURE__ */ new Map();
3005
+ const lines = text.split(/\r?\n/);
3006
+ for (let i = 0; i < lines.length; i++) {
3007
+ const l = lines[i];
3008
+ if (!l.trim() || l.startsWith("$$")) continue;
3009
+ const name = l.trim().split(/\s+/)[0].toUpperCase();
3010
+ const rows = [];
3011
+ let j = i + 1;
3012
+ while (j < lines.length && rows.length < 6) {
3013
+ const r = lines[j];
3014
+ j++;
3015
+ if (r.startsWith("$$") || !r.trim()) continue;
3016
+ const v = r.trim().split(/\s+/).map(Number);
3017
+ if (v.length !== 11 || v.some((x) => !Number.isFinite(x))) break;
3018
+ rows.push(v);
3019
+ }
3020
+ if (rows.length === 6) {
3021
+ out.set(name, {
3022
+ amplitude: BLQ_CONSTITUENTS.map(
3023
+ (_, k) => [rows[0][k], rows[1][k], rows[2][k]]
3024
+ ),
3025
+ phase: BLQ_CONSTITUENTS.map(
3026
+ (_, k) => [rows[3][k], rows[4][k], rows[5][k]]
3027
+ )
3028
+ });
3029
+ i = j - 1;
3030
+ }
3031
+ }
3032
+ return out;
3033
+ }
3034
+
2938
3035
  // src/positioning/ppp-corrections.ts
2939
3036
  function applyCorrections(corrections, geom, ctx) {
2940
3037
  if (corrections.evaluate) return corrections.evaluate(geom, ctx);
@@ -2952,6 +3049,14 @@ function createPppCorrections(cfg) {
2952
3049
  const sun = sunEcef(timeMs);
2953
3050
  const moon = moonEcef(timeMs);
2954
3051
  const tideDisp = useTides ? solidEarthTide(rcvEcef, sun, moon) : [0, 0, 0];
3052
+ if (cfg.oceanLoading) {
3053
+ const [e, n, u] = oceanLoadingEnu(cfg.oceanLoading, timeMs);
3054
+ const [lat, lon] = ecefToGeodetic(rcvEcef[0], rcvEcef[1], rcvEcef[2]);
3055
+ const d = enuToEcef([e, n, u], lat, lon);
3056
+ tideDisp[0] += d[0];
3057
+ tideDisp[1] += d[1];
3058
+ tideDisp[2] += d[2];
3059
+ }
2955
3060
  return { timeMs, sun, moon, tideDisp };
2956
3061
  },
2957
3062
  evaluate(geom, ctx) {
@@ -3006,7 +3111,7 @@ function createPppCorrections(cfg) {
3006
3111
  rangeM += interpPcv(off, zenithDeg);
3007
3112
  }
3008
3113
  }
3009
- if (useTides && ctx) {
3114
+ if (ctx) {
3010
3115
  rangeM -= dot(e, ctx.tideDisp);
3011
3116
  }
3012
3117
  if (useWindup && frame) {
@@ -3144,7 +3249,32 @@ function sagnacRotate(x, y, z, travelS) {
3144
3249
  const s = Math.sin(theta);
3145
3250
  return [x * c + y * s, -x * s + y * c, z];
3146
3251
  }
3147
- function satStateAtEmission(source, prn, recvTimeMs, rcv) {
3252
+ function satStateAtEmission(source, prn, recvTimeMs, rcv, pseudorangeM) {
3253
+ if (pseudorangeM !== void 0 && pseudorangeM > 1e6) {
3254
+ let tEmit = recvTimeMs - pseudorangeM / C_LIGHT * 1e3;
3255
+ const s0 = source.satState(prn, tEmit);
3256
+ if (!s0) return null;
3257
+ tEmit -= s0.clkS * 1e3;
3258
+ const s = source.satState(prn, tEmit);
3259
+ if (!s) return null;
3260
+ let travelS2 = 0.075;
3261
+ let pos = [s.x, s.y, s.z];
3262
+ for (let iter = 0; iter < 3; iter++) {
3263
+ pos = sagnacRotate(s.x, s.y, s.z, travelS2);
3264
+ travelS2 = Math.hypot(pos[0] - rcv[0], pos[1] - rcv[1], pos[2] - rcv[2]) / C_LIGHT;
3265
+ }
3266
+ const velDotPos2 = s.x * s.vx + s.y * s.vy + s.z * s.vz;
3267
+ const relS2 = -2 * velDotPos2 / (C_LIGHT * C_LIGHT);
3268
+ return {
3269
+ state: {
3270
+ x: pos[0],
3271
+ y: pos[1],
3272
+ z: pos[2],
3273
+ clkM: C_LIGHT * (s.clkS + relS2)
3274
+ },
3275
+ travelS: travelS2
3276
+ };
3277
+ }
3148
3278
  let travelS = 0.075;
3149
3279
  let sx = 0;
3150
3280
  let sy = 0;
@@ -3367,7 +3497,7 @@ var PppEngine = class {
3367
3497
  for (const ci of clkIdx.values()) P[ci][ci] = CLK_VAR;
3368
3498
  P[IDX_ZWD][IDX_ZWD] += ztdQ * (ei > 0 ? 1 : 0);
3369
3499
  const rcv = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
3370
- const [latRad, , heightM] = ecefToGeodetic(rcv[0], rcv[1], rcv[2]);
3500
+ const [latRad, lonRad, heightM] = ecefToGeodetic(rcv[0], rcv[1], rcv[2]);
3371
3501
  const epochCtx = corrections?.epochContext?.(epoch.timeMs, rcv) ?? null;
3372
3502
  const vis = [];
3373
3503
  let epochZhd = 0;
@@ -3377,7 +3507,7 @@ var PppEngine = class {
3377
3507
  const o = applySatBiases(source, raw, epoch.timeMs);
3378
3508
  if (!o) continue;
3379
3509
  const slip = detectSlip(o, ei);
3380
- const sat = satStateAtEmission(source, o.prn, epoch.timeMs, rcv);
3510
+ const sat = satStateAtEmission(source, o.prn, epoch.timeMs, rcv, o.c1);
3381
3511
  if (!sat) continue;
3382
3512
  const [elRad, azRad] = getAer(
3383
3513
  sat.state.x,
@@ -3400,7 +3530,17 @@ var PppEngine = class {
3400
3530
  const pIf = g * o.c1 - (g - 1) * o.c2;
3401
3531
  const lIf = g * (o.l1 * lam1) - (g - 1) * (o.l2 * lam2);
3402
3532
  if (!Number.isFinite(pIf) || !Number.isFinite(lIf)) continue;
3403
- const trop = opts.troposphere ?? true ? niellMapping(elRad, latRad, heightM, epoch.timeMs) : { zhd: 0, mh: 0, mw: 0 };
3533
+ const trop = opts.troposphere ?? true ? opts.troposphereModel ? opts.troposphereModel.delays(
3534
+ epoch.timeMs,
3535
+ latRad,
3536
+ lonRad,
3537
+ heightM,
3538
+ elRad,
3539
+ azRad
3540
+ ) : {
3541
+ ...niellMapping(elRad, latRad, heightM, epoch.timeMs),
3542
+ gradient: 0
3543
+ } : { zhd: 0, mh: 0, mw: 0, gradient: 0 };
3404
3544
  const { zhd, mh, mw } = trop;
3405
3545
  epochZhd = zhd;
3406
3546
  const geom = {
@@ -3425,7 +3565,7 @@ var PppEngine = class {
3425
3565
  lIf,
3426
3566
  satClkM: sat.state.clkM,
3427
3567
  range,
3428
- tropoFixed: zhd * mh + corr.rangeM,
3568
+ tropoFixed: zhd * mh + trop.gradient + corr.rangeM,
3429
3569
  mw,
3430
3570
  windupM: corr.phaseWindupM,
3431
3571
  slip,
@@ -4380,6 +4520,9 @@ export {
4380
4520
  sunEcef,
4381
4521
  moonEcef,
4382
4522
  solidEarthTide,
4523
+ BLQ_CONSTITUENTS,
4524
+ oceanLoadingEnu,
4525
+ parseBlq,
4383
4526
  createPppCorrections,
4384
4527
  Sp3EphemerisSource,
4385
4528
  PppEngine,