gnss-js 1.45.1 → 1.47.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.
@@ -1150,31 +1150,50 @@ function postProcessRtk(base, rover, ephemerides, baseEcef, opts = {}) {
1150
1150
  unmatched++;
1151
1151
  continue;
1152
1152
  }
1153
- const sol = engine.process(
1154
- toRtkEpoch(rEp.meas),
1155
- toRtkEpoch(bEp.meas),
1156
- rEp.timeMs
1157
- );
1158
- if (!sol) continue;
1153
+ let point;
1154
+ if (opts.codeOnly) {
1155
+ const dg = solveDgnss(
1156
+ toRtkEpoch(rEp.meas),
1157
+ toRtkEpoch(bEp.meas),
1158
+ baseEcef,
1159
+ ephemerides,
1160
+ rEp.timeMs,
1161
+ {
1162
+ elevationMaskDeg: opts.elevationMaskDeg,
1163
+ troposphere: opts.troposphere,
1164
+ codeSigmaM: opts.codeSigmaM
1165
+ }
1166
+ );
1167
+ point = dg ? {
1168
+ timeMs: rEp.timeMs,
1169
+ position: dg.position,
1170
+ status: "dgnss",
1171
+ nSats: dg.nSats
1172
+ } : null;
1173
+ } else {
1174
+ const sol = engine.process(
1175
+ toRtkEpoch(rEp.meas),
1176
+ toRtkEpoch(bEp.meas),
1177
+ rEp.timeMs
1178
+ );
1179
+ point = sol ? {
1180
+ timeMs: rEp.timeMs,
1181
+ position: sol.position,
1182
+ status: sol.status,
1183
+ ratio: sol.ratio,
1184
+ nSats: sol.nSats,
1185
+ nFixed: sol.nFixed
1186
+ } : null;
1187
+ }
1188
+ if (!point) continue;
1159
1189
  solved++;
1160
- if (sol.status === "fixed") fixed++;
1190
+ if (point.status === "fixed") fixed++;
1161
1191
  const [lat, lon, height] = ecefToGeodetic(
1162
- sol.position[0],
1163
- sol.position[1],
1164
- sol.position[2]
1192
+ point.position[0],
1193
+ point.position[1],
1194
+ point.position[2]
1165
1195
  );
1166
- track.push({
1167
- timeMs: rEp.timeMs,
1168
- position: sol.position,
1169
- lat,
1170
- lon,
1171
- height,
1172
- enu: enuOf(sol.position),
1173
- status: sol.status,
1174
- ratio: sol.ratio,
1175
- nSats: sol.nSats,
1176
- nFixed: sol.nFixed
1177
- });
1196
+ track.push({ ...point, lat, lon, height, enu: enuOf(point.position) });
1178
1197
  }
1179
1198
  return { track, solved, unmatched, fixRate: solved ? fixed / solved : 0 };
1180
1199
  }
