gnss-js 1.45.0 → 1.46.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.
@@ -1102,12 +1102,23 @@ var RtkFloatEngine = class {
1102
1102
 
1103
1103
  // src/positioning/rtk-postprocess.ts
1104
1104
  var epochsOf = (o) => Array.isArray(o) ? o : o.epochs;
1105
+ function medianIntervalMs(epochs) {
1106
+ const times = [...new Set(epochs.map((e) => e.timeMs))].sort((a, b) => a - b);
1107
+ if (times.length < 2) return null;
1108
+ const gaps = [];
1109
+ for (let i = 1; i < times.length; i++) gaps.push(times[i] - times[i - 1]);
1110
+ gaps.sort((a, b) => a - b);
1111
+ return gaps[Math.floor(gaps.length / 2)];
1112
+ }
1105
1113
  function postProcessRtk(base, rover, ephemerides, baseEcef, opts = {}) {
1106
1114
  const tol = opts.pairToleranceMs ?? 500;
1107
1115
  const round = (ms) => Math.round(ms / 1e3) * 1e3;
1116
+ const roverEpochs = epochsOf(rover);
1117
+ const interval = medianIntervalMs(roverEpochs);
1118
+ const engineOpts = opts.maxGapMs != null || interval == null ? opts : { ...opts, maxGapMs: Math.max(1e4, Math.round(interval * 2.5)) };
1108
1119
  const baseByT = /* @__PURE__ */ new Map();
1109
1120
  for (const e of epochsOf(base)) baseByT.set(round(e.timeMs), e);
1110
- const engine = new RtkFloatEngine(baseEcef, ephemerides, opts);
1121
+ const engine = new RtkFloatEngine(baseEcef, ephemerides, engineOpts);
1111
1122
  const [bLat, bLon] = ecefToGeodetic(baseEcef[0], baseEcef[1], baseEcef[2]);
1112
1123
  const [sLat, cLat, sLon, cLon] = [
1113
1124
  Math.sin(bLat),
@@ -1130,7 +1141,7 @@ function postProcessRtk(base, rover, ephemerides, baseEcef, opts = {}) {
1130
1141
  let solved = 0;
1131
1142
  let unmatched = 0;
1132
1143
  let fixed = 0;
1133
- const sorted = [...epochsOf(rover)].sort((a, b) => a.timeMs - b.timeMs);
1144
+ const sorted = [...roverEpochs].sort((a, b) => a.timeMs - b.timeMs);
1134
1145
  for (const rEp of sorted) {
1135
1146
  if (seen.has(rEp.timeMs)) continue;
1136
1147
  seen.add(rEp.timeMs);
@@ -1799,6 +1810,7 @@ function solvePpp(epochs, sp3, opts) {
1799
1810
  const latRad = latDeg * Math.PI / 180;
1800
1811
  const epochCtx = corrections?.epochContext?.(epoch.timeMs, rcv) ?? null;
1801
1812
  const vis = [];
1813
+ let epochZhd = 0;
1802
1814
  for (const o of epoch.obs) {
1803
1815
  if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
1804
1816
  const slip = detectSlip(o, ei);
@@ -1827,6 +1839,7 @@ function solvePpp(epochs, sp3, opts) {
1827
1839
  if (!Number.isFinite(pIf) || !Number.isFinite(lIf)) continue;
1828
1840
  const trop = opts.troposphere ?? true ? niellMapping(elRad, latRad, heightM, epoch.timeMs) : { zhd: 0, mh: 0, mw: 0 };
1829
1841
  const { zhd, mh, mw } = trop;
1842
+ epochZhd = zhd;
1830
1843
  const geom = {
1831
1844
  prn: o.prn,
1832
1845
  satEcef: [sat.state.x, sat.state.y, sat.state.z],
@@ -2024,6 +2037,7 @@ function solvePpp(epochs, sp3, opts) {
2024
2037
  position: pos,
2025
2038
  nSats,
2026
2039
  ztdWet: x[IDX_ZWD],
2040
+ ztdHydrostatic: epochZhd,
2027
2041
  phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0
2028
2042
  });
2029
2043
  }
@@ -2062,6 +2076,7 @@ function solvePpp(epochs, sp3, opts) {
2062
2076
  llh,
2063
2077
  series,
2064
2078
  ztdWet: x[IDX_ZWD],
2079
+ ztdHydrostatic: series.length ? series[series.length - 1].ztdHydrostatic : 0,
2065
2080
  epochsUsed: epochs.length,
2066
2081
  convergenceSec,
2067
2082
  finalError3d,
package/dist/index.cjs CHANGED
@@ -13035,12 +13035,23 @@ var RtkFloatEngine = class {
13035
13035
 
13036
13036
  // src/positioning/rtk-postprocess.ts
13037
13037
  var epochsOf = (o) => Array.isArray(o) ? o : o.epochs;
13038
+ function medianIntervalMs(epochs) {
13039
+ const times = [...new Set(epochs.map((e) => e.timeMs))].sort((a, b) => a - b);
13040
+ if (times.length < 2) return null;
13041
+ const gaps = [];
13042
+ for (let i = 1; i < times.length; i++) gaps.push(times[i] - times[i - 1]);
13043
+ gaps.sort((a, b) => a - b);
13044
+ return gaps[Math.floor(gaps.length / 2)];
13045
+ }
13038
13046
  function postProcessRtk(base, rover, ephemerides, baseEcef, opts = {}) {
13039
13047
  const tol = opts.pairToleranceMs ?? 500;
13040
13048
  const round = (ms) => Math.round(ms / 1e3) * 1e3;
13049
+ const roverEpochs = epochsOf(rover);
13050
+ const interval = medianIntervalMs(roverEpochs);
13051
+ const engineOpts = opts.maxGapMs != null || interval == null ? opts : { ...opts, maxGapMs: Math.max(1e4, Math.round(interval * 2.5)) };
13041
13052
  const baseByT = /* @__PURE__ */ new Map();
13042
13053
  for (const e of epochsOf(base)) baseByT.set(round(e.timeMs), e);
13043
- const engine = new RtkFloatEngine(baseEcef, ephemerides, opts);
13054
+ const engine = new RtkFloatEngine(baseEcef, ephemerides, engineOpts);
13044
13055
  const [bLat, bLon] = ecefToGeodetic(baseEcef[0], baseEcef[1], baseEcef[2]);
13045
13056
  const [sLat, cLat, sLon, cLon] = [
13046
13057
  Math.sin(bLat),
@@ -13063,7 +13074,7 @@ function postProcessRtk(base, rover, ephemerides, baseEcef, opts = {}) {
13063
13074
  let solved = 0;
13064
13075
  let unmatched = 0;
13065
13076
  let fixed = 0;
13066
- const sorted = [...epochsOf(rover)].sort((a, b) => a.timeMs - b.timeMs);
13077
+ const sorted = [...roverEpochs].sort((a, b) => a.timeMs - b.timeMs);
13067
13078
  for (const rEp of sorted) {
13068
13079
  if (seen.has(rEp.timeMs)) continue;
13069
13080
  seen.add(rEp.timeMs);
@@ -13732,6 +13743,7 @@ function solvePpp(epochs, sp3, opts) {
13732
13743
  const latRad = latDeg * Math.PI / 180;
13733
13744
  const epochCtx = corrections?.epochContext?.(epoch.timeMs, rcv) ?? null;
13734
13745
  const vis = [];
13746
+ let epochZhd = 0;
13735
13747
  for (const o of epoch.obs) {
13736
13748
  if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
13737
13749
  const slip = detectSlip(o, ei);
@@ -13760,6 +13772,7 @@ function solvePpp(epochs, sp3, opts) {
13760
13772
  if (!Number.isFinite(pIf) || !Number.isFinite(lIf)) continue;
13761
13773
  const trop = opts.troposphere ?? true ? niellMapping(elRad, latRad, heightM, epoch.timeMs) : { zhd: 0, mh: 0, mw: 0 };
13762
13774
  const { zhd, mh, mw } = trop;
13775
+ epochZhd = zhd;
13763
13776
  const geom = {
13764
13777
  prn: o.prn,
13765
13778
  satEcef: [sat.state.x, sat.state.y, sat.state.z],
@@ -13957,6 +13970,7 @@ function solvePpp(epochs, sp3, opts) {
13957
13970
  position: pos,
13958
13971
  nSats,
13959
13972
  ztdWet: x[IDX_ZWD],
13973
+ ztdHydrostatic: epochZhd,
13960
13974
  phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0
13961
13975
  });
13962
13976
  }
@@ -13995,6 +14009,7 @@ function solvePpp(epochs, sp3, opts) {
13995
14009
  llh,
13996
14010
  series,
13997
14011
  ztdWet: x[IDX_ZWD],
14012
+ ztdHydrostatic: series.length ? series[series.length - 1].ztdHydrostatic : 0,
13998
14013
  epochsUsed: epochs.length,
13999
14014
  convergenceSec,
14000
14015
  finalError3d,
package/dist/index.js CHANGED
@@ -164,7 +164,7 @@ import {
164
164
  sunEcef,
165
165
  toRtkEpoch,
166
166
  wlWavelength
167
- } from "./chunk-XYCECWWS.js";
167
+ } from "./chunk-VNDMPBKK.js";
168
168
  import {
169
169
  almanacEpochMs,
170
170
  almanacSatPosition,
@@ -1558,12 +1558,23 @@ var RtkFloatEngine = class {
1558
1558
 
1559
1559
  // src/positioning/rtk-postprocess.ts
1560
1560
  var epochsOf = (o) => Array.isArray(o) ? o : o.epochs;
1561
+ function medianIntervalMs(epochs) {
1562
+ const times = [...new Set(epochs.map((e) => e.timeMs))].sort((a, b) => a - b);
1563
+ if (times.length < 2) return null;
1564
+ const gaps = [];
1565
+ for (let i = 1; i < times.length; i++) gaps.push(times[i] - times[i - 1]);
1566
+ gaps.sort((a, b) => a - b);
1567
+ return gaps[Math.floor(gaps.length / 2)];
1568
+ }
1561
1569
  function postProcessRtk(base, rover, ephemerides, baseEcef, opts = {}) {
1562
1570
  const tol = opts.pairToleranceMs ?? 500;
1563
1571
  const round = (ms) => Math.round(ms / 1e3) * 1e3;
1572
+ const roverEpochs = epochsOf(rover);
1573
+ const interval = medianIntervalMs(roverEpochs);
1574
+ const engineOpts = opts.maxGapMs != null || interval == null ? opts : { ...opts, maxGapMs: Math.max(1e4, Math.round(interval * 2.5)) };
1564
1575
  const baseByT = /* @__PURE__ */ new Map();
1565
1576
  for (const e of epochsOf(base)) baseByT.set(round(e.timeMs), e);
1566
- const engine = new RtkFloatEngine(baseEcef, ephemerides, opts);
1577
+ const engine = new RtkFloatEngine(baseEcef, ephemerides, engineOpts);
1567
1578
  const [bLat, bLon] = ecefToGeodetic(baseEcef[0], baseEcef[1], baseEcef[2]);
1568
1579
  const [sLat, cLat, sLon, cLon] = [
1569
1580
  Math.sin(bLat),
@@ -1586,7 +1597,7 @@ function postProcessRtk(base, rover, ephemerides, baseEcef, opts = {}) {
1586
1597
  let solved = 0;
1587
1598
  let unmatched = 0;
1588
1599
  let fixed = 0;
1589
- const sorted = [...epochsOf(rover)].sort((a, b) => a.timeMs - b.timeMs);
1600
+ const sorted = [...roverEpochs].sort((a, b) => a.timeMs - b.timeMs);
1590
1601
  for (const rEp of sorted) {
1591
1602
  if (seen.has(rEp.timeMs)) continue;
1592
1603
  seen.add(rEp.timeMs);
@@ -2327,6 +2338,7 @@ function solvePpp(epochs, sp3, opts) {
2327
2338
  const latRad = latDeg * Math.PI / 180;
2328
2339
  const epochCtx = corrections?.epochContext?.(epoch.timeMs, rcv) ?? null;
2329
2340
  const vis = [];
2341
+ let epochZhd = 0;
2330
2342
  for (const o of epoch.obs) {
2331
2343
  if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
2332
2344
  const slip = detectSlip(o, ei);
@@ -2355,6 +2367,7 @@ function solvePpp(epochs, sp3, opts) {
2355
2367
  if (!Number.isFinite(pIf) || !Number.isFinite(lIf)) continue;
2356
2368
  const trop = opts.troposphere ?? true ? niellMapping(elRad, latRad, heightM, epoch.timeMs) : { zhd: 0, mh: 0, mw: 0 };
2357
2369
  const { zhd, mh, mw } = trop;
2370
+ epochZhd = zhd;
2358
2371
  const geom = {
2359
2372
  prn: o.prn,
2360
2373
  satEcef: [sat.state.x, sat.state.y, sat.state.z],
@@ -2552,6 +2565,7 @@ function solvePpp(epochs, sp3, opts) {
2552
2565
  position: pos,
2553
2566
  nSats,
2554
2567
  ztdWet: x[IDX_ZWD],
2568
+ ztdHydrostatic: epochZhd,
2555
2569
  phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0
2556
2570
  });
2557
2571
  }
@@ -2590,6 +2604,7 @@ function solvePpp(epochs, sp3, opts) {
2590
2604
  llh,
2591
2605
  series,
2592
2606
  ztdWet: x[IDX_ZWD],
2607
+ ztdHydrostatic: series.length ? series[series.length - 1].ztdHydrostatic : 0,
2593
2608
  epochsUsed: epochs.length,
2594
2609
  convergenceSec,
2595
2610
  finalError3d,
@@ -711,6 +711,8 @@ interface PppEpochResult {
711
711
  nSats: number;
712
712
  /** Estimated zenith wet delay (m). */
713
713
  ztdWet: number;
714
+ /** A priori zenith hydrostatic delay (m, Saastamoinen). ZTD = this + ztdWet. */
715
+ ztdHydrostatic: number;
714
716
  /** RMS of post-fit phase residuals this epoch (m). */
715
717
  phaseResRms: number;
716
718
  }
@@ -723,6 +725,8 @@ interface PppSolution {
723
725
  series: PppEpochResult[];
724
726
  /** Estimated zenith wet delay at the end (m). */
725
727
  ztdWet: number;
728
+ /** A priori zenith hydrostatic delay at the end (m). ZTD = this + ztdWet. */
729
+ ztdHydrostatic: number;
726
730
  /** Epochs processed. */
727
731
  epochsUsed: number;
728
732
  /** Seconds from first epoch until 3D error first stays < 0.1 m
@@ -711,6 +711,8 @@ interface PppEpochResult {
711
711
  nSats: number;
712
712
  /** Estimated zenith wet delay (m). */
713
713
  ztdWet: number;
714
+ /** A priori zenith hydrostatic delay (m, Saastamoinen). ZTD = this + ztdWet. */
715
+ ztdHydrostatic: number;
714
716
  /** RMS of post-fit phase residuals this epoch (m). */
715
717
  phaseResRms: number;
716
718
  }
@@ -723,6 +725,8 @@ interface PppSolution {
723
725
  series: PppEpochResult[];
724
726
  /** Estimated zenith wet delay at the end (m). */
725
727
  ztdWet: number;
728
+ /** A priori zenith hydrostatic delay at the end (m). ZTD = this + ztdWet. */
729
+ ztdHydrostatic: number;
726
730
  /** Epochs processed. */
727
731
  epochsUsed: number;
728
732
  /** Seconds from first epoch until 3D error first stays < 0.1 m
@@ -28,7 +28,7 @@ import {
28
28
  sunEcef,
29
29
  toRtkEpoch,
30
30
  wlWavelength
31
- } from "./chunk-XYCECWWS.js";
31
+ } from "./chunk-VNDMPBKK.js";
32
32
  import "./chunk-MHGNKSSH.js";
33
33
  import "./chunk-MIIM4LDY.js";
34
34
  import "./chunk-37QNKGTC.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gnss-js",
3
- "version": "1.45.0",
3
+ "version": "1.46.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,