gnss-js 1.29.0 → 1.31.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/index.cjs CHANGED
@@ -111,6 +111,7 @@ __export(src_exports, {
111
111
  analyzeQuality: () => analyzeQuality,
112
112
  applyHelmert: () => applyHelmert,
113
113
  applyIonoDcb: () => applyIonoDcb,
114
+ biasMetres: () => biasMetres,
114
115
  binexCrc16: () => binexCrc16,
115
116
  binexCrc32: () => binexCrc32,
116
117
  binexCsum8: () => binexCsum8,
@@ -119,6 +120,7 @@ __export(src_exports, {
119
120
  buildObsIndices: () => buildObsIndices,
120
121
  buildPppAntenna: () => buildPppAntenna,
121
122
  clampUnit: () => clampUnit,
123
+ clkBias: () => clkBias,
122
124
  computeAllPositions: () => computeAllPositions,
123
125
  computeDop: () => computeDop,
124
126
  computeIonoRate: () => computeIonoRate,
@@ -149,6 +151,7 @@ __export(src_exports, {
149
151
  ephInfoToEphemeris: () => ephInfoToEphemeris,
150
152
  euclidean3D: () => euclidean3D,
151
153
  fetchSourcetable: () => fetchSourcetable,
154
+ findSatBias: () => findSatBias,
152
155
  fmtD: () => fmtD,
153
156
  fmtF: () => fmtF,
154
157
  formatUTCTime: () => formatUTCTime,
@@ -231,12 +234,15 @@ __export(src_exports, {
231
234
  msmEpochToDate: () => msmEpochToDate,
232
235
  navTimesFromEph: () => navTimesFromEph,
233
236
  niellMapping: () => niellMapping,
237
+ nlWavelength: () => nlWavelength,
234
238
  nmeaCoordToDecimal: () => nmeaCoordToDecimal,
235
239
  oem4Frames: () => oem4Frames,
236
240
  padL: () => padL,
237
241
  padR: () => padR,
238
242
  parseAntex: () => parseAntex,
243
+ parseBiasSinex: () => parseBiasSinex,
239
244
  parseBinex: () => parseBinex,
245
+ parseClk: () => parseClk,
240
246
  parseCrxDataLine: () => parseCrxDataLine,
241
247
  parseIonex: () => parseIonex,
242
248
  parseNavFile: () => parseNavFile,
@@ -272,6 +278,7 @@ __export(src_exports, {
272
278
  readString: () => readString,
273
279
  reportDecodeError: () => reportDecodeError,
274
280
  resetGloFreqCache: () => resetGloFreqCache,
281
+ resolvePppAmbiguities: () => resolvePppAmbiguities,
275
282
  rhumbLine: () => rhumbLine,
276
283
  rtcm3Constellation: () => rtcm3Constellation,
277
284
  satClockCorrection: () => satClockCorrection,
@@ -297,6 +304,7 @@ __export(src_exports, {
297
304
  updateStreamStats: () => updateStreamStats,
298
305
  verifyChecksum: () => verifyChecksum,
299
306
  vincenty: () => vincenty,
307
+ wlWavelength: () => wlWavelength,
300
308
  writeCrx: () => writeCrx,
301
309
  writeModernObsBlob: () => writeModernObsBlob,
302
310
  writeRinex2ObsBlob: () => writeRinex2ObsBlob,
@@ -3896,6 +3904,141 @@ function sp3Position(sp3, prn, tMs, order = 9) {
3896
3904
  return { x, y, z, clk };
3897
3905
  }
3898
3906
 
3907
+ // src/rinex/clk.ts
3908
+ var GPS_EPOCH_MS4 = Date.UTC(1980, 0, 6);
3909
+ function parseClk(text) {
3910
+ const sats = {};
3911
+ let inData = false;
3912
+ for (const line of text.split("\n")) {
3913
+ if (!inData) {
3914
+ if (line.includes("END OF HEADER")) inData = true;
3915
+ continue;
3916
+ }
3917
+ if (line.length < 3 || line[0] !== "A" || line[1] !== "S") continue;
3918
+ const p = line.slice(2).trim().split(/\s+/);
3919
+ if (p.length < 9) continue;
3920
+ const prn = p[0];
3921
+ const y = +p[1];
3922
+ const mo = +p[2];
3923
+ const d = +p[3];
3924
+ const h = +p[4];
3925
+ const mi = +p[5];
3926
+ const s = +p[6];
3927
+ const bias = +p[8];
3928
+ if (!Number.isFinite(bias)) continue;
3929
+ const t = Date.UTC(y, mo - 1, d, h, mi, Math.floor(s)) + s % 1 * 1e3;
3930
+ let e = sats[prn];
3931
+ if (!e) {
3932
+ e = { t: [], c: [] };
3933
+ sats[prn] = e;
3934
+ }
3935
+ e.t.push(t);
3936
+ e.c.push(bias);
3937
+ }
3938
+ let intervalSec = 30;
3939
+ for (const e of Object.values(sats)) {
3940
+ if (e.t.length >= 2) {
3941
+ intervalSec = Math.round((e.t[1] - e.t[0]) / 1e3);
3942
+ break;
3943
+ }
3944
+ }
3945
+ return { sats, intervalSec };
3946
+ }
3947
+ function clkBias(clk, prn, tMs) {
3948
+ const e = clk.sats[prn];
3949
+ if (!e || e.t.length === 0) return null;
3950
+ const { t, c } = e;
3951
+ let lo = 0;
3952
+ let hi = t.length - 1;
3953
+ if (tMs < t[0] || tMs > t[hi]) return null;
3954
+ while (lo < hi) {
3955
+ const mid = lo + hi + 1 >> 1;
3956
+ if (t[mid] <= tMs) lo = mid;
3957
+ else hi = mid - 1;
3958
+ }
3959
+ if (t[lo] === tMs || lo === t.length - 1) return c[lo];
3960
+ const t0 = t[lo];
3961
+ const t1 = t[lo + 1];
3962
+ if (t1 - t0 > clk.intervalSec * 1e3 * 4) return null;
3963
+ const f = (tMs - t0) / (t1 - t0);
3964
+ return c[lo] + f * (c[lo + 1] - c[lo]);
3965
+ }
3966
+
3967
+ // src/rinex/bias-sinex.ts
3968
+ function parseEpoch(s, openTo) {
3969
+ const m = /^(\d{4}):(\d{3}):(\d{5})$/.exec(s.trim());
3970
+ if (!m) return openTo;
3971
+ const y = +m[1];
3972
+ if (y === 0) return openTo;
3973
+ const doy = +m[2];
3974
+ const sod = +m[3];
3975
+ return Date.UTC(y, 0, 1) + (doy - 1) * 864e5 + sod * 1e3;
3976
+ }
3977
+ function parseBiasSinex(text) {
3978
+ const records = [];
3979
+ let inBlock = false;
3980
+ for (const line of text.split("\n")) {
3981
+ if (line.startsWith("+BIAS/SOLUTION")) {
3982
+ inBlock = true;
3983
+ continue;
3984
+ }
3985
+ if (line.startsWith("-BIAS/SOLUTION")) {
3986
+ inBlock = false;
3987
+ continue;
3988
+ }
3989
+ if (!inBlock || line.length < 65 || line.startsWith("*")) continue;
3990
+ const type = line.slice(1, 4).trim();
3991
+ if (type !== "DSB" && type !== "OSB" && type !== "ISB") continue;
3992
+ const prn = line.slice(11, 14).trim();
3993
+ const station = line.slice(15, 24).trim();
3994
+ const obs1 = line.slice(25, 29).trim();
3995
+ const obs2 = line.slice(30, 34).trim();
3996
+ const startMs = parseEpoch(line.slice(35, 49), -Infinity);
3997
+ const endMs = parseEpoch(line.slice(50, 64), Infinity);
3998
+ const tail = line.slice(65).trim().split(/\s+/);
3999
+ if (tail.length < 2) continue;
4000
+ const unit = tail[0];
4001
+ const value = Number(tail[1]);
4002
+ if (!Number.isFinite(value)) continue;
4003
+ records.push({
4004
+ type,
4005
+ prn,
4006
+ station,
4007
+ obs1,
4008
+ obs2,
4009
+ startMs,
4010
+ endMs,
4011
+ value,
4012
+ unit
4013
+ });
4014
+ }
4015
+ const bySat = /* @__PURE__ */ new Map();
4016
+ for (const r of records) {
4017
+ if (!r.prn || r.station) continue;
4018
+ let a = bySat.get(r.prn);
4019
+ if (!a) {
4020
+ a = [];
4021
+ bySat.set(r.prn, a);
4022
+ }
4023
+ a.push(r);
4024
+ }
4025
+ return { records, bySat };
4026
+ }
4027
+ function biasMetres(r) {
4028
+ return r.unit === "ns" ? r.value * 1e-9 * C_LIGHT : r.value;
4029
+ }
4030
+ function findSatBias(bias, prn, obs1, obs2, tMs) {
4031
+ const recs = bias.bySat.get(prn);
4032
+ if (!recs) return null;
4033
+ for (const r of recs) {
4034
+ if (r.obs1 !== obs1) continue;
4035
+ if (obs2 === void 0 ? r.obs2 !== "" : r.obs2 !== obs2) continue;
4036
+ if (tMs != null && (tMs < r.startMs || tMs > r.endMs)) continue;
4037
+ return r;
4038
+ }
4039
+ return null;
4040
+ }
4041
+
3899
4042
  // src/rinex/obs-writer-common.ts
3900
4043
  function createGzipLineSink() {
3901
4044
  const encoder = new TextEncoder();
@@ -6147,7 +6290,7 @@ var BdsAssembler = class {
6147
6290
  };
6148
6291
 
6149
6292
  // src/navbits/gal.ts
6150
- var GPS_EPOCH_MS4 = Date.UTC(1980, 0, 6);
6293
+ var GPS_EPOCH_MS5 = Date.UTC(1980, 0, 6);
6151
6294
  var SEC_PER_WEEK5 = 7 * 86400;
6152
6295
  var HALF_WEEK3 = 302400;
6153
6296
  var GST_GPS_WEEK_OFFSET = 1024;
@@ -6160,7 +6303,7 @@ function galFnavPageCrcOk(page) {
6160
6303
  return crc24q(page, 214) === getBitU(page, 214, 24);
6161
6304
  }
6162
6305
  function gpsDate2(week, sec) {
6163
- return new Date(GPS_EPOCH_MS4 + (week * SEC_PER_WEEK5 + sec) * 1e3);
6306
+ return new Date(GPS_EPOCH_MS5 + (week * SEC_PER_WEEK5 + sec) * 1e3);
6164
6307
  }
6165
6308
  function weekOfToe(week, tow, toe) {
6166
6309
  if (toe - tow > HALF_WEEK3) return week - 1;
@@ -6455,7 +6598,7 @@ var GalFnavAssembler = class {
6455
6598
  };
6456
6599
 
6457
6600
  // src/navbits/glo.ts
6458
- var GPS_EPOCH_MS5 = Date.UTC(1980, 0, 6);
6601
+ var GPS_EPOCH_MS6 = Date.UTC(1980, 0, 6);
6459
6602
  var SEC_PER_WEEK6 = 7 * 86400;
6460
6603
  var SEC_PER_DAY = 86400;
6461
6604
  var GLO_STRING_BYTES = 10;
@@ -6549,7 +6692,7 @@ function decodeGloStrings(strings, refDate, opts = {}) {
6549
6692
  const slot = getBitU(b, i, 5);
6550
6693
  if (frn1 !== 1 || frn2 !== 2 || frn3 !== 3 || frn4 !== 4) return null;
6551
6694
  if (slot < 1 || slot > 27) return null;
6552
- const utcSec = (getUtcDate(refDate).getTime() - GPS_EPOCH_MS5) / 1e3;
6695
+ const utcSec = (getUtcDate(refDate).getTime() - GPS_EPOCH_MS6) / 1e3;
6553
6696
  const week = Math.floor(utcSec / SEC_PER_WEEK6);
6554
6697
  let tow = utcSec - week * SEC_PER_WEEK6;
6555
6698
  const tod = tow % SEC_PER_DAY;
@@ -6564,7 +6707,7 @@ function decodeGloStrings(strings, refDate, opts = {}) {
6564
6707
  system: "R",
6565
6708
  prn: `R${String(slot).padStart(2, "0")}`,
6566
6709
  // RINEX GLONASS epochs are UTC: build the UTC toe Date directly.
6567
- tocDate: new Date(GPS_EPOCH_MS5 + (week * SEC_PER_WEEK6 + tow + toe) * 1e3),
6710
+ tocDate: new Date(GPS_EPOCH_MS6 + (week * SEC_PER_WEEK6 + tow + toe) * 1e3),
6568
6711
  tauN: -tauN,
6569
6712
  // RINEX stores −τn; the SIS carries τn (ICD sign)
6570
6713
  gammaN,
@@ -6618,7 +6761,7 @@ var GloStringAssembler = class {
6618
6761
  };
6619
6762
 
6620
6763
  // src/ubx/rawnav.ts
6621
- var GPS_EPOCH_MS6 = Date.UTC(1980, 0, 6);
6764
+ var GPS_EPOCH_MS7 = Date.UTC(1980, 0, 6);
6622
6765
  var SEC_PER_WEEK7 = 7 * 86400;
6623
6766
  var two2 = (n) => String(n).padStart(2, "0");
6624
6767
  function parseUbxRawNav(data, opts = {}) {
@@ -6638,7 +6781,7 @@ function parseUbxRawNav(data, opts = {}) {
6638
6781
  if (week === 0 && opts.refWeek !== void 0) week = opts.refWeek;
6639
6782
  if (week > 0) {
6640
6783
  refDate = new Date(
6641
- GPS_EPOCH_MS6 + (week * SEC_PER_WEEK7 + rcvTow) * 1e3
6784
+ GPS_EPOCH_MS7 + (week * SEC_PER_WEEK7 + rcvTow) * 1e3
6642
6785
  );
6643
6786
  }
6644
6787
  continue;
@@ -6718,7 +6861,7 @@ function parseUbxRawNav(data, opts = {}) {
6718
6861
  }
6719
6862
 
6720
6863
  // src/ubx/index.ts
6721
- var GPS_EPOCH_MS7 = Date.UTC(1980, 0, 6);
6864
+ var GPS_EPOCH_MS8 = Date.UTC(1980, 0, 6);
6722
6865
  var MS_PER_WEEK3 = 7 * 864e5;
6723
6866
  var SIGNALS = {
6724
6867
  0: { 0: ["G", "1C"], 3: ["G", "2X"], 4: ["G", "2X"] },
@@ -6801,7 +6944,7 @@ function parseUbxRawx(data) {
6801
6944
  if (!codes.includes(sig[1])) codes.push(sig[1]);
6802
6945
  }
6803
6946
  epochs.push({
6804
- timeMs: GPS_EPOCH_MS7 + week * MS_PER_WEEK3 + Math.round(rcvTow * 1e3),
6947
+ timeMs: GPS_EPOCH_MS8 + week * MS_PER_WEEK3 + Math.round(rcvTow * 1e3),
6805
6948
  leapS: leapValid ? leapS : null,
6806
6949
  meas
6807
6950
  });
@@ -6872,7 +7015,7 @@ function svidToPrn(svid) {
6872
7015
 
6873
7016
  // src/sbf/nav.ts
6874
7017
  var PI2 = Math.PI;
6875
- var GPS_EPOCH_MS8 = Date.UTC(1980, 0, 6);
7018
+ var GPS_EPOCH_MS9 = Date.UTC(1980, 0, 6);
6876
7019
  var BDT_EPOCH_MS2 = Date.UTC(2006, 0, 1);
6877
7020
  var SEC_PER_WEEK8 = 7 * 86400;
6878
7021
  var MS_PER_WEEK4 = SEC_PER_WEEK8 * 1e3;
@@ -6884,7 +7027,7 @@ function adjustWeek(refWeek, wn, mod) {
6884
7027
  if (offset < -(mod / 2 - 1)) offset += mod;
6885
7028
  return refWeek - offset;
6886
7029
  }
6887
- var gpsMs = (week, sec) => GPS_EPOCH_MS8 + week * MS_PER_WEEK4 + sec * 1e3;
7030
+ var gpsMs = (week, sec) => GPS_EPOCH_MS9 + week * MS_PER_WEEK4 + sec * 1e3;
6888
7031
  var sowOf2 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK8;
6889
7032
  function decodeGpsQzsNav(view, b, sys) {
6890
7033
  const svid = view.getUint8(b + 14);
@@ -7034,7 +7177,7 @@ function decodeGloNav(view, b) {
7034
7177
  const tocDate = new Date(toeGpsMs - leapMs);
7035
7178
  const tofGpsMs = gpsMs(wnc, 0) + view.getUint32(b + 8, true);
7036
7179
  const tofLeapMs = getGpsLeap(new Date(tofGpsMs)) * 1e3;
7037
- const messageFrameTime = (tofGpsMs - tofLeapMs - GPS_EPOCH_MS8) / 1e3 % SEC_PER_WEEK8;
7180
+ const messageFrameTime = (tofGpsMs - tofLeapMs - GPS_EPOCH_MS9) / 1e3 % SEC_PER_WEEK8;
7038
7181
  return {
7039
7182
  system: "R",
7040
7183
  prn,
@@ -7306,7 +7449,7 @@ function isFnavDummy(page) {
7306
7449
  }
7307
7450
 
7308
7451
  // src/sbf/rawnav-bds.ts
7309
- var GPS_EPOCH_MS9 = Date.UTC(1980, 0, 6);
7452
+ var GPS_EPOCH_MS10 = Date.UTC(1980, 0, 6);
7310
7453
  var MS_PER_WEEK5 = 7 * 86400 * 1e3;
7311
7454
  var TOW_DNU = 4294967295;
7312
7455
  var WNC_DNU = 65535;
@@ -7376,7 +7519,7 @@ function parseSbfGloNav(data) {
7376
7519
  const eph = assembler.push(
7377
7520
  prn,
7378
7521
  str,
7379
- new Date(GPS_EPOCH_MS9 + wnc * MS_PER_WEEK5 + towMs),
7522
+ new Date(GPS_EPOCH_MS10 + wnc * MS_PER_WEEK5 + towMs),
7380
7523
  view.getUint8(b + 18) - 8
7381
7524
  // FreqNr, offset by 8
7382
7525
  );
@@ -7910,7 +8053,7 @@ function parseSbfHas(data) {
7910
8053
 
7911
8054
  // src/sbf/index.ts
7912
8055
  var CLIGHT = 299792458;
7913
- var GPS_EPOCH_MS10 = Date.UTC(1980, 0, 6);
8056
+ var GPS_EPOCH_MS11 = Date.UTC(1980, 0, 6);
7914
8057
  var MS_PER_WEEK6 = 7 * 864e5;
7915
8058
  var M3_SYS = ["G", "R", "E", "C", "S", "J", "I"];
7916
8059
  var M3_PR_BASE = [19e6, 19e6, 22e6, 2e7, 34e6, 34e6, 34e6];
@@ -8564,7 +8707,7 @@ function parseSbfMeas(data) {
8564
8707
  const tow = view.getUint32(i + 8, true);
8565
8708
  const wnc = view.getUint16(i + 12, true);
8566
8709
  if (tow !== 4294967295 && wnc !== 65535) {
8567
- ensureEpoch(GPS_EPOCH_MS10 + wnc * MS_PER_WEEK6 + tow);
8710
+ ensureEpoch(GPS_EPOCH_MS11 + wnc * MS_PER_WEEK6 + tow);
8568
8711
  if (id === 4109) decodeMeas3Ranges(i, tow);
8569
8712
  else if (id === 4110) decodeMeas3CN0(i, len);
8570
8713
  else if (id === 4111) decodeMeas3Doppler(i, len);
@@ -8629,15 +8772,15 @@ var ID_GALEPHEMERIS = 1122;
8629
8772
  var ID_QZSSEPHEMERIS = 1336;
8630
8773
  var ID_GPSEPHEM = 7;
8631
8774
  var ID_BDSEPHEMERIS = 1696;
8632
- var GPS_EPOCH_MS11 = Date.UTC(1980, 0, 6);
8775
+ var GPS_EPOCH_MS12 = Date.UTC(1980, 0, 6);
8633
8776
  var BDT_EPOCH_MS3 = Date.UTC(2006, 0, 1);
8634
8777
  var SEC_PER_WEEK9 = 7 * 86400;
8635
8778
  var SEC_PER_DAY2 = 86400;
8636
8779
  var MS_PER_WEEK7 = SEC_PER_WEEK9 * 1e3;
8637
- var gpsMs2 = (week, sec) => GPS_EPOCH_MS11 + week * MS_PER_WEEK7 + sec * 1e3;
8780
+ var gpsMs2 = (week, sec) => GPS_EPOCH_MS12 + week * MS_PER_WEEK7 + sec * 1e3;
8638
8781
  var sowOf3 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK9;
8639
8782
  function nearWeekMs(refMs, sow) {
8640
- const refWeek = Math.floor((refMs - GPS_EPOCH_MS11) / MS_PER_WEEK7);
8783
+ const refWeek = Math.floor((refMs - GPS_EPOCH_MS12) / MS_PER_WEEK7);
8641
8784
  let ms = gpsMs2(refWeek, sow);
8642
8785
  if (ms < refMs - MS_PER_WEEK7 / 2) ms += MS_PER_WEEK7;
8643
8786
  else if (ms > refMs + MS_PER_WEEK7 / 2) ms -= MS_PER_WEEK7;
@@ -8664,9 +8807,9 @@ function decodeGloEphemeris(view, p) {
8664
8807
  tof += Math.floor(tow / SEC_PER_DAY2) * SEC_PER_DAY2;
8665
8808
  if (tof < tow - 43200) tof += SEC_PER_DAY2;
8666
8809
  else if (tof > tow + 43200) tof -= SEC_PER_DAY2;
8667
- const toeGpsMs = GPS_EPOCH_MS11 + (week * SEC_PER_WEEK9 + tow) * 1e3;
8668
- const tofGpsMs = GPS_EPOCH_MS11 + (week * SEC_PER_WEEK9 + tof) * 1e3;
8669
- const tofUtcSec = (getUtcDate(new Date(tofGpsMs)).getTime() - GPS_EPOCH_MS11) / 1e3;
8810
+ const toeGpsMs = GPS_EPOCH_MS12 + (week * SEC_PER_WEEK9 + tow) * 1e3;
8811
+ const tofGpsMs = GPS_EPOCH_MS12 + (week * SEC_PER_WEEK9 + tof) * 1e3;
8812
+ const tofUtcSec = (getUtcDate(new Date(tofGpsMs)).getTime() - GPS_EPOCH_MS12) / 1e3;
8670
8813
  return {
8671
8814
  system: "R",
8672
8815
  prn: `R${String(slot).padStart(2, "0")}`,
@@ -8731,7 +8874,7 @@ function decodeGalEphemeris(view, p, headerMs) {
8731
8874
  omega: view.getFloat64(p + 60, true),
8732
8875
  omegaDot: view.getFloat64(p + 140, true),
8733
8876
  idot: view.getFloat64(p + 124, true),
8734
- week: Math.floor((toeMs - GPS_EPOCH_MS11) / MS_PER_WEEK7),
8877
+ week: Math.floor((toeMs - GPS_EPOCH_MS12) / MS_PER_WEEK7),
8735
8878
  // RINEX Galileo SVH bit layout (E1B DVS/HS in bits 0-2, E5a in
8736
8879
  // 3-5, E5b in 6-8) — same packing as RTKLIB.
8737
8880
  svHealth: svhE5b << 7 | dvsE5b << 6 | svhE5a << 4 | dvsE5a << 3 | svhE1b << 1 | dvsE1b,
@@ -8903,7 +9046,7 @@ function parseNovatelNav(data) {
8903
9046
  }
8904
9047
 
8905
9048
  // src/novatel/index.ts
8906
- var GPS_EPOCH_MS12 = Date.UTC(1980, 0, 6);
9049
+ var GPS_EPOCH_MS13 = Date.UTC(1980, 0, 6);
8907
9050
  var MS_PER_WEEK8 = 7 * 864e5;
8908
9051
  var HDR = 28;
8909
9052
  var ID_RANGE = 43;
@@ -9073,7 +9216,7 @@ function parseNovatelRange(data) {
9073
9216
  if (!codes.includes(code)) codes.push(code);
9074
9217
  }
9075
9218
  epochs.push({
9076
- timeMs: GPS_EPOCH_MS12 + week * MS_PER_WEEK8 + towMs,
9219
+ timeMs: GPS_EPOCH_MS13 + week * MS_PER_WEEK8 + towMs,
9077
9220
  meas
9078
9221
  });
9079
9222
  }
@@ -9125,7 +9268,7 @@ function parseNovatelRange(data) {
9125
9268
  if (!codes.includes(code)) codes.push(code);
9126
9269
  }
9127
9270
  epochs.push({
9128
- timeMs: GPS_EPOCH_MS12 + week * MS_PER_WEEK8 + towMs,
9271
+ timeMs: GPS_EPOCH_MS13 + week * MS_PER_WEEK8 + towMs,
9129
9272
  meas
9130
9273
  });
9131
9274
  }
@@ -9176,11 +9319,11 @@ function* trimbleFrames(data, stats) {
9176
9319
  }
9177
9320
 
9178
9321
  // src/trimble/nav.ts
9179
- var GPS_EPOCH_MS13 = Date.UTC(1980, 0, 6);
9322
+ var GPS_EPOCH_MS14 = Date.UTC(1980, 0, 6);
9180
9323
  var SEC_PER_WEEK10 = 7 * 86400;
9181
9324
  var MS_PER_WEEK9 = SEC_PER_WEEK10 * 1e3;
9182
9325
  var GPS_PI2 = 3.1415926535898;
9183
- var gpsMs3 = (week, sec) => GPS_EPOCH_MS13 + week * MS_PER_WEEK9 + sec * 1e3;
9326
+ var gpsMs3 = (week, sec) => GPS_EPOCH_MS14 + week * MS_PER_WEEK9 + sec * 1e3;
9184
9327
  var sowOf4 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK10;
9185
9328
  var SUB_GPS_EPHEMERIS = 1;
9186
9329
  var SUB_ION_UTC = 3;
@@ -9282,7 +9425,7 @@ function parseTrimbleNav(data) {
9282
9425
  }
9283
9426
 
9284
9427
  // src/trimble/index.ts
9285
- var GPS_EPOCH_MS14 = Date.UTC(1980, 0, 6);
9428
+ var GPS_EPOCH_MS15 = Date.UTC(1980, 0, 6);
9286
9429
  var MS_PER_WEEK10 = 7 * 864e5;
9287
9430
  var REC_TYPE_27 = 6;
9288
9431
  var SYS = {
@@ -9480,7 +9623,7 @@ function decodeEpoch(epoch, epochs, obsCodes) {
9480
9623
  o += c.length;
9481
9624
  }
9482
9625
  const dv = new DataView(M.buffer, M.byteOffset, M.byteLength);
9483
- const timeMs = GPS_EPOCH_MS14 + epoch.week * MS_PER_WEEK10 + epoch.towMs;
9626
+ const timeMs = GPS_EPOCH_MS15 + epoch.week * MS_PER_WEEK10 + epoch.towMs;
9484
9627
  const meas = [];
9485
9628
  let q = 0;
9486
9629
  for (let sv = 0; sv < epoch.nsv && q + 8 <= M.length; sv++) {
@@ -9661,13 +9804,13 @@ function* binexRecords(data, view, stats) {
9661
9804
  }
9662
9805
 
9663
9806
  // src/binex/nav.ts
9664
- var GPS_EPOCH_MS15 = Date.UTC(1980, 0, 6);
9807
+ var GPS_EPOCH_MS16 = Date.UTC(1980, 0, 6);
9665
9808
  var GLO_DAY0_MS = Date.UTC(1980, 0, 1);
9666
9809
  var BDT_EPOCH_MS4 = Date.UTC(2006, 0, 1);
9667
9810
  var SEC_PER_WEEK11 = 7 * 86400;
9668
9811
  var MS_PER_WEEK11 = SEC_PER_WEEK11 * 1e3;
9669
9812
  var SC2RAD = GPS_PI;
9670
- var gpsMs4 = (week, sec) => GPS_EPOCH_MS15 + week * MS_PER_WEEK11 + sec * 1e3;
9813
+ var gpsMs4 = (week, sec) => GPS_EPOCH_MS16 + week * MS_PER_WEEK11 + sec * 1e3;
9671
9814
  var sowOf5 = (dateMs) => (dateMs / 1e3 % SEC_PER_WEEK11 + SEC_PER_WEEK11) % SEC_PER_WEEK11;
9672
9815
  var two5 = (n) => String(n).padStart(2, "0");
9673
9816
  var Reader = class {
@@ -9955,7 +10098,7 @@ function decodeBinexEph(view, body, len, le) {
9955
10098
  }
9956
10099
 
9957
10100
  // src/binex/index.ts
9958
- var GPS_EPOCH_MS16 = Date.UTC(1980, 0, 6);
10101
+ var GPS_EPOCH_MS17 = Date.UTC(1980, 0, 6);
9959
10102
  var CLIGHT2 = 299792458;
9960
10103
  var OBS_CODES = {
9961
10104
  0: [
@@ -10213,7 +10356,7 @@ function decodeObsRecord(data, view, body, len, obsCodes) {
10213
10356
  p += 4;
10214
10357
  const msec = view.getUint16(p);
10215
10358
  p += 2;
10216
- const timeMs = GPS_EPOCH_MS16 + min * 6e4 + msec;
10359
+ const timeMs = GPS_EPOCH_MS17 + min * 6e4 + msec;
10217
10360
  const flag = data[p++];
10218
10361
  const nsat = (flag & 63) + 1;
10219
10362
  if (flag & 128) p += 3;
@@ -10299,7 +10442,7 @@ function parseBinex(data) {
10299
10442
  var GM_GPS = 3986005e8;
10300
10443
  var GM_GAL = 3986004418e5;
10301
10444
  var GM_BDS = 3986004418e5;
10302
- var GPS_EPOCH_MS17 = Date.UTC(1980, 0, 6);
10445
+ var GPS_EPOCH_MS18 = Date.UTC(1980, 0, 6);
10303
10446
  var BDT_EPOCH_MS5 = Date.UTC(2006, 0, 1);
10304
10447
  var WEEK_MS = 6048e5;
10305
10448
  var BDT_MINUS_GPST_MS = 14e3;
@@ -10308,7 +10451,7 @@ function almanacEpochMs(alm) {
10308
10451
  if (alm.system === "C") {
10309
10452
  return BDT_EPOCH_MS5 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3 + BDT_MINUS_GPST_MS;
10310
10453
  }
10311
- return GPS_EPOCH_MS17 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3;
10454
+ return GPS_EPOCH_MS18 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3;
10312
10455
  }
10313
10456
  function almanacSatPosition(alm, timeMs) {
10314
10457
  const GM = alm.system === "E" ? GM_GAL : alm.system === "C" ? GM_BDS : GM_GPS;
@@ -10817,10 +10960,10 @@ function selectBest(ephs, timeMs) {
10817
10960
  }
10818
10961
  return best;
10819
10962
  }
10820
- var GPS_EPOCH_MS18 = START_GPS_TIME.getTime();
10963
+ var GPS_EPOCH_MS19 = START_GPS_TIME.getTime();
10821
10964
  var MS_PER_WEEK12 = 7 * 864e5;
10822
10965
  var BDS_EPOCH_MS = START_BDS_TIME.getTime();
10823
- var GAL_EPOCH_MS = GPS_EPOCH_MS18 + 1024 * MS_PER_WEEK12;
10966
+ var GAL_EPOCH_MS = GPS_EPOCH_MS19 + 1024 * MS_PER_WEEK12;
10824
10967
  function ephInfoToEphemeris(info) {
10825
10968
  const sys = info.prn.charAt(0);
10826
10969
  if (sys === "R") {
@@ -10871,8 +11014,8 @@ function ephInfoToEphemeris(info) {
10871
11014
  } else if (sys === "E") {
10872
11015
  epochMs = GAL_EPOCH_MS;
10873
11016
  } else {
10874
- epochMs = GPS_EPOCH_MS18;
10875
- const weeksNow = (info.lastReceived - GPS_EPOCH_MS18) / MS_PER_WEEK12;
11017
+ epochMs = GPS_EPOCH_MS19;
11018
+ const weeksNow = (info.lastReceived - GPS_EPOCH_MS19) / MS_PER_WEEK12;
10876
11019
  week += 1024 * Math.round((weeksNow - week) / 1024);
10877
11020
  }
10878
11021
  const tocDate = new Date(epochMs + week * MS_PER_WEEK12 + tocSec * 1e3);
@@ -12834,7 +12977,7 @@ function sagnacRotate(x, y, z, travelS) {
12834
12977
  const s = Math.sin(theta);
12835
12978
  return [x * c + y * s, -x * s + y * c, z];
12836
12979
  }
12837
- function satStateAtEmission(sp3, prn, recvTimeMs, rcv) {
12980
+ function satStateAtEmission(sp3, prn, recvTimeMs, rcv, clk) {
12838
12981
  let travelS = 0.075;
12839
12982
  let sx = 0;
12840
12983
  let sy = 0;
@@ -12853,7 +12996,7 @@ function satStateAtEmission(sp3, prn, recvTimeMs, rcv) {
12853
12996
  const vz = (pPlus.z - pMinus.z) / 1;
12854
12997
  velDotPos = p.x * vx + p.y * vy + p.z * vz;
12855
12998
  }
12856
- clkS = p.clk;
12999
+ clkS = (clk && clkBias(clk, prn, tEmit)) ?? p.clk;
12857
13000
  const [rx, ry, rz] = sagnacRotate(p.x, p.y, p.z, travelS);
12858
13001
  sx = rx;
12859
13002
  sy = ry;
@@ -12967,7 +13110,7 @@ function solvePpp(epochs, sp3, opts) {
12967
13110
  for (const o of epoch.obs) {
12968
13111
  if (o.c1 === 0 || o.c2 === 0 || o.l1 === 0 || o.l2 === 0) continue;
12969
13112
  const slip = detectSlip(o, ei);
12970
- const sat = satStateAtEmission(sp3, o.prn, epoch.timeMs, rcv);
13113
+ const sat = satStateAtEmission(sp3, o.prn, epoch.timeMs, rcv, opts.clk);
12971
13114
  if (!sat) continue;
12972
13115
  const [elRad, azRad] = getAer(
12973
13116
  sat.state.x,
@@ -13162,6 +13305,96 @@ function solvePpp(epochs, sp3, opts) {
13162
13305
  };
13163
13306
  }
13164
13307
 
13308
+ // src/positioning/ppp-ar.ts
13309
+ function wlWavelength(f1, f2) {
13310
+ return C_LIGHT / (f1 - f2);
13311
+ }
13312
+ function nlWavelength(f1, f2) {
13313
+ return C_LIGHT / (f1 + f2);
13314
+ }
13315
+ function resolvePppAmbiguities(sats, Qaif, opts = {}) {
13316
+ const wlThreshold = opts.wlThreshold ?? 0.25;
13317
+ const ratioThreshold = opts.ratioThreshold ?? 3;
13318
+ const kept = [];
13319
+ const nWl = [];
13320
+ const rejectedWl = [];
13321
+ for (let i = 0; i < sats.length; i++) {
13322
+ const s = sats[i];
13323
+ const wlFloat = s.mwCyc - (s.wlBiasCyc ?? 0);
13324
+ const r = Math.round(wlFloat);
13325
+ if (Math.abs(wlFloat - r) <= wlThreshold) {
13326
+ kept.push(i);
13327
+ nWl.push(r);
13328
+ } else {
13329
+ rejectedWl.push(s.prn);
13330
+ }
13331
+ }
13332
+ if (kept.length < 2) {
13333
+ return {
13334
+ fixed: false,
13335
+ ratio: 0,
13336
+ refPrn: null,
13337
+ sats: [],
13338
+ rejectedWl
13339
+ };
13340
+ }
13341
+ const n1Float = [];
13342
+ const lamNl = [];
13343
+ for (let k = 0; k < kept.length; k++) {
13344
+ const s = sats[kept[k]];
13345
+ const lNl = nlWavelength(s.f1, s.f2);
13346
+ lamNl.push(lNl);
13347
+ const n1 = s.aIF / lNl - s.f2 / (s.f1 - s.f2) * nWl[k] - (s.nlBiasCyc ?? 0);
13348
+ n1Float.push(n1);
13349
+ }
13350
+ let ref = 0;
13351
+ for (let k = 1; k < kept.length; k++) {
13352
+ const e = sats[kept[k]].elevDeg ?? -1;
13353
+ if (e > (sats[kept[ref]].elevDeg ?? -1)) ref = k;
13354
+ }
13355
+ const m = kept.length - 1;
13356
+ const sd2 = new Float64Array(m);
13357
+ const Qsd = new Float64Array(m * m);
13358
+ const others = [];
13359
+ for (let k = 0; k < kept.length; k++) if (k !== ref) others.push(k);
13360
+ const n = sats.length;
13361
+ const qN1 = (ka, kb) => Qaif[kept[ka] * n + kept[kb]] / (lamNl[ka] * lamNl[kb]);
13362
+ for (let a = 0; a < m; a++) {
13363
+ const ka = others[a];
13364
+ sd2[a] = n1Float[ka] - n1Float[ref];
13365
+ for (let b = 0; b < m; b++) {
13366
+ const kb = others[b];
13367
+ Qsd[a * m + b] = qN1(ka, kb) - qN1(ka, ref) - qN1(ref, kb) + qN1(ref, ref);
13368
+ }
13369
+ }
13370
+ const res = lambdaSearch(sd2, Qsd, m, 2);
13371
+ const ratio = res ? Math.min(res.ratio, 999.9) : 0;
13372
+ const fixed = !!res && ratio >= ratioThreshold;
13373
+ const refN1 = Math.round(n1Float[ref]);
13374
+ const sdFix = res?.candidates[0];
13375
+ const outSats = [];
13376
+ for (let k = 0; k < kept.length; k++) {
13377
+ const s = sats[kept[k]];
13378
+ let n1;
13379
+ if (k === ref) {
13380
+ n1 = refN1;
13381
+ } else {
13382
+ const a = others.indexOf(k);
13383
+ n1 = fixed && sdFix ? refN1 + Math.round(sdFix[a]) : Math.round(n1Float[k]);
13384
+ }
13385
+ const lNl = lamNl[k];
13386
+ const aIF = lNl * n1 + lNl * (s.f2 / (s.f1 - s.f2)) * nWl[k];
13387
+ outSats.push({ prn: s.prn, nWl: nWl[k], n1, aIF });
13388
+ }
13389
+ return {
13390
+ fixed,
13391
+ ratio,
13392
+ refPrn: sats[kept[ref]].prn,
13393
+ sats: outSats,
13394
+ rejectedWl
13395
+ };
13396
+ }
13397
+
13165
13398
  // src/positioning/index.ts
13166
13399
  var GM_GPS3 = 3986005e8;
13167
13400
  var F_REL = -4442807633e-19;
@@ -15741,6 +15974,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
15741
15974
  analyzeQuality,
15742
15975
  applyHelmert,
15743
15976
  applyIonoDcb,
15977
+ biasMetres,
15744
15978
  binexCrc16,
15745
15979
  binexCrc32,
15746
15980
  binexCsum8,
@@ -15749,6 +15983,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
15749
15983
  buildObsIndices,
15750
15984
  buildPppAntenna,
15751
15985
  clampUnit,
15986
+ clkBias,
15752
15987
  computeAllPositions,
15753
15988
  computeDop,
15754
15989
  computeIonoRate,
@@ -15779,6 +16014,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
15779
16014
  ephInfoToEphemeris,
15780
16015
  euclidean3D,
15781
16016
  fetchSourcetable,
16017
+ findSatBias,
15782
16018
  fmtD,
15783
16019
  fmtF,
15784
16020
  formatUTCTime,
@@ -15861,12 +16097,15 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
15861
16097
  msmEpochToDate,
15862
16098
  navTimesFromEph,
15863
16099
  niellMapping,
16100
+ nlWavelength,
15864
16101
  nmeaCoordToDecimal,
15865
16102
  oem4Frames,
15866
16103
  padL,
15867
16104
  padR,
15868
16105
  parseAntex,
16106
+ parseBiasSinex,
15869
16107
  parseBinex,
16108
+ parseClk,
15870
16109
  parseCrxDataLine,
15871
16110
  parseIonex,
15872
16111
  parseNavFile,
@@ -15902,6 +16141,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
15902
16141
  readString,
15903
16142
  reportDecodeError,
15904
16143
  resetGloFreqCache,
16144
+ resolvePppAmbiguities,
15905
16145
  rhumbLine,
15906
16146
  rtcm3Constellation,
15907
16147
  satClockCorrection,
@@ -15927,6 +16167,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
15927
16167
  updateStreamStats,
15928
16168
  verifyChecksum,
15929
16169
  vincenty,
16170
+ wlWavelength,
15930
16171
  writeCrx,
15931
16172
  writeModernObsBlob,
15932
16173
  writeRinex2ObsBlob,