@@ -1810,6 +1829,7 @@ function solvePpp(epochs, sp3, opts) {
1810
1829
  const latRad = latDeg * Math.PI / 180;
1811
1830
  const epochCtx = corrections?.epochContext?.(epoch.timeMs, rcv) ?? null;
1812
1831
  const vis = [];
1832
+ let epochZhd = 0;
1813
1833
  for (const o of epoch.obs) {
1814
1834
  if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
1815
1835
  const slip = detectSlip(o, ei);
@@ -1838,6 +1858,7 @@ function solvePpp(epochs, sp3, opts) {
1838
1858
  if (!Number.isFinite(pIf) || !Number.isFinite(lIf)) continue;
1839
1859
  const trop = opts.troposphere ?? true ? niellMapping(elRad, latRad, heightM, epoch.timeMs) : { zhd: 0, mh: 0, mw: 0 };
1840
1860
  const { zhd, mh, mw } = trop;
1861
+ epochZhd = zhd;
1841
1862
  const geom = {
1842
1863
  prn: o.prn,
1843
1864
  satEcef: [sat.state.x, sat.state.y, sat.state.z],
@@ -2035,6 +2056,7 @@ function solvePpp(epochs, sp3, opts) {
2035
2056
  position: pos,
2036
2057
  nSats,
2037
2058
  ztdWet: x[IDX_ZWD],
2059
+ ztdHydrostatic: epochZhd,
2038
2060
  phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0
2039
2061
  });
2040
2062
  }
@@ -2073,6 +2095,7 @@ function solvePpp(epochs, sp3, opts) {
2073
2095
  llh,
2074
2096
  series,
2075
2097
  ztdWet: x[IDX_ZWD],
2098
+ ztdHydrostatic: series.length ? series[series.length - 1].ztdHydrostatic : 0,
2076
2099
  epochsUsed: epochs.length,
2077
2100
  convergenceSec,
2078
2101
  finalError3d,
package/dist/index.cjs CHANGED
@@ -13083,31 +13083,50 @@ function postProcessRtk(base, rover, ephemerides, baseEcef, opts = {}) {
13083
13083
  unmatched++;
13084
13084
  continue;
13085
13085
  }
13086
- const sol = engine.process(
13087
- toRtkEpoch(rEp.meas),
13088
- toRtkEpoch(bEp.meas),
13089
- rEp.timeMs
13090
- );
13091
- if (!sol) continue;
13086
+ let point;
13087
+ if (opts.codeOnly) {
13088
+ const dg = solveDgnss(
13089
+ toRtkEpoch(rEp.meas),
13090
+ toRtkEpoch(bEp.meas),
13091
+ baseEcef,
13092
+ ephemerides,
13093
+ rEp.timeMs,
13094
+ {
13095
+ elevationMaskDeg: opts.elevationMaskDeg,
13096
+ troposphere: opts.troposphere,
13097
+ codeSigmaM: opts.codeSigmaM
13098
+ }
13099
+ );
13100
+ point = dg ? {
13101
+ timeMs: rEp.timeMs,
13102
+ position: dg.position,
13103
+ status: "dgnss",
13104
+ nSats: dg.nSats
13105
+ } : null;
13106
+ } else {
13107
+ const sol = engine.process(
13108
+ toRtkEpoch(rEp.meas),
13109
+ toRtkEpoch(bEp.meas),
13110
+ rEp.timeMs
13111
+ );
13112
+ point = sol ? {
13113
+ timeMs: rEp.timeMs,
13114
+ position: sol.position,
13115
+ status: sol.status,
13116
+ ratio: sol.ratio,
13117
+ nSats: sol.nSats,
13118
+ nFixed: sol.nFixed
13119
+ } : null;
13120
+ }
13121
+ if (!point) continue;
13092
13122
  solved++;
13093
- if (sol.status === "fixed") fixed++;
13123
+ if (point.status === "fixed") fixed++;
13094
13124
  const [lat, lon, height] = ecefToGeodetic(
13095
- sol.position[0],
13096
- sol.position[1],
13097
- sol.position[2]
13125
+ point.position[0],
13126
+ point.position[1],
13127
+ point.position[2]
13098
13128
  );
13099
- track.push({
13100
- timeMs: rEp.timeMs,
13101
- position: sol.position,
13102
- lat,
13103
- lon,
13104
- height,
13105
- enu: enuOf(sol.position),
13106
- status: sol.status,
13107
- ratio: sol.ratio,
13108
- nSats: sol.nSats,
13109
- nFixed: sol.nFixed
13110
- });
13129
+ track.push({ ...point, lat, lon, height, enu: enuOf(point.position) });
13111
13130
  }
13112
13131
  return { track, solved, unmatched, fixRate: solved ? fixed / solved : 0 };
13113
13132
  }
@@ -13743,6 +13762,7 @@ function solvePpp(epochs, sp3, opts) {
13743
13762
  const latRad = latDeg * Math.PI / 180;
13744
13763
  const epochCtx = corrections?.epochContext?.(epoch.timeMs, rcv) ?? null;
13745
13764
  const vis = [];
13765
+ let epochZhd = 0;
13746
13766
  for (const o of epoch.obs) {
13747
13767
  if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
13748
13768
  const slip = detectSlip(o, ei);
@@ -13771,6 +13791,7 @@ function solvePpp(epochs, sp3, opts) {
13771
13791
  if (!Number.isFinite(pIf) || !Number.isFinite(lIf)) continue;
13772
13792
  const trop = opts.troposphere ?? true ? niellMapping(elRad, latRad, heightM, epoch.timeMs) : { zhd: 0, mh: 0, mw: 0 };
13773
13793
  const { zhd, mh, mw } = trop;
13794
+ epochZhd = zhd;
13774
13795
  const geom = {
13775
13796
  prn: o.prn,
13776
13797
  satEcef: [sat.state.x, sat.state.y, sat.state.z],
@@ -13968,6 +13989,7 @@ function solvePpp(epochs, sp3, opts) {
13968
13989
  position: pos,
13969
13990
  nSats,
13970
13991
  ztdWet: x[IDX_ZWD],
13992
+ ztdHydrostatic: epochZhd,
13971
13993
  phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0
13972
13994
  });
13973
13995
  }
@@ -14006,6 +14028,7 @@ function solvePpp(epochs, sp3, opts) {
14006
14028
  llh,
14007
14029
  series,
14008
14030
  ztdWet: x[IDX_ZWD],
14031
+ ztdHydrostatic: series.length ? series[series.length - 1].ztdHydrostatic : 0,
14009
14032
  epochsUsed: epochs.length,
14010
14033
  convergenceSec,
14011
14034
  finalError3d,
package/dist/index.js CHANGED
@@ -164,7 +164,7 @@ import {
164
164
  sunEcef,
165
165
  toRtkEpoch,
166
166
  wlWavelength
167
- } from "./chunk-ST22ULND.js";
167
+ } from "./chunk-75OYCNTY.js";
168
168
  import {
169
169
  almanacEpochMs,
170
170
  almanacSatPosition,
@@ -1606,31 +1606,50 @@ function postProcessRtk(base, rover, ephemerides, baseEcef, opts = {}) {
1606
1606
  unmatched++;
1607
1607
  continue;
1608
1608
  }
1609
- const sol = engine.process(
1610
- toRtkEpoch(rEp.meas),
1611
- toRtkEpoch(bEp.meas),
1612
- rEp.timeMs
1613
- );
1614
- if (!sol) continue;
1609
+ let point;
1610
+ if (opts.codeOnly) {
1611
+ const dg = solveDgnss(
1612
+ toRtkEpoch(rEp.meas),
1613
+ toRtkEpoch(bEp.meas),
1614
+ baseEcef,
1615
+ ephemerides,
1616
+ rEp.timeMs,
1617
+ {
1618
+ elevationMaskDeg: opts.elevationMaskDeg,
1619
+ troposphere: opts.troposphere,
1620
+ codeSigmaM: opts.codeSigmaM
1621
+ }
1622
+ );
1623
+ point = dg ? {
1624
+ timeMs: rEp.timeMs,
1625
+ position: dg.position,
1626
+ status: "dgnss",
1627
+ nSats: dg.nSats
1628
+ } : null;
1629
+ } else {
1630
+ const sol = engine.process(
1631
+ toRtkEpoch(rEp.meas),
1632
+ toRtkEpoch(bEp.meas),
1633
+ rEp.timeMs
1634
+ );
1635
+ point = sol ? {
1636
+ timeMs: rEp.timeMs,
1637
+ position: sol.position,
1638
+ status: sol.status,
1639
+ ratio: sol.ratio,
1640
+ nSats: sol.nSats,
1641
+ nFixed: sol.nFixed
1642
+ } : null;
1643
+ }
1644
+ if (!point) continue;
1615
1645
  solved++;
1616
- if (sol.status === "fixed") fixed++;
1646
+ if (point.status === "fixed") fixed++;
1617
1647
  const [lat, lon, height] = ecefToGeodetic(
1618
- sol.position[0],
1619
- sol.position[1],
1620
- sol.position[2]
1648
+ point.position[0],
1649
+ point.position[1],
1650
+ point.position[2]
1621
1651
  );
1622
- track.push({
1623
- timeMs: rEp.timeMs,
1624
- position: sol.position,
1625
- lat,
1626
- lon,
1627
- height,
1628
- enu: enuOf(sol.position),
1629
- status: sol.status,
1630
- ratio: sol.ratio,
1631
- nSats: sol.nSats,
1632
- nFixed: sol.nFixed
1633
- });
1652
+ track.push({ ...point, lat, lon, height, enu: enuOf(point.position) });
1634
1653
  }
1635
1654
  return { track, solved, unmatched, fixRate: solved ? fixed / solved : 0 };
1636
1655
  }
@@ -2338,6 +2357,7 @@ function solvePpp(epochs, sp3, opts) {
2338
2357
  const latRad = latDeg * Math.PI / 180;
2339
2358
  const epochCtx = corrections?.epochContext?.(epoch.timeMs, rcv) ?? null;
2340
2359
  const vis = [];
2360
+ let epochZhd = 0;
2341
2361
  for (const o of epoch.obs) {
2342
2362
  if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
2343
2363
  const slip = detectSlip(o, ei);
@@ -2366,6 +2386,7 @@ function solvePpp(epochs, sp3, opts) {
2366
2386
  if (!Number.isFinite(pIf) || !Number.isFinite(lIf)) continue;
2367
2387
  const trop = opts.troposphere ?? true ? niellMapping(elRad, latRad, heightM, epoch.timeMs) : { zhd: 0, mh: 0, mw: 0 };
2368
2388
  const { zhd, mh, mw } = trop;
2389
+ epochZhd = zhd;
2369
2390
  const geom = {
2370
2391
  prn: o.prn,
2371
2392
  satEcef: [sat.state.x, sat.state.y, sat.state.z],
@@ -2563,6 +2584,7 @@ function solvePpp(epochs, sp3, opts) {
2563
2584
  position: pos,
2564
2585
  nSats,
2565
2586
  ztdWet: x[IDX_ZWD],
2587
+ ztdHydrostatic: epochZhd,
2566
2588
  phaseResRms: nPhaseRes > 0 ? Math.sqrt(sumPhaseResSq / nPhaseRes) : 0
2567
2589
  });
2568
2590
  }
@@ -2601,6 +2623,7 @@ function solvePpp(epochs, sp3, opts) {
2601
2623
  llh,
2602
2624
  series,
2603
2625
  ztdWet: x[IDX_ZWD],
2626
+ ztdHydrostatic: series.length ? series[series.length - 1].ztdHydrostatic : 0,
2604
2627
  epochsUsed: epochs.length,
2605
2628
  convergenceSec,
2606
2629
  finalError3d,
@@ -437,6 +437,14 @@ interface RtkPostProcessOptions extends RtkFloatOptions {
437
437
  * mainly rejects a base gap rather than sub-second offsets.
438
438
  */
439
439
  pairToleranceMs?: number;
440
+ /**
441
+ * Code-only differential (DGNSS): solve each epoch from double-differenced
442
+ * pseudoranges via {@link solveDgnss} instead of the carrier-phase float
443
+ * engine. Every epoch is independent (no filter), so there is no ambiguity
444
+ * fixing — a robust metre→sub-metre fallback that needs no carrier phase.
445
+ * Track points come back with `status: 'dgnss'`. Default false.
446
+ */
447
+ codeOnly?: boolean;
440
448
  }
441
449
  interface RtkPostProcessResult {
442
450
  /** Solved rover epochs in time order. */
@@ -711,6 +719,8 @@ interface PppEpochResult {
711
719
  nSats: number;
712
720
  /** Estimated zenith wet delay (m). */
713
721
  ztdWet: number;
722
+ /** A priori zenith hydrostatic delay (m, Saastamoinen). ZTD = this + ztdWet. */
723
+ ztdHydrostatic: number;
714
724
  /** RMS of post-fit phase residuals this epoch (m). */
715
725
  phaseResRms: number;
716
726
  }
@@ -723,6 +733,8 @@ interface PppSolution {
723
733
  series: PppEpochResult[];
724
734
  /** Estimated zenith wet delay at the end (m). */
725
735
  ztdWet: number;
736
+ /** A priori zenith hydrostatic delay at the end (m). ZTD = this + ztdWet. */
737
+ ztdHydrostatic: number;
726
738
  /** Epochs processed. */
727
739
  epochsUsed: number;
728
740
  /** Seconds from first epoch until 3D error first stays < 0.1 m
@@ -437,6 +437,14 @@ interface RtkPostProcessOptions extends RtkFloatOptions {
437
437
  * mainly rejects a base gap rather than sub-second offsets.
438
438
  */
439
439
  pairToleranceMs?: number;
440
+ /**
441
+ * Code-only differential (DGNSS): solve each epoch from double-differenced
442
+ * pseudoranges via {@link solveDgnss} instead of the carrier-phase float
443
+ * engine. Every epoch is independent (no filter), so there is no ambiguity
444
+ * fixing — a robust metre→sub-metre fallback that needs no carrier phase.
445
+ * Track points come back with `status: 'dgnss'`. Default false.
446
+ */
447
+ codeOnly?: boolean;
440
448
  }
441
449
  interface RtkPostProcessResult {
442
450
  /** Solved rover epochs in time order. */
@@ -711,6 +719,8 @@ interface PppEpochResult {
711
719
  nSats: number;
712
720
  /** Estimated zenith wet delay (m). */
713
721
  ztdWet: number;
722
+ /** A priori zenith hydrostatic delay (m, Saastamoinen). ZTD = this + ztdWet. */
723
+ ztdHydrostatic: number;
714
724
  /** RMS of post-fit phase residuals this epoch (m). */
715
725
  phaseResRms: number;
716
726
  }
@@ -723,6 +733,8 @@ interface PppSolution {
723
733
  series: PppEpochResult[];
724
734
  /** Estimated zenith wet delay at the end (m). */
725
735
  ztdWet: number;
736
+ /** A priori zenith hydrostatic delay at the end (m). ZTD = this + ztdWet. */
737
+ ztdHydrostatic: number;
726
738
  /** Epochs processed. */
727
739
  epochsUsed: number;
728
740
  /** 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-ST22ULND.js";
31
+ } from "./chunk-75OYCNTY.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.1",
3
+ "version": "1.47.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,