gnss-js 1.30.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.
@@ -5,6 +5,9 @@ import {
5
5
  import {
6
6
  GPS_PI
7
7
  } from "./chunk-IQ5OIMQD.js";
8
+ import {
9
+ C_LIGHT
10
+ } from "./chunk-FIEWO4J4.js";
8
11
 
9
12
  // src/rinex/crx-writer.ts
10
13
  var ARC_ORDER = 3;
@@ -1417,6 +1420,81 @@ function parseIonex(text) {
1417
1420
  return { epochs, lats, lons, maps };
1418
1421
  }
1419
1422
 
1423
+ // src/rinex/bias-sinex.ts
1424
+ function parseEpoch(s, openTo) {
1425
+ const m = /^(\d{4}):(\d{3}):(\d{5})$/.exec(s.trim());
1426
+ if (!m) return openTo;
1427
+ const y = +m[1];
1428
+ if (y === 0) return openTo;
1429
+ const doy = +m[2];
1430
+ const sod = +m[3];
1431
+ return Date.UTC(y, 0, 1) + (doy - 1) * 864e5 + sod * 1e3;
1432
+ }
1433
+ function parseBiasSinex(text) {
1434
+ const records = [];
1435
+ let inBlock = false;
1436
+ for (const line of text.split("\n")) {
1437
+ if (line.startsWith("+BIAS/SOLUTION")) {
1438
+ inBlock = true;
1439
+ continue;
1440
+ }
1441
+ if (line.startsWith("-BIAS/SOLUTION")) {
1442
+ inBlock = false;
1443
+ continue;
1444
+ }
1445
+ if (!inBlock || line.length < 65 || line.startsWith("*")) continue;
1446
+ const type = line.slice(1, 4).trim();
1447
+ if (type !== "DSB" && type !== "OSB" && type !== "ISB") continue;
1448
+ const prn = line.slice(11, 14).trim();
1449
+ const station = line.slice(15, 24).trim();
1450
+ const obs1 = line.slice(25, 29).trim();
1451
+ const obs2 = line.slice(30, 34).trim();
1452
+ const startMs = parseEpoch(line.slice(35, 49), -Infinity);
1453
+ const endMs = parseEpoch(line.slice(50, 64), Infinity);
1454
+ const tail = line.slice(65).trim().split(/\s+/);
1455
+ if (tail.length < 2) continue;
1456
+ const unit = tail[0];
1457
+ const value = Number(tail[1]);
1458
+ if (!Number.isFinite(value)) continue;
1459
+ records.push({
1460
+ type,
1461
+ prn,
1462
+ station,
1463
+ obs1,
1464
+ obs2,
1465
+ startMs,
1466
+ endMs,
1467
+ value,
1468
+ unit
1469
+ });
1470
+ }
1471
+ const bySat = /* @__PURE__ */ new Map();
1472
+ for (const r of records) {
1473
+ if (!r.prn || r.station) continue;
1474
+ let a = bySat.get(r.prn);
1475
+ if (!a) {
1476
+ a = [];
1477
+ bySat.set(r.prn, a);
1478
+ }
1479
+ a.push(r);
1480
+ }
1481
+ return { records, bySat };
1482
+ }
1483
+ function biasMetres(r) {
1484
+ return r.unit === "ns" ? r.value * 1e-9 * C_LIGHT : r.value;
1485
+ }
1486
+ function findSatBias(bias, prn, obs1, obs2, tMs) {
1487
+ const recs = bias.bySat.get(prn);
1488
+ if (!recs) return null;
1489
+ for (const r of recs) {
1490
+ if (r.obs1 !== obs1) continue;
1491
+ if (obs2 === void 0 ? r.obs2 !== "" : r.obs2 !== obs2) continue;
1492
+ if (tMs != null && (tMs < r.startMs || tMs > r.endMs)) continue;
1493
+ return r;
1494
+ }
1495
+ return null;
1496
+ }
1497
+
1420
1498
  // src/rinex/obs-writer-common.ts
1421
1499
  function createGzipLineSink() {
1422
1500
  const encoder = new TextEncoder();
@@ -1804,6 +1882,9 @@ export {
1804
1882
  writeRinexNav,
1805
1883
  writeRinexNav4,
1806
1884
  parseIonex,
1885
+ parseBiasSinex,
1886
+ biasMetres,
1887
+ findSatBias,
1807
1888
  createGzipLineSink,
1808
1889
  stationHeaderLines,
1809
1890
  writeRinexObsBlob,
@@ -1911,6 +1911,96 @@ function solvePpp(epochs, sp3, opts) {
1911
1911
  };
1912
1912
  }
1913
1913
 
1914
+ // src/positioning/ppp-ar.ts
1915
+ function wlWavelength(f1, f2) {
1916
+ return C_LIGHT / (f1 - f2);
1917
+ }
1918
+ function nlWavelength(f1, f2) {
1919
+ return C_LIGHT / (f1 + f2);
1920
+ }
1921
+ function resolvePppAmbiguities(sats, Qaif, opts = {}) {
1922
+ const wlThreshold = opts.wlThreshold ?? 0.25;
1923
+ const ratioThreshold = opts.ratioThreshold ?? 3;
1924
+ const kept = [];
1925
+ const nWl = [];
1926
+ const rejectedWl = [];
1927
+ for (let i = 0; i < sats.length; i++) {
1928
+ const s = sats[i];
1929
+ const wlFloat = s.mwCyc - (s.wlBiasCyc ?? 0);
1930
+ const r = Math.round(wlFloat);
1931
+ if (Math.abs(wlFloat - r) <= wlThreshold) {
1932
+ kept.push(i);
1933
+ nWl.push(r);
1934
+ } else {
1935
+ rejectedWl.push(s.prn);
1936
+ }
1937
+ }
1938
+ if (kept.length < 2) {
1939
+ return {
1940
+ fixed: false,
1941
+ ratio: 0,
1942
+ refPrn: null,
1943
+ sats: [],
1944
+ rejectedWl
1945
+ };
1946
+ }
1947
+ const n1Float = [];
1948
+ const lamNl = [];
1949
+ for (let k = 0; k < kept.length; k++) {
1950
+ const s = sats[kept[k]];
1951
+ const lNl = nlWavelength(s.f1, s.f2);
1952
+ lamNl.push(lNl);
1953
+ const n1 = s.aIF / lNl - s.f2 / (s.f1 - s.f2) * nWl[k] - (s.nlBiasCyc ?? 0);
1954
+ n1Float.push(n1);
1955
+ }
1956
+ let ref = 0;
1957
+ for (let k = 1; k < kept.length; k++) {
1958
+ const e = sats[kept[k]].elevDeg ?? -1;
1959
+ if (e > (sats[kept[ref]].elevDeg ?? -1)) ref = k;
1960
+ }
1961
+ const m = kept.length - 1;
1962
+ const sd = new Float64Array(m);
1963
+ const Qsd = new Float64Array(m * m);
1964
+ const others = [];
1965
+ for (let k = 0; k < kept.length; k++) if (k !== ref) others.push(k);
1966
+ const n = sats.length;
1967
+ const qN1 = (ka, kb) => Qaif[kept[ka] * n + kept[kb]] / (lamNl[ka] * lamNl[kb]);
1968
+ for (let a = 0; a < m; a++) {
1969
+ const ka = others[a];
1970
+ sd[a] = n1Float[ka] - n1Float[ref];
1971
+ for (let b = 0; b < m; b++) {
1972
+ const kb = others[b];
1973
+ Qsd[a * m + b] = qN1(ka, kb) - qN1(ka, ref) - qN1(ref, kb) + qN1(ref, ref);
1974
+ }
1975
+ }
1976
+ const res = lambdaSearch(sd, Qsd, m, 2);
1977
+ const ratio = res ? Math.min(res.ratio, 999.9) : 0;
1978
+ const fixed = !!res && ratio >= ratioThreshold;
1979
+ const refN1 = Math.round(n1Float[ref]);
1980
+ const sdFix = res?.candidates[0];
1981
+ const outSats = [];
1982
+ for (let k = 0; k < kept.length; k++) {
1983
+ const s = sats[kept[k]];
1984
+ let n1;
1985
+ if (k === ref) {
1986
+ n1 = refN1;
1987
+ } else {
1988
+ const a = others.indexOf(k);
1989
+ n1 = fixed && sdFix ? refN1 + Math.round(sdFix[a]) : Math.round(n1Float[k]);
1990
+ }
1991
+ const lNl = lamNl[k];
1992
+ const aIF = lNl * n1 + lNl * (s.f2 / (s.f1 - s.f2)) * nWl[k];
1993
+ outSats.push({ prn: s.prn, nWl: nWl[k], n1, aIF });
1994
+ }
1995
+ return {
1996
+ fixed,
1997
+ ratio,
1998
+ refPrn: sats[kept[ref]].prn,
1999
+ sats: outSats,
2000
+ rejectedWl
2001
+ };
2002
+ }
2003
+
1914
2004
  // src/positioning/index.ts
1915
2005
  var GM_GPS = 3986005e8;
1916
2006
  var F_REL = -4442807633e-19;
@@ -2157,6 +2247,9 @@ export {
2157
2247
  buildPppAntenna,
2158
2248
  createPppCorrections,
2159
2249
  solvePpp,
2250
+ wlWavelength,
2251
+ nlWavelength,
2252
+ resolvePppAmbiguities,
2160
2253
  satClockCorrection,
2161
2254
  ionoFree,
2162
2255
  solveSpp
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,
@@ -150,6 +151,7 @@ __export(src_exports, {
150
151
  ephInfoToEphemeris: () => ephInfoToEphemeris,
151
152
  euclidean3D: () => euclidean3D,
152
153
  fetchSourcetable: () => fetchSourcetable,
154
+ findSatBias: () => findSatBias,
153
155
  fmtD: () => fmtD,
154
156
  fmtF: () => fmtF,
155
157
  formatUTCTime: () => formatUTCTime,
@@ -232,11 +234,13 @@ __export(src_exports, {
232
234
  msmEpochToDate: () => msmEpochToDate,
233
235
  navTimesFromEph: () => navTimesFromEph,
234
236
  niellMapping: () => niellMapping,
237
+ nlWavelength: () => nlWavelength,
235
238
  nmeaCoordToDecimal: () => nmeaCoordToDecimal,
236
239
  oem4Frames: () => oem4Frames,
237
240
  padL: () => padL,
238
241
  padR: () => padR,
239
242
  parseAntex: () => parseAntex,
243
+ parseBiasSinex: () => parseBiasSinex,
240
244
  parseBinex: () => parseBinex,
241
245
  parseClk: () => parseClk,
242
246
  parseCrxDataLine: () => parseCrxDataLine,
@@ -274,6 +278,7 @@ __export(src_exports, {
274
278
  readString: () => readString,
275
279
  reportDecodeError: () => reportDecodeError,
276
280
  resetGloFreqCache: () => resetGloFreqCache,
281
+ resolvePppAmbiguities: () => resolvePppAmbiguities,
277
282
  rhumbLine: () => rhumbLine,
278
283
  rtcm3Constellation: () => rtcm3Constellation,
279
284
  satClockCorrection: () => satClockCorrection,
@@ -299,6 +304,7 @@ __export(src_exports, {
299
304
  updateStreamStats: () => updateStreamStats,
300
305
  verifyChecksum: () => verifyChecksum,
301
306
  vincenty: () => vincenty,
307
+ wlWavelength: () => wlWavelength,
302
308
  writeCrx: () => writeCrx,
303
309
  writeModernObsBlob: () => writeModernObsBlob,
304
310
  writeRinex2ObsBlob: () => writeRinex2ObsBlob,
@@ -3958,6 +3964,81 @@ function clkBias(clk, prn, tMs) {
3958
3964
  return c[lo] + f * (c[lo + 1] - c[lo]);
3959
3965
  }
3960
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
+
3961
4042
  // src/rinex/obs-writer-common.ts
3962
4043
  function createGzipLineSink() {
3963
4044
  const encoder = new TextEncoder();
@@ -13224,6 +13305,96 @@ function solvePpp(epochs, sp3, opts) {
13224
13305
  };
13225
13306
  }
13226
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
+
13227
13398
  // src/positioning/index.ts
13228
13399
  var GM_GPS3 = 3986005e8;
13229
13400
  var F_REL = -4442807633e-19;
@@ -15803,6 +15974,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
15803
15974
  analyzeQuality,
15804
15975
  applyHelmert,
15805
15976
  applyIonoDcb,
15977
+ biasMetres,
15806
15978
  binexCrc16,
15807
15979
  binexCrc32,
15808
15980
  binexCsum8,
@@ -15842,6 +16014,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
15842
16014
  ephInfoToEphemeris,
15843
16015
  euclidean3D,
15844
16016
  fetchSourcetable,
16017
+ findSatBias,
15845
16018
  fmtD,
15846
16019
  fmtF,
15847
16020
  formatUTCTime,
@@ -15924,11 +16097,13 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
15924
16097
  msmEpochToDate,
15925
16098
  navTimesFromEph,
15926
16099
  niellMapping,
16100
+ nlWavelength,
15927
16101
  nmeaCoordToDecimal,
15928
16102
  oem4Frames,
15929
16103
  padL,
15930
16104
  padR,
15931
16105
  parseAntex,
16106
+ parseBiasSinex,
15932
16107
  parseBinex,
15933
16108
  parseClk,
15934
16109
  parseCrxDataLine,
@@ -15966,6 +16141,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
15966
16141
  readString,
15967
16142
  reportDecodeError,
15968
16143
  resetGloFreqCache,
16144
+ resolvePppAmbiguities,
15969
16145
  rhumbLine,
15970
16146
  rtcm3Constellation,
15971
16147
  satClockCorrection,
@@ -15991,6 +16167,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
15991
16167
  updateStreamStats,
15992
16168
  verifyChecksum,
15993
16169
  vincenty,
16170
+ wlWavelength,
15994
16171
  writeCrx,
15995
16172
  writeModernObsBlob,
15996
16173
  writeRinex2ObsBlob,
package/dist/index.d.cts CHANGED
@@ -4,7 +4,7 @@ export { A as ARC_GAP_FACTOR, B as BAND_LABELS, a as BDS_SATELLITES, b as BdsSat
4
4
  export { Scale, getBdsTime, getDateFromBdsTime, getDateFromDayOfWeek, getDateFromDayOfYear, getDateFromGalTime, getDateFromGloN, getDateFromGpsData, getDateFromGpsTime, getDateFromHourCode, getDateFromJulianDate, getDateFromMJD, getDateFromMJD2000, getDateFromRINEX, getDateFromTai, getDateFromTimeOfDay, getDateFromTt, getDateFromUnixTime, getDateFromUtc, getDayOfWeek, getDayOfYear, getGalTime, getGloN4, getGloNA, getGpsLeap, getGpsTime, getHourCode, getHoursFromTimeDifference, getJulianDate, getLeap, getMJD, getMJD2000, getMinutesFromTimeDifference, getNtpTime, getRINEX, getSecondsFromTimeDifference, getTaiDate, getTimeDifference, getTimeDifferenceFromDays, getTimeDifferenceFromHours, getTimeDifferenceFromMinutes, getTimeDifferenceFromObject, getTimeDifferenceFromSeconds, getTimeOfDay, getTimeOfWeek, getTotalDaysFromTimeDifference, getTtDate, getUnixTime, getUtcDate, getWeekNumber, getWeekOfYear } from './time.cjs';
5
5
  export { deg2dms, deg2rad, euclidean3D, geodeticToGeohash, geodeticToMaidenhead, geodeticToUtm, greatCircleMidpoint, horizonDistance, rad2deg, rhumbLine, vincenty } from './coordinates.cjs';
6
6
  export { c as clampUnit, e as ecefToGeodetic, g as geodeticToEcef, a as getAer, b as getEnuDifference } from './ecef-CF0uAysr.cjs';
7
- export { CompactEpoch, CrxField, DiffState, EMPTY_WARNINGS, Nav4Input, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, WriteCrxOptions, createGzipLineSink, crxDecompress, crxRepair, fmtD, fmtF, hdrLine, padL, padR, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob } from './rinex.cjs';
7
+ export { BiasRecord, BiasSinex, CompactEpoch, CrxField, DiffState, EMPTY_WARNINGS, Nav4Input, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, WriteCrxOptions, biasMetres, createGzipLineSink, crxDecompress, crxRepair, findSatBias, fmtD, fmtF, hdrLine, padL, padR, parseBiasSinex, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob } from './rinex.cjs';
8
8
  export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResult, b as RinexStats, S as SYSTEM_ORDER, c as SatObsCallback, p as parseRinexStream, s as systemCmp, d as systemName } from './parser-JPjjFgeP.cjs';
9
9
  export { C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, R as RinexCnavEphemeris, p as parseNavFile } from './nav-DImXUdbp.cjs';
10
10
  export { C as ClkFile, I as IonexGrid, S as Sp3File, a as Sp3Sample, c as clkBias, p as parseClk, b as parseIonex, d as parseSp3, s as sp3Position } from './clk-DGVBGRzA.cjs';
@@ -17,7 +17,7 @@ export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, Trimb
17
17
  export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.cjs';
18
18
  export { AllPositionsData, AlmanacPosition, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.cjs';
19
19
  export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.cjs';
20
- export { AntennaOffset, CorrectionResult, DgnssOptions, DgnssSolution, EphemerisSource, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, PppAntennaModel, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, SatGeom, SppOptions, SppSolution, TropoMapping, buildPppAntenna, createPppCorrections, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch } from './positioning.cjs';
20
+ export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, DgnssOptions, DgnssSolution, EphemerisSource, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, PppAntennaModel, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, SatGeom, SppOptions, SppSolution, TropoMapping, buildPppAntenna, createPppCorrections, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.cjs';
21
21
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.cjs';
22
22
  export { CompleteSatSignal, CompleteSignalStats, CompletenessAccumulator, CompletenessResult, CycleSlipAccumulator, CycleSlipEvent, CycleSlipResult, CycleSlipSignalStats, IonoAccumulator, IonoDcbResult, IonoPoint, IonoRatePoint, IonoRateSeries, IonoResult, IonoSeries, MultipathAccumulator, MultipathPoint, MultipathResult, MultipathSeries, MultipathSignalStat, QualityResult, SatDcbMap, analyzeQuality, applyIonoDcb, computeIonoRate, detrendIonoArcs, parseSinexBiasDcb } from './analysis.cjs';
23
23
  export { AntennaEntry, AntexFile, FrequencyData, frequencyLabel, parseAntex } from './antex.cjs';
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { A as ARC_GAP_FACTOR, B as BAND_LABELS, a as BDS_SATELLITES, b as BdsSat
4
4
  export { Scale, getBdsTime, getDateFromBdsTime, getDateFromDayOfWeek, getDateFromDayOfYear, getDateFromGalTime, getDateFromGloN, getDateFromGpsData, getDateFromGpsTime, getDateFromHourCode, getDateFromJulianDate, getDateFromMJD, getDateFromMJD2000, getDateFromRINEX, getDateFromTai, getDateFromTimeOfDay, getDateFromTt, getDateFromUnixTime, getDateFromUtc, getDayOfWeek, getDayOfYear, getGalTime, getGloN4, getGloNA, getGpsLeap, getGpsTime, getHourCode, getHoursFromTimeDifference, getJulianDate, getLeap, getMJD, getMJD2000, getMinutesFromTimeDifference, getNtpTime, getRINEX, getSecondsFromTimeDifference, getTaiDate, getTimeDifference, getTimeDifferenceFromDays, getTimeDifferenceFromHours, getTimeDifferenceFromMinutes, getTimeDifferenceFromObject, getTimeDifferenceFromSeconds, getTimeOfDay, getTimeOfWeek, getTotalDaysFromTimeDifference, getTtDate, getUnixTime, getUtcDate, getWeekNumber, getWeekOfYear } from './time.js';
5
5
  export { deg2dms, deg2rad, euclidean3D, geodeticToGeohash, geodeticToMaidenhead, geodeticToUtm, greatCircleMidpoint, horizonDistance, rad2deg, rhumbLine, vincenty } from './coordinates.js';
6
6
  export { c as clampUnit, e as ecefToGeodetic, g as geodeticToEcef, a as getAer, b as getEnuDifference } from './ecef-CF0uAysr.js';
7
- export { CompactEpoch, CrxField, DiffState, EMPTY_WARNINGS, Nav4Input, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, WriteCrxOptions, createGzipLineSink, crxDecompress, crxRepair, fmtD, fmtF, hdrLine, padL, padR, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob } from './rinex.js';
7
+ export { BiasRecord, BiasSinex, CompactEpoch, CrxField, DiffState, EMPTY_WARNINGS, Nav4Input, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, WriteCrxOptions, biasMetres, createGzipLineSink, crxDecompress, crxRepair, findSatBias, fmtD, fmtF, hdrLine, padL, padR, parseBiasSinex, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob } from './rinex.js';
8
8
  export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResult, b as RinexStats, S as SYSTEM_ORDER, c as SatObsCallback, p as parseRinexStream, s as systemCmp, d as systemName } from './parser-JPjjFgeP.js';
9
9
  export { C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, R as RinexCnavEphemeris, p as parseNavFile } from './nav-DImXUdbp.js';
10
10
  export { C as ClkFile, I as IonexGrid, S as Sp3File, a as Sp3Sample, c as clkBias, p as parseClk, b as parseIonex, d as parseSp3, s as sp3Position } from './clk-DGVBGRzA.js';
@@ -17,7 +17,7 @@ export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, Trimb
17
17
  export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.js';
18
18
  export { AllPositionsData, AlmanacPosition, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.js';
19
19
  export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.js';
20
- export { AntennaOffset, CorrectionResult, DgnssOptions, DgnssSolution, EphemerisSource, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, PppAntennaModel, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, SatGeom, SppOptions, SppSolution, TropoMapping, buildPppAntenna, createPppCorrections, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch } from './positioning.js';
20
+ export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, DgnssOptions, DgnssSolution, EphemerisSource, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, PppAntennaModel, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, SatGeom, SppOptions, SppSolution, TropoMapping, buildPppAntenna, createPppCorrections, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.js';
21
21
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.js';
22
22
  export { CompleteSatSignal, CompleteSignalStats, CompletenessAccumulator, CompletenessResult, CycleSlipAccumulator, CycleSlipEvent, CycleSlipResult, CycleSlipSignalStats, IonoAccumulator, IonoDcbResult, IonoPoint, IonoRatePoint, IonoRateSeries, IonoResult, IonoSeries, MultipathAccumulator, MultipathPoint, MultipathResult, MultipathSeries, MultipathSignalStat, QualityResult, SatDcbMap, analyzeQuality, applyIonoDcb, computeIonoRate, detrendIonoArcs, parseSinexBiasDcb } from './analysis.js';
23
23
  export { AntennaEntry, AntexFile, FrequencyData, frequencyLabel, parseAntex } from './antex.js';
package/dist/index.js CHANGED
@@ -155,14 +155,17 @@ import {
155
155
  lambdaSearch,
156
156
  moonEcef,
157
157
  niellMapping,
158
+ nlWavelength,
159
+ resolvePppAmbiguities,
158
160
  satClockCorrection,
159
161
  solidEarthTide,
160
162
  solveDgnss,
161
163
  solvePpp,
162
164
  solveSpp,
163
165
  sunEcef,
164
- toRtkEpoch
165
- } from "./chunk-CRFFUU5Y.js";
166
+ toRtkEpoch,
167
+ wlWavelength
168
+ } from "./chunk-EVFD4UNZ.js";
166
169
  import {
167
170
  almanacEpochMs,
168
171
  almanacSatPosition,
@@ -201,12 +204,15 @@ import {
201
204
  import {
202
205
  EMPTY_WARNINGS,
203
206
  WarningAccumulator,
207
+ biasMetres,
204
208
  createGzipLineSink,
209
+ findSatBias,
205
210
  fmtD,
206
211
  fmtF,
207
212
  hdrLine,
208
213
  padL,
209
214
  padR,
215
+ parseBiasSinex,
210
216
  parseIonex,
211
217
  parseNavFile,
212
218
  stationHeaderLines,
@@ -217,7 +223,7 @@ import {
217
223
  writeRinexNav,
218
224
  writeRinexNav4,
219
225
  writeRinexObsBlob
220
- } from "./chunk-KDM2NVBO.js";
226
+ } from "./chunk-5RNDQQ6J.js";
221
227
  import "./chunk-726LQBGM.js";
222
228
  import "./chunk-IQ5OIMQD.js";
223
229
  import {
@@ -428,6 +434,7 @@ export {
428
434
  analyzeQuality,
429
435
  applyHelmert,
430
436
  applyIonoDcb,
437
+ biasMetres,
431
438
  binexCrc16,
432
439
  binexCrc32,
433
440
  binexCsum8,
@@ -467,6 +474,7 @@ export {
467
474
  ephInfoToEphemeris,
468
475
  euclidean3D,
469
476
  fetchSourcetable,
477
+ findSatBias,
470
478
  fmtD,
471
479
  fmtF,
472
480
  formatUTCTime,
@@ -549,11 +557,13 @@ export {
549
557
  msmEpochToDate,
550
558
  navTimesFromEph,
551
559
  niellMapping,
560
+ nlWavelength,
552
561
  nmeaCoordToDecimal,
553
562
  oem4Frames,
554
563
  padL,
555
564
  padR,
556
565
  parseAntex,
566
+ parseBiasSinex,
557
567
  parseBinex,
558
568
  parseClk,
559
569
  parseCrxDataLine,
@@ -591,6 +601,7 @@ export {
591
601
  readString,
592
602
  reportDecodeError,
593
603
  resetGloFreqCache,
604
+ resolvePppAmbiguities,
594
605
  rhumbLine,
595
606
  rtcm3Constellation,
596
607
  satClockCorrection,
@@ -616,6 +627,7 @@ export {
616
627
  updateStreamStats,
617
628
  verifyChecksum,
618
629
  vincenty,
630
+ wlWavelength,
619
631
  writeCrx,
620
632
  writeModernObsBlob,
621
633
  writeRinex2ObsBlob,
@@ -33,13 +33,16 @@ __export(positioning_exports, {
33
33
  lambdaSearch: () => lambdaSearch,
34
34
  moonEcef: () => moonEcef,
35
35
  niellMapping: () => niellMapping,
36
+ nlWavelength: () => nlWavelength,
37
+ resolvePppAmbiguities: () => resolvePppAmbiguities,
36
38
  satClockCorrection: () => satClockCorrection,
37
39
  solidEarthTide: () => solidEarthTide,
38
40
  solveDgnss: () => solveDgnss,
39
41
  solvePpp: () => solvePpp,
40
42
  solveSpp: () => solveSpp,
41
43
  sunEcef: () => sunEcef,
42
- toRtkEpoch: () => toRtkEpoch
44
+ toRtkEpoch: () => toRtkEpoch,
45
+ wlWavelength: () => wlWavelength
43
46
  });
44
47
  module.exports = __toCommonJS(positioning_exports);
45
48
 
@@ -2430,6 +2433,96 @@ function solvePpp(epochs, sp3, opts) {
2430
2433
  };
2431
2434
  }
2432
2435
 
2436
+ // src/positioning/ppp-ar.ts
2437
+ function wlWavelength(f1, f2) {
2438
+ return C_LIGHT / (f1 - f2);
2439
+ }
2440
+ function nlWavelength(f1, f2) {
2441
+ return C_LIGHT / (f1 + f2);
2442
+ }
2443
+ function resolvePppAmbiguities(sats, Qaif, opts = {}) {
2444
+ const wlThreshold = opts.wlThreshold ?? 0.25;
2445
+ const ratioThreshold = opts.ratioThreshold ?? 3;
2446
+ const kept = [];
2447
+ const nWl = [];
2448
+ const rejectedWl = [];
2449
+ for (let i = 0; i < sats.length; i++) {
2450
+ const s = sats[i];
2451
+ const wlFloat = s.mwCyc - (s.wlBiasCyc ?? 0);
2452
+ const r = Math.round(wlFloat);
2453
+ if (Math.abs(wlFloat - r) <= wlThreshold) {
2454
+ kept.push(i);
2455
+ nWl.push(r);
2456
+ } else {
2457
+ rejectedWl.push(s.prn);
2458
+ }
2459
+ }
2460
+ if (kept.length < 2) {
2461
+ return {
2462
+ fixed: false,
2463
+ ratio: 0,
2464
+ refPrn: null,
2465
+ sats: [],
2466
+ rejectedWl
2467
+ };
2468
+ }
2469
+ const n1Float = [];
2470
+ const lamNl = [];
2471
+ for (let k = 0; k < kept.length; k++) {
2472
+ const s = sats[kept[k]];
2473
+ const lNl = nlWavelength(s.f1, s.f2);
2474
+ lamNl.push(lNl);
2475
+ const n1 = s.aIF / lNl - s.f2 / (s.f1 - s.f2) * nWl[k] - (s.nlBiasCyc ?? 0);
2476
+ n1Float.push(n1);
2477
+ }
2478
+ let ref = 0;
2479
+ for (let k = 1; k < kept.length; k++) {
2480
+ const e = sats[kept[k]].elevDeg ?? -1;
2481
+ if (e > (sats[kept[ref]].elevDeg ?? -1)) ref = k;
2482
+ }
2483
+ const m = kept.length - 1;
2484
+ const sd = new Float64Array(m);
2485
+ const Qsd = new Float64Array(m * m);
2486
+ const others = [];
2487
+ for (let k = 0; k < kept.length; k++) if (k !== ref) others.push(k);
2488
+ const n = sats.length;
2489
+ const qN1 = (ka, kb) => Qaif[kept[ka] * n + kept[kb]] / (lamNl[ka] * lamNl[kb]);
2490
+ for (let a = 0; a < m; a++) {
2491
+ const ka = others[a];
2492
+ sd[a] = n1Float[ka] - n1Float[ref];
2493
+ for (let b = 0; b < m; b++) {
2494
+ const kb = others[b];
2495
+ Qsd[a * m + b] = qN1(ka, kb) - qN1(ka, ref) - qN1(ref, kb) + qN1(ref, ref);
2496
+ }
2497
+ }
2498
+ const res = lambdaSearch(sd, Qsd, m, 2);
2499
+ const ratio = res ? Math.min(res.ratio, 999.9) : 0;
2500
+ const fixed = !!res && ratio >= ratioThreshold;
2501
+ const refN1 = Math.round(n1Float[ref]);
2502
+ const sdFix = res?.candidates[0];
2503
+ const outSats = [];
2504
+ for (let k = 0; k < kept.length; k++) {
2505
+ const s = sats[kept[k]];
2506
+ let n1;
2507
+ if (k === ref) {
2508
+ n1 = refN1;
2509
+ } else {
2510
+ const a = others.indexOf(k);
2511
+ n1 = fixed && sdFix ? refN1 + Math.round(sdFix[a]) : Math.round(n1Float[k]);
2512
+ }
2513
+ const lNl = lamNl[k];
2514
+ const aIF = lNl * n1 + lNl * (s.f2 / (s.f1 - s.f2)) * nWl[k];
2515
+ outSats.push({ prn: s.prn, nWl: nWl[k], n1, aIF });
2516
+ }
2517
+ return {
2518
+ fixed,
2519
+ ratio,
2520
+ refPrn: sats[kept[ref]].prn,
2521
+ sats: outSats,
2522
+ rejectedWl
2523
+ };
2524
+ }
2525
+
2433
2526
  // src/positioning/index.ts
2434
2527
  var GM_GPS2 = 3986005e8;
2435
2528
  var F_REL = -4442807633e-19;
@@ -2672,11 +2765,14 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
2672
2765
  lambdaSearch,
2673
2766
  moonEcef,
2674
2767
  niellMapping,
2768
+ nlWavelength,
2769
+ resolvePppAmbiguities,
2675
2770
  satClockCorrection,
2676
2771
  solidEarthTide,
2677
2772
  solveDgnss,
2678
2773
  solvePpp,
2679
2774
  solveSpp,
2680
2775
  sunEcef,
2681
- toRtkEpoch
2776
+ toRtkEpoch,
2777
+ wlWavelength
2682
2778
  });
@@ -714,6 +714,85 @@ declare function moonEcef(timeMs: number): [number, number, number];
714
714
  */
715
715
  declare function solidEarthTide(rcv: [number, number, number], sun: [number, number, number], moon: [number, number, number]): [number, number, number];
716
716
 
717
+ /**
718
+ * PPP-AR — integer ambiguity resolution for Precise Point Positioning.
719
+ *
720
+ * Float PPP estimates one *ionosphere-free* ambiguity per satellite arc, a
721
+ * real number in metres. Fixing those to integers is what takes PPP from the
722
+ * decimetre to the centimetre level. The classic two-step decomposition is
723
+ * used here:
724
+ *
725
+ * 1. **Wide-lane** N_WL = N1 − N2 from the Melbourne–Wübbena combination.
726
+ * The WL wavelength is ~86 cm (GPS), so the arc-averaged MW rounds to an
727
+ * integer reliably once the satellite WL fractional-cycle bias is removed.
728
+ * 2. **Narrow-lane** N1, recovered from the float IF ambiguity with N_WL
729
+ * fixed, then resolved with LAMBDA on *between-satellite single
730
+ * differences* (which cancel the receiver phase bias) after removing the
731
+ * satellite NL fractional-cycle bias.
732
+ *
733
+ * The satellite WL/NL fractional-cycle biases come from a phase-bias product
734
+ * (Bias-SINEX OSB from an AR-capable analysis centre such as CNES or CODE).
735
+ * Without them, a single receiver cannot separate the satellite bias from the
736
+ * integer, so those biases are required inputs — pass 0 only for a network
737
+ * datum where they have already been removed.
738
+ *
739
+ * The relation between the IF ambiguity (metres) and the integers is
740
+ * A_IF = λ_NL·N1 + λ_NL·(f2/(f1−f2))·N_WL, λ_NL = c/(f1+f2).
741
+ */
742
+ /** Wide-lane wavelength c/(f1−f2) (m). */
743
+ declare function wlWavelength(f1: number, f2: number): number;
744
+ /** Narrow-lane wavelength c/(f1+f2) (m). */
745
+ declare function nlWavelength(f1: number, f2: number): number;
746
+ /** One satellite's float ambiguity inputs for AR. */
747
+ interface ArSat {
748
+ prn: string;
749
+ /** Float ionosphere-free ambiguity (m) from the PPP EKF. */
750
+ aIF: number;
751
+ /** Arc-averaged Melbourne–Wübbena wide-lane estimate (cycles). */
752
+ mwCyc: number;
753
+ f1: number;
754
+ f2: number;
755
+ /** Satellite wide-lane fractional-cycle bias (cycles). Default 0. */
756
+ wlBiasCyc?: number;
757
+ /** Satellite narrow-lane fractional-cycle bias (cycles). Default 0. */
758
+ nlBiasCyc?: number;
759
+ /** Elevation (deg), used only to pick the reference satellite. */
760
+ elevDeg?: number;
761
+ }
762
+ interface ArOptions {
763
+ /** Max |MW − round| to accept a wide-lane (cycles). Default 0.25. */
764
+ wlThreshold?: number;
765
+ /** Min LAMBDA ratio to accept the narrow-lane fix. Default 3. */
766
+ ratioThreshold?: number;
767
+ }
768
+ interface ArFixedSat {
769
+ prn: string;
770
+ nWl: number;
771
+ n1: number;
772
+ /** Fixed IF ambiguity (m). */
773
+ aIF: number;
774
+ }
775
+ interface ArResult {
776
+ /** Whether the narrow-lane fix passed the ratio test. */
777
+ fixed: boolean;
778
+ /** LAMBDA ratio statistic (second-best / best). */
779
+ ratio: number;
780
+ /** Reference PRN whose absolute N1 stays float (SD datum). */
781
+ refPrn: string | null;
782
+ /** Fixed satellites (includes the reference with its float-rounded N1). */
783
+ sats: ArFixedSat[];
784
+ /** PRNs whose wide-lane did not round confidently (excluded). */
785
+ rejectedWl: string[];
786
+ }
787
+ /**
788
+ * Resolve PPP integer ambiguities from the float IF ambiguities and their
789
+ * covariance. `Qaif` is the n×n float covariance (m²) in the same order as
790
+ * `sats`. Returns the fixed narrow-lane / wide-lane integers and the ratio
791
+ * test result. A `fixed: false` result means the data did not support a
792
+ * confident fix (keep the float solution).
793
+ */
794
+ declare function resolvePppAmbiguities(sats: ArSat[], Qaif: Float64Array, opts?: ArOptions): ArResult;
795
+
717
796
  /**
718
797
  * Single-point positioning (SPP) from pseudoranges and broadcast
719
798
  * ephemerides.
@@ -803,4 +882,4 @@ declare function ionoFree(p1: number, p2: number, f1: number, f2: number): numbe
803
882
  */
804
883
  declare function solveSpp(pseudoranges: Map<string, number>, ephemerides: Map<string, Ephemeris>, timeMs: number, opts?: SppOptions): SppSolution | null;
805
884
 
806
- export { type AntennaOffset, type CorrectionResult, type DgnssOptions, type DgnssSolution, type EphemerisSource, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type PppAntennaModel, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type SatGeom, type SppOptions, type SppSolution, type TropoMapping, buildPppAntenna, createPppCorrections, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch };
885
+ export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, type DgnssOptions, type DgnssSolution, type EphemerisSource, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type PppAntennaModel, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type SatGeom, type SppOptions, type SppSolution, type TropoMapping, buildPppAntenna, createPppCorrections, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
@@ -714,6 +714,85 @@ declare function moonEcef(timeMs: number): [number, number, number];
714
714
  */
715
715
  declare function solidEarthTide(rcv: [number, number, number], sun: [number, number, number], moon: [number, number, number]): [number, number, number];
716
716
 
717
+ /**
718
+ * PPP-AR — integer ambiguity resolution for Precise Point Positioning.
719
+ *
720
+ * Float PPP estimates one *ionosphere-free* ambiguity per satellite arc, a
721
+ * real number in metres. Fixing those to integers is what takes PPP from the
722
+ * decimetre to the centimetre level. The classic two-step decomposition is
723
+ * used here:
724
+ *
725
+ * 1. **Wide-lane** N_WL = N1 − N2 from the Melbourne–Wübbena combination.
726
+ * The WL wavelength is ~86 cm (GPS), so the arc-averaged MW rounds to an
727
+ * integer reliably once the satellite WL fractional-cycle bias is removed.
728
+ * 2. **Narrow-lane** N1, recovered from the float IF ambiguity with N_WL
729
+ * fixed, then resolved with LAMBDA on *between-satellite single
730
+ * differences* (which cancel the receiver phase bias) after removing the
731
+ * satellite NL fractional-cycle bias.
732
+ *
733
+ * The satellite WL/NL fractional-cycle biases come from a phase-bias product
734
+ * (Bias-SINEX OSB from an AR-capable analysis centre such as CNES or CODE).
735
+ * Without them, a single receiver cannot separate the satellite bias from the
736
+ * integer, so those biases are required inputs — pass 0 only for a network
737
+ * datum where they have already been removed.
738
+ *
739
+ * The relation between the IF ambiguity (metres) and the integers is
740
+ * A_IF = λ_NL·N1 + λ_NL·(f2/(f1−f2))·N_WL, λ_NL = c/(f1+f2).
741
+ */
742
+ /** Wide-lane wavelength c/(f1−f2) (m). */
743
+ declare function wlWavelength(f1: number, f2: number): number;
744
+ /** Narrow-lane wavelength c/(f1+f2) (m). */
745
+ declare function nlWavelength(f1: number, f2: number): number;
746
+ /** One satellite's float ambiguity inputs for AR. */
747
+ interface ArSat {
748
+ prn: string;
749
+ /** Float ionosphere-free ambiguity (m) from the PPP EKF. */
750
+ aIF: number;
751
+ /** Arc-averaged Melbourne–Wübbena wide-lane estimate (cycles). */
752
+ mwCyc: number;
753
+ f1: number;
754
+ f2: number;
755
+ /** Satellite wide-lane fractional-cycle bias (cycles). Default 0. */
756
+ wlBiasCyc?: number;
757
+ /** Satellite narrow-lane fractional-cycle bias (cycles). Default 0. */
758
+ nlBiasCyc?: number;
759
+ /** Elevation (deg), used only to pick the reference satellite. */
760
+ elevDeg?: number;
761
+ }
762
+ interface ArOptions {
763
+ /** Max |MW − round| to accept a wide-lane (cycles). Default 0.25. */
764
+ wlThreshold?: number;
765
+ /** Min LAMBDA ratio to accept the narrow-lane fix. Default 3. */
766
+ ratioThreshold?: number;
767
+ }
768
+ interface ArFixedSat {
769
+ prn: string;
770
+ nWl: number;
771
+ n1: number;
772
+ /** Fixed IF ambiguity (m). */
773
+ aIF: number;
774
+ }
775
+ interface ArResult {
776
+ /** Whether the narrow-lane fix passed the ratio test. */
777
+ fixed: boolean;
778
+ /** LAMBDA ratio statistic (second-best / best). */
779
+ ratio: number;
780
+ /** Reference PRN whose absolute N1 stays float (SD datum). */
781
+ refPrn: string | null;
782
+ /** Fixed satellites (includes the reference with its float-rounded N1). */
783
+ sats: ArFixedSat[];
784
+ /** PRNs whose wide-lane did not round confidently (excluded). */
785
+ rejectedWl: string[];
786
+ }
787
+ /**
788
+ * Resolve PPP integer ambiguities from the float IF ambiguities and their
789
+ * covariance. `Qaif` is the n×n float covariance (m²) in the same order as
790
+ * `sats`. Returns the fixed narrow-lane / wide-lane integers and the ratio
791
+ * test result. A `fixed: false` result means the data did not support a
792
+ * confident fix (keep the float solution).
793
+ */
794
+ declare function resolvePppAmbiguities(sats: ArSat[], Qaif: Float64Array, opts?: ArOptions): ArResult;
795
+
717
796
  /**
718
797
  * Single-point positioning (SPP) from pseudoranges and broadcast
719
798
  * ephemerides.
@@ -803,4 +882,4 @@ declare function ionoFree(p1: number, p2: number, f1: number, f2: number): numbe
803
882
  */
804
883
  declare function solveSpp(pseudoranges: Map<string, number>, ephemerides: Map<string, Ephemeris>, timeMs: number, opts?: SppOptions): SppSolution | null;
805
884
 
806
- export { type AntennaOffset, type CorrectionResult, type DgnssOptions, type DgnssSolution, type EphemerisSource, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type PppAntennaModel, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type SatGeom, type SppOptions, type SppSolution, type TropoMapping, buildPppAntenna, createPppCorrections, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch };
885
+ export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, type DgnssOptions, type DgnssSolution, type EphemerisSource, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type PppAntennaModel, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type SatGeom, type SppOptions, type SppSolution, type TropoMapping, buildPppAntenna, createPppCorrections, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
@@ -12,14 +12,17 @@ import {
12
12
  lambdaSearch,
13
13
  moonEcef,
14
14
  niellMapping,
15
+ nlWavelength,
16
+ resolvePppAmbiguities,
15
17
  satClockCorrection,
16
18
  solidEarthTide,
17
19
  solveDgnss,
18
20
  solvePpp,
19
21
  solveSpp,
20
22
  sunEcef,
21
- toRtkEpoch
22
- } from "./chunk-CRFFUU5Y.js";
23
+ toRtkEpoch,
24
+ wlWavelength
25
+ } from "./chunk-EVFD4UNZ.js";
23
26
  import "./chunk-MHGNKSSH.js";
24
27
  import "./chunk-37QNKGTC.js";
25
28
  import "./chunk-6FAL6P4G.js";
@@ -41,11 +44,14 @@ export {
41
44
  lambdaSearch,
42
45
  moonEcef,
43
46
  niellMapping,
47
+ nlWavelength,
48
+ resolvePppAmbiguities,
44
49
  satClockCorrection,
45
50
  solidEarthTide,
46
51
  solveDgnss,
47
52
  solvePpp,
48
53
  solveSpp,
49
54
  sunEcef,
50
- toRtkEpoch
55
+ toRtkEpoch,
56
+ wlWavelength
51
57
  };
package/dist/rinex.cjs CHANGED
@@ -23,15 +23,18 @@ __export(rinex_exports, {
23
23
  EMPTY_WARNINGS: () => EMPTY_WARNINGS,
24
24
  SYSTEM_ORDER: () => SYSTEM_ORDER,
25
25
  WarningAccumulator: () => WarningAccumulator,
26
+ biasMetres: () => biasMetres,
26
27
  clkBias: () => clkBias,
27
28
  createGzipLineSink: () => createGzipLineSink,
28
29
  crxDecompress: () => crxDecompress,
29
30
  crxRepair: () => crxRepair,
31
+ findSatBias: () => findSatBias,
30
32
  fmtD: () => fmtD,
31
33
  fmtF: () => fmtF,
32
34
  hdrLine: () => hdrLine,
33
35
  padL: () => padL,
34
36
  padR: () => padR,
37
+ parseBiasSinex: () => parseBiasSinex,
35
38
  parseClk: () => parseClk,
36
39
  parseCrxDataLine: () => parseCrxDataLine,
37
40
  parseIonex: () => parseIonex,
@@ -597,6 +600,7 @@ var SYSTEM_NAMES = {
597
600
  I: "NavIC",
598
601
  S: "SBAS"
599
602
  };
603
+ var C_LIGHT = 299792458;
600
604
 
601
605
  // src/rinex/parser.ts
602
606
  var CHUNK_SIZE = 2 * 1024 * 1024;
@@ -2450,6 +2454,81 @@ function clkBias(clk, prn, tMs) {
2450
2454
  return c[lo] + f * (c[lo + 1] - c[lo]);
2451
2455
  }
2452
2456
 
2457
+ // src/rinex/bias-sinex.ts
2458
+ function parseEpoch(s, openTo) {
2459
+ const m = /^(\d{4}):(\d{3}):(\d{5})$/.exec(s.trim());
2460
+ if (!m) return openTo;
2461
+ const y = +m[1];
2462
+ if (y === 0) return openTo;
2463
+ const doy = +m[2];
2464
+ const sod = +m[3];
2465
+ return Date.UTC(y, 0, 1) + (doy - 1) * 864e5 + sod * 1e3;
2466
+ }
2467
+ function parseBiasSinex(text) {
2468
+ const records = [];
2469
+ let inBlock = false;
2470
+ for (const line of text.split("\n")) {
2471
+ if (line.startsWith("+BIAS/SOLUTION")) {
2472
+ inBlock = true;
2473
+ continue;
2474
+ }
2475
+ if (line.startsWith("-BIAS/SOLUTION")) {
2476
+ inBlock = false;
2477
+ continue;
2478
+ }
2479
+ if (!inBlock || line.length < 65 || line.startsWith("*")) continue;
2480
+ const type = line.slice(1, 4).trim();
2481
+ if (type !== "DSB" && type !== "OSB" && type !== "ISB") continue;
2482
+ const prn = line.slice(11, 14).trim();
2483
+ const station = line.slice(15, 24).trim();
2484
+ const obs1 = line.slice(25, 29).trim();
2485
+ const obs2 = line.slice(30, 34).trim();
2486
+ const startMs = parseEpoch(line.slice(35, 49), -Infinity);
2487
+ const endMs = parseEpoch(line.slice(50, 64), Infinity);
2488
+ const tail = line.slice(65).trim().split(/\s+/);
2489
+ if (tail.length < 2) continue;
2490
+ const unit = tail[0];
2491
+ const value = Number(tail[1]);
2492
+ if (!Number.isFinite(value)) continue;
2493
+ records.push({
2494
+ type,
2495
+ prn,
2496
+ station,
2497
+ obs1,
2498
+ obs2,
2499
+ startMs,
2500
+ endMs,
2501
+ value,
2502
+ unit
2503
+ });
2504
+ }
2505
+ const bySat = /* @__PURE__ */ new Map();
2506
+ for (const r of records) {
2507
+ if (!r.prn || r.station) continue;
2508
+ let a = bySat.get(r.prn);
2509
+ if (!a) {
2510
+ a = [];
2511
+ bySat.set(r.prn, a);
2512
+ }
2513
+ a.push(r);
2514
+ }
2515
+ return { records, bySat };
2516
+ }
2517
+ function biasMetres(r) {
2518
+ return r.unit === "ns" ? r.value * 1e-9 * C_LIGHT : r.value;
2519
+ }
2520
+ function findSatBias(bias, prn, obs1, obs2, tMs) {
2521
+ const recs = bias.bySat.get(prn);
2522
+ if (!recs) return null;
2523
+ for (const r of recs) {
2524
+ if (r.obs1 !== obs1) continue;
2525
+ if (obs2 === void 0 ? r.obs2 !== "" : r.obs2 !== obs2) continue;
2526
+ if (tMs != null && (tMs < r.startMs || tMs > r.endMs)) continue;
2527
+ return r;
2528
+ }
2529
+ return null;
2530
+ }
2531
+
2453
2532
  // src/rinex/obs-writer-common.ts
2454
2533
  function createGzipLineSink() {
2455
2534
  const encoder = new TextEncoder();
@@ -2828,15 +2907,18 @@ function writeRinex4ObsBlob(header, epochs, obsTypes) {
2828
2907
  EMPTY_WARNINGS,
2829
2908
  SYSTEM_ORDER,
2830
2909
  WarningAccumulator,
2910
+ biasMetres,
2831
2911
  clkBias,
2832
2912
  createGzipLineSink,
2833
2913
  crxDecompress,
2834
2914
  crxRepair,
2915
+ findSatBias,
2835
2916
  fmtD,
2836
2917
  fmtF,
2837
2918
  hdrLine,
2838
2919
  padL,
2839
2920
  padR,
2921
+ parseBiasSinex,
2840
2922
  parseClk,
2841
2923
  parseCrxDataLine,
2842
2924
  parseIonex,
package/dist/rinex.d.cts CHANGED
@@ -182,6 +182,54 @@ interface Nav4Input {
182
182
  */
183
183
  declare function writeRinexNav4(nav: Nav4Input): string;
184
184
 
185
+ /**
186
+ * Bias-SINEX (`.BIA`) parser — GNSS code/phase biases published by the IGS
187
+ * analysis centres. Two record kinds matter here:
188
+ *
189
+ * - **DSB** differential signal bias (OBS1−OBS2), the classic inter-code
190
+ * bias used for ionosphere/DCB corrections in SPP.
191
+ * - **OSB** observable-specific (absolute) bias for a single OBS, the
192
+ * ingredient PPP-AR needs: the *phase* OSBs are the satellite
193
+ * fractional-cycle biases that make the ambiguities integer-recoverable.
194
+ *
195
+ * Values keep their file unit (`ns` for code/most phase biases, `cyc` for
196
+ * cycle-based phase biases); `biasMetres` converts ns → m via c.
197
+ */
198
+ interface BiasRecord {
199
+ /** 'DSB' | 'OSB' | 'ISB' | … */
200
+ type: string;
201
+ /** Satellite PRN (e.g. 'G01', 'E11'); '' for a pure station bias. */
202
+ prn: string;
203
+ /** Station (9-char), '' for satellite biases. */
204
+ station: string;
205
+ /** First observable code (e.g. 'C1W', 'L1C'). */
206
+ obs1: string;
207
+ /** Second observable (DSB only; '' for OSB). */
208
+ obs2: string;
209
+ /** Validity start / end (GPS-scale ms); ±Infinity when open. */
210
+ startMs: number;
211
+ endMs: number;
212
+ /** Estimated value in the file unit. */
213
+ value: number;
214
+ /** File unit ('ns' | 'cyc' | …). */
215
+ unit: string;
216
+ }
217
+ interface BiasSinex {
218
+ records: BiasRecord[];
219
+ /** All satellite records grouped by PRN (station === ''). */
220
+ bySat: Map<string, BiasRecord[]>;
221
+ }
222
+ /** Parse a Bias-SINEX file. */
223
+ declare function parseBiasSinex(text: string): BiasSinex;
224
+ /** A satellite bias record's value in metres (ns → m via c; cyc left as-is). */
225
+ declare function biasMetres(r: BiasRecord): number;
226
+ /**
227
+ * Look up a satellite bias: a DSB by its (obs1,obs2) pair, or an OSB by obs1
228
+ * alone (pass obs2 = undefined), valid at `tMs` (default: any). Returns the
229
+ * record or null.
230
+ */
231
+ declare function findSatBias(bias: BiasSinex, prn: string, obs1: string, obs2?: string, tMs?: number): BiasRecord | null;
232
+
185
233
  /**
186
234
  * RINEX 3.04 / 4.01 observation file writer.
187
235
  *
@@ -263,4 +311,4 @@ declare function createGzipLineSink(): {
263
311
  */
264
312
  declare function stationHeaderLines(header: RinexHeader): string[];
265
313
 
266
- export { type CompactEpoch, type CrxField, type DiffState, EMPTY_WARNINGS, Ephemeris, type Nav4Input, NavHeader, NavResult, RinexCnavEphemeris, RinexHeader, type RinexWarning, type RinexWarnings, WarningAccumulator, type WarningSeverity, type WriteCrxOptions, createGzipLineSink, crxDecompress, crxRepair, fmtD, fmtF, hdrLine, padL, padR, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob };
314
+ export { type BiasRecord, type BiasSinex, type CompactEpoch, type CrxField, type DiffState, EMPTY_WARNINGS, Ephemeris, type Nav4Input, NavHeader, NavResult, RinexCnavEphemeris, RinexHeader, type RinexWarning, type RinexWarnings, WarningAccumulator, type WarningSeverity, type WriteCrxOptions, biasMetres, createGzipLineSink, crxDecompress, crxRepair, findSatBias, fmtD, fmtF, hdrLine, padL, padR, parseBiasSinex, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob };
package/dist/rinex.d.ts CHANGED
@@ -182,6 +182,54 @@ interface Nav4Input {
182
182
  */
183
183
  declare function writeRinexNav4(nav: Nav4Input): string;
184
184
 
185
+ /**
186
+ * Bias-SINEX (`.BIA`) parser — GNSS code/phase biases published by the IGS
187
+ * analysis centres. Two record kinds matter here:
188
+ *
189
+ * - **DSB** differential signal bias (OBS1−OBS2), the classic inter-code
190
+ * bias used for ionosphere/DCB corrections in SPP.
191
+ * - **OSB** observable-specific (absolute) bias for a single OBS, the
192
+ * ingredient PPP-AR needs: the *phase* OSBs are the satellite
193
+ * fractional-cycle biases that make the ambiguities integer-recoverable.
194
+ *
195
+ * Values keep their file unit (`ns` for code/most phase biases, `cyc` for
196
+ * cycle-based phase biases); `biasMetres` converts ns → m via c.
197
+ */
198
+ interface BiasRecord {
199
+ /** 'DSB' | 'OSB' | 'ISB' | … */
200
+ type: string;
201
+ /** Satellite PRN (e.g. 'G01', 'E11'); '' for a pure station bias. */
202
+ prn: string;
203
+ /** Station (9-char), '' for satellite biases. */
204
+ station: string;
205
+ /** First observable code (e.g. 'C1W', 'L1C'). */
206
+ obs1: string;
207
+ /** Second observable (DSB only; '' for OSB). */
208
+ obs2: string;
209
+ /** Validity start / end (GPS-scale ms); ±Infinity when open. */
210
+ startMs: number;
211
+ endMs: number;
212
+ /** Estimated value in the file unit. */
213
+ value: number;
214
+ /** File unit ('ns' | 'cyc' | …). */
215
+ unit: string;
216
+ }
217
+ interface BiasSinex {
218
+ records: BiasRecord[];
219
+ /** All satellite records grouped by PRN (station === ''). */
220
+ bySat: Map<string, BiasRecord[]>;
221
+ }
222
+ /** Parse a Bias-SINEX file. */
223
+ declare function parseBiasSinex(text: string): BiasSinex;
224
+ /** A satellite bias record's value in metres (ns → m via c; cyc left as-is). */
225
+ declare function biasMetres(r: BiasRecord): number;
226
+ /**
227
+ * Look up a satellite bias: a DSB by its (obs1,obs2) pair, or an OSB by obs1
228
+ * alone (pass obs2 = undefined), valid at `tMs` (default: any). Returns the
229
+ * record or null.
230
+ */
231
+ declare function findSatBias(bias: BiasSinex, prn: string, obs1: string, obs2?: string, tMs?: number): BiasRecord | null;
232
+
185
233
  /**
186
234
  * RINEX 3.04 / 4.01 observation file writer.
187
235
  *
@@ -263,4 +311,4 @@ declare function createGzipLineSink(): {
263
311
  */
264
312
  declare function stationHeaderLines(header: RinexHeader): string[];
265
313
 
266
- export { type CompactEpoch, type CrxField, type DiffState, EMPTY_WARNINGS, Ephemeris, type Nav4Input, NavHeader, NavResult, RinexCnavEphemeris, RinexHeader, type RinexWarning, type RinexWarnings, WarningAccumulator, type WarningSeverity, type WriteCrxOptions, createGzipLineSink, crxDecompress, crxRepair, fmtD, fmtF, hdrLine, padL, padR, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob };
314
+ export { type BiasRecord, type BiasSinex, type CompactEpoch, type CrxField, type DiffState, EMPTY_WARNINGS, Ephemeris, type Nav4Input, NavHeader, NavResult, RinexCnavEphemeris, RinexHeader, type RinexWarning, type RinexWarnings, WarningAccumulator, type WarningSeverity, type WriteCrxOptions, biasMetres, createGzipLineSink, crxDecompress, crxRepair, findSatBias, fmtD, fmtF, hdrLine, padL, padR, parseBiasSinex, parseCrxDataLine, stationHeaderLines, writeCrx, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob };
package/dist/rinex.js CHANGED
@@ -1,12 +1,15 @@
1
1
  import {
2
2
  EMPTY_WARNINGS,
3
3
  WarningAccumulator,
4
+ biasMetres,
4
5
  createGzipLineSink,
6
+ findSatBias,
5
7
  fmtD,
6
8
  fmtF,
7
9
  hdrLine,
8
10
  padL,
9
11
  padR,
12
+ parseBiasSinex,
10
13
  parseIonex,
11
14
  parseNavFile,
12
15
  stationHeaderLines,
@@ -17,7 +20,7 @@ import {
17
20
  writeRinexNav,
18
21
  writeRinexNav4,
19
22
  writeRinexObsBlob
20
- } from "./chunk-KDM2NVBO.js";
23
+ } from "./chunk-5RNDQQ6J.js";
21
24
  import "./chunk-726LQBGM.js";
22
25
  import "./chunk-IQ5OIMQD.js";
23
26
  import {
@@ -40,15 +43,18 @@ export {
40
43
  EMPTY_WARNINGS,
41
44
  SYSTEM_ORDER,
42
45
  WarningAccumulator,
46
+ biasMetres,
43
47
  clkBias,
44
48
  createGzipLineSink,
45
49
  crxDecompress,
46
50
  crxRepair,
51
+ findSatBias,
47
52
  fmtD,
48
53
  fmtF,
49
54
  hdrLine,
50
55
  padL,
51
56
  padR,
57
+ parseBiasSinex,
52
58
  parseClk,
53
59
  parseCrxDataLine,
54
60
  parseIonex,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gnss-js",
3
- "version": "1.30.0",
3
+ "version": "1.31.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,