gnss-js 1.30.0 → 1.32.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.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, WlArc, WlFcbOptions, WlFcbResult, WlObs, buildPppAntenna, createPppCorrections, estimateWidelaneFcb, extractWidelaneArcs, 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, WlArc, WlFcbOptions, WlFcbResult, WlObs, buildPppAntenna, createPppCorrections, estimateWidelaneFcb, extractWidelaneArcs, 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
@@ -146,6 +146,8 @@ import {
146
146
  RtkFloatEngine,
147
147
  buildPppAntenna,
148
148
  createPppCorrections,
149
+ estimateWidelaneFcb,
150
+ extractWidelaneArcs,
149
151
  gimSlantIonoDelayL1,
150
152
  gimVerticalTec,
151
153
  gmst,
@@ -155,14 +157,17 @@ import {
155
157
  lambdaSearch,
156
158
  moonEcef,
157
159
  niellMapping,
160
+ nlWavelength,
161
+ resolvePppAmbiguities,
158
162
  satClockCorrection,
159
163
  solidEarthTide,
160
164
  solveDgnss,
161
165
  solvePpp,
162
166
  solveSpp,
163
167
  sunEcef,
164
- toRtkEpoch
165
- } from "./chunk-CRFFUU5Y.js";
168
+ toRtkEpoch,
169
+ wlWavelength
170
+ } from "./chunk-HOH27N42.js";
166
171
  import {
167
172
  almanacEpochMs,
168
173
  almanacSatPosition,
@@ -201,12 +206,15 @@ import {
201
206
  import {
202
207
  EMPTY_WARNINGS,
203
208
  WarningAccumulator,
209
+ biasMetres,
204
210
  createGzipLineSink,
211
+ findSatBias,
205
212
  fmtD,
206
213
  fmtF,
207
214
  hdrLine,
208
215
  padL,
209
216
  padR,
217
+ parseBiasSinex,
210
218
  parseIonex,
211
219
  parseNavFile,
212
220
  stationHeaderLines,
@@ -217,7 +225,7 @@ import {
217
225
  writeRinexNav,
218
226
  writeRinexNav4,
219
227
  writeRinexObsBlob
220
- } from "./chunk-KDM2NVBO.js";
228
+ } from "./chunk-5RNDQQ6J.js";
221
229
  import "./chunk-726LQBGM.js";
222
230
  import "./chunk-IQ5OIMQD.js";
223
231
  import {
@@ -428,6 +436,7 @@ export {
428
436
  analyzeQuality,
429
437
  applyHelmert,
430
438
  applyIonoDcb,
439
+ biasMetres,
431
440
  binexCrc16,
432
441
  binexCrc32,
433
442
  binexCsum8,
@@ -465,8 +474,11 @@ export {
465
474
  ecefToAzEl,
466
475
  ecefToGeodetic,
467
476
  ephInfoToEphemeris,
477
+ estimateWidelaneFcb,
468
478
  euclidean3D,
479
+ extractWidelaneArcs,
469
480
  fetchSourcetable,
481
+ findSatBias,
470
482
  fmtD,
471
483
  fmtF,
472
484
  formatUTCTime,
@@ -549,11 +561,13 @@ export {
549
561
  msmEpochToDate,
550
562
  navTimesFromEph,
551
563
  niellMapping,
564
+ nlWavelength,
552
565
  nmeaCoordToDecimal,
553
566
  oem4Frames,
554
567
  padL,
555
568
  padR,
556
569
  parseAntex,
570
+ parseBiasSinex,
557
571
  parseBinex,
558
572
  parseClk,
559
573
  parseCrxDataLine,
@@ -591,6 +605,7 @@ export {
591
605
  readString,
592
606
  reportDecodeError,
593
607
  resetGloFreqCache,
608
+ resolvePppAmbiguities,
594
609
  rhumbLine,
595
610
  rtcm3Constellation,
596
611
  satClockCorrection,
@@ -616,6 +631,7 @@ export {
616
631
  updateStreamStats,
617
632
  verifyChecksum,
618
633
  vincenty,
634
+ wlWavelength,
619
635
  writeCrx,
620
636
  writeModernObsBlob,
621
637
  writeRinex2ObsBlob,
@@ -24,6 +24,8 @@ __export(positioning_exports, {
24
24
  RtkFloatEngine: () => RtkFloatEngine,
25
25
  buildPppAntenna: () => buildPppAntenna,
26
26
  createPppCorrections: () => createPppCorrections,
27
+ estimateWidelaneFcb: () => estimateWidelaneFcb,
28
+ extractWidelaneArcs: () => extractWidelaneArcs,
27
29
  gimSlantIonoDelayL1: () => gimSlantIonoDelayL1,
28
30
  gimVerticalTec: () => gimVerticalTec,
29
31
  gmst: () => gmst,
@@ -33,13 +35,16 @@ __export(positioning_exports, {
33
35
  lambdaSearch: () => lambdaSearch,
34
36
  moonEcef: () => moonEcef,
35
37
  niellMapping: () => niellMapping,
38
+ nlWavelength: () => nlWavelength,
39
+ resolvePppAmbiguities: () => resolvePppAmbiguities,
36
40
  satClockCorrection: () => satClockCorrection,
37
41
  solidEarthTide: () => solidEarthTide,
38
42
  solveDgnss: () => solveDgnss,
39
43
  solvePpp: () => solvePpp,
40
44
  solveSpp: () => solveSpp,
41
45
  sunEcef: () => sunEcef,
42
- toRtkEpoch: () => toRtkEpoch
46
+ toRtkEpoch: () => toRtkEpoch,
47
+ wlWavelength: () => wlWavelength
43
48
  });
44
49
  module.exports = __toCommonJS(positioning_exports);
45
50
 
@@ -2430,6 +2435,212 @@ function solvePpp(epochs, sp3, opts) {
2430
2435
  };
2431
2436
  }
2432
2437
 
2438
+ // src/positioning/ppp-ar.ts
2439
+ function wlWavelength(f1, f2) {
2440
+ return C_LIGHT / (f1 - f2);
2441
+ }
2442
+ function nlWavelength(f1, f2) {
2443
+ return C_LIGHT / (f1 + f2);
2444
+ }
2445
+ function resolvePppAmbiguities(sats, Qaif, opts = {}) {
2446
+ const wlThreshold = opts.wlThreshold ?? 0.25;
2447
+ const ratioThreshold = opts.ratioThreshold ?? 3;
2448
+ const kept = [];
2449
+ const nWl = [];
2450
+ const rejectedWl = [];
2451
+ for (let i = 0; i < sats.length; i++) {
2452
+ const s = sats[i];
2453
+ const wlFloat = s.mwCyc - (s.wlBiasCyc ?? 0);
2454
+ const r = Math.round(wlFloat);
2455
+ if (Math.abs(wlFloat - r) <= wlThreshold) {
2456
+ kept.push(i);
2457
+ nWl.push(r);
2458
+ } else {
2459
+ rejectedWl.push(s.prn);
2460
+ }
2461
+ }
2462
+ if (kept.length < 2) {
2463
+ return {
2464
+ fixed: false,
2465
+ ratio: 0,
2466
+ refPrn: null,
2467
+ sats: [],
2468
+ rejectedWl
2469
+ };
2470
+ }
2471
+ const n1Float = [];
2472
+ const lamNl = [];
2473
+ for (let k = 0; k < kept.length; k++) {
2474
+ const s = sats[kept[k]];
2475
+ const lNl = nlWavelength(s.f1, s.f2);
2476
+ lamNl.push(lNl);
2477
+ const n1 = s.aIF / lNl - s.f2 / (s.f1 - s.f2) * nWl[k] - (s.nlBiasCyc ?? 0);
2478
+ n1Float.push(n1);
2479
+ }
2480
+ let ref = 0;
2481
+ for (let k = 1; k < kept.length; k++) {
2482
+ const e = sats[kept[k]].elevDeg ?? -1;
2483
+ if (e > (sats[kept[ref]].elevDeg ?? -1)) ref = k;
2484
+ }
2485
+ const m = kept.length - 1;
2486
+ const sd = new Float64Array(m);
2487
+ const Qsd = new Float64Array(m * m);
2488
+ const others = [];
2489
+ for (let k = 0; k < kept.length; k++) if (k !== ref) others.push(k);
2490
+ const n = sats.length;
2491
+ const qN1 = (ka, kb) => Qaif[kept[ka] * n + kept[kb]] / (lamNl[ka] * lamNl[kb]);
2492
+ for (let a = 0; a < m; a++) {
2493
+ const ka = others[a];
2494
+ sd[a] = n1Float[ka] - n1Float[ref];
2495
+ for (let b = 0; b < m; b++) {
2496
+ const kb = others[b];
2497
+ Qsd[a * m + b] = qN1(ka, kb) - qN1(ka, ref) - qN1(ref, kb) + qN1(ref, ref);
2498
+ }
2499
+ }
2500
+ const res = lambdaSearch(sd, Qsd, m, 2);
2501
+ const ratio = res ? Math.min(res.ratio, 999.9) : 0;
2502
+ const fixed = !!res && ratio >= ratioThreshold;
2503
+ const refN1 = Math.round(n1Float[ref]);
2504
+ const sdFix = res?.candidates[0];
2505
+ const outSats = [];
2506
+ for (let k = 0; k < kept.length; k++) {
2507
+ const s = sats[kept[k]];
2508
+ let n1;
2509
+ if (k === ref) {
2510
+ n1 = refN1;
2511
+ } else {
2512
+ const a = others.indexOf(k);
2513
+ n1 = fixed && sdFix ? refN1 + Math.round(sdFix[a]) : Math.round(n1Float[k]);
2514
+ }
2515
+ const lNl = lamNl[k];
2516
+ const aIF = lNl * n1 + lNl * (s.f2 / (s.f1 - s.f2)) * nWl[k];
2517
+ outSats.push({ prn: s.prn, nWl: nWl[k], n1, aIF });
2518
+ }
2519
+ return {
2520
+ fixed,
2521
+ ratio,
2522
+ refPrn: sats[kept[ref]].prn,
2523
+ sats: outSats,
2524
+ rejectedWl
2525
+ };
2526
+ }
2527
+
2528
+ // src/positioning/ppp-fcb.ts
2529
+ function extractWidelaneArcs(station, epochs, opts = {}) {
2530
+ const slipCyc = opts.slipCyc ?? 4;
2531
+ const gapMs = opts.gapMs ?? 12e4;
2532
+ const minObs = opts.minObs ?? 20;
2533
+ const state = /* @__PURE__ */ new Map();
2534
+ const out = [];
2535
+ const flush = (prn) => {
2536
+ const s = state.get(prn);
2537
+ if (s && s.n >= minObs)
2538
+ out.push({ station, prn, wlFloat: s.sum / s.n, nObs: s.n });
2539
+ };
2540
+ for (const ep of epochs) {
2541
+ for (const o of ep.obs) {
2542
+ if (!o.c1 || !o.c2 || !o.l1 || !o.l2) continue;
2543
+ const lamW = C_LIGHT / (o.f1 - o.f2);
2544
+ const codeNl = (o.f1 * o.c1 + o.f2 * o.c2) / (o.f1 + o.f2);
2545
+ const mw = o.l1 - o.l2 - codeNl / lamW;
2546
+ const s = state.get(o.prn);
2547
+ if (!s || ep.timeMs - s.lastT > gapMs || Math.abs(mw - s.mean) > slipCyc) {
2548
+ if (s) flush(o.prn);
2549
+ state.set(o.prn, { sum: mw, n: 1, mean: mw, lastT: ep.timeMs });
2550
+ } else {
2551
+ s.sum += mw;
2552
+ s.n += 1;
2553
+ s.mean = s.sum / s.n;
2554
+ s.lastT = ep.timeMs;
2555
+ }
2556
+ }
2557
+ }
2558
+ for (const prn of state.keys()) flush(prn);
2559
+ return out;
2560
+ }
2561
+ function wrapHalf(x) {
2562
+ return x - Math.round(x);
2563
+ }
2564
+ function circMean(vals, weights) {
2565
+ let s = 0;
2566
+ let c = 0;
2567
+ for (let i = 0; i < vals.length; i++) {
2568
+ const a = 2 * Math.PI * vals[i];
2569
+ s += weights[i] * Math.sin(a);
2570
+ c += weights[i] * Math.cos(a);
2571
+ }
2572
+ if (s === 0 && c === 0) return 0;
2573
+ return wrapHalf(Math.atan2(s, c) / (2 * Math.PI));
2574
+ }
2575
+ function estimateWidelaneFcb(arcs, opts = {}) {
2576
+ const maxIter = opts.maxIter ?? 50;
2577
+ const tol = opts.tol ?? 1e-4;
2578
+ const fixWindow = opts.fixWindow ?? 0.25;
2579
+ const sats = [...new Set(arcs.map((a) => a.prn))].sort();
2580
+ const stations = [...new Set(arcs.map((a) => a.station))].sort();
2581
+ const refStation = stations[0] ?? "";
2582
+ const satFcb = new Map(sats.map((s) => [s, 0]));
2583
+ const rcvBias = new Map(stations.map((s) => [s, 0]));
2584
+ const nInt = new Array(arcs.length).fill(0);
2585
+ let iterations = 0;
2586
+ for (let it = 0; it < maxIter; it++) {
2587
+ iterations = it + 1;
2588
+ for (let i = 0; i < arcs.length; i++) {
2589
+ const a = arcs[i];
2590
+ nInt[i] = Math.round(
2591
+ a.wlFloat - rcvBias.get(a.station) - satFcb.get(a.prn)
2592
+ );
2593
+ }
2594
+ let maxChange = 0;
2595
+ for (const s of sats) {
2596
+ const vals = [];
2597
+ const w = [];
2598
+ for (let i = 0; i < arcs.length; i++) {
2599
+ const a = arcs[i];
2600
+ if (a.prn !== s) continue;
2601
+ vals.push(a.wlFloat - nInt[i] - rcvBias.get(a.station));
2602
+ w.push(a.nObs);
2603
+ }
2604
+ if (!vals.length) continue;
2605
+ const nv = circMean(vals, w);
2606
+ maxChange = Math.max(maxChange, Math.abs(wrapHalf(nv - satFcb.get(s))));
2607
+ satFcb.set(s, nv);
2608
+ }
2609
+ for (const r of stations) {
2610
+ const vals = [];
2611
+ const w = [];
2612
+ for (let i = 0; i < arcs.length; i++) {
2613
+ const a = arcs[i];
2614
+ if (a.station !== r) continue;
2615
+ vals.push(a.wlFloat - nInt[i] - satFcb.get(a.prn));
2616
+ w.push(a.nObs);
2617
+ }
2618
+ if (!vals.length) continue;
2619
+ rcvBias.set(r, circMean(vals, w));
2620
+ }
2621
+ const shift = rcvBias.get(refStation);
2622
+ if (shift !== 0) {
2623
+ for (const r of stations)
2624
+ rcvBias.set(r, wrapHalf(rcvBias.get(r) - shift));
2625
+ for (const s of sats) satFcb.set(s, wrapHalf(satFcb.get(s) + shift));
2626
+ }
2627
+ if (maxChange < tol) break;
2628
+ }
2629
+ let sumSq = 0;
2630
+ let fixed = 0;
2631
+ for (let i = 0; i < arcs.length; i++) {
2632
+ const a = arcs[i];
2633
+ const resid = wrapHalf(
2634
+ a.wlFloat - nInt[i] - rcvBias.get(a.station) - satFcb.get(a.prn)
2635
+ );
2636
+ sumSq += resid * resid;
2637
+ if (Math.abs(resid) <= fixWindow) fixed++;
2638
+ }
2639
+ const residRms = arcs.length ? Math.sqrt(sumSq / arcs.length) : 0;
2640
+ const fixRate = arcs.length ? fixed / arcs.length : 0;
2641
+ return { satFcb, rcvBias, residRms, fixRate, refStation, iterations };
2642
+ }
2643
+
2433
2644
  // src/positioning/index.ts
2434
2645
  var GM_GPS2 = 3986005e8;
2435
2646
  var F_REL = -4442807633e-19;
@@ -2663,6 +2874,8 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
2663
2874
  RtkFloatEngine,
2664
2875
  buildPppAntenna,
2665
2876
  createPppCorrections,
2877
+ estimateWidelaneFcb,
2878
+ extractWidelaneArcs,
2666
2879
  gimSlantIonoDelayL1,
2667
2880
  gimVerticalTec,
2668
2881
  gmst,
@@ -2672,11 +2885,14 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
2672
2885
  lambdaSearch,
2673
2886
  moonEcef,
2674
2887
  niellMapping,
2888
+ nlWavelength,
2889
+ resolvePppAmbiguities,
2675
2890
  satClockCorrection,
2676
2891
  solidEarthTide,
2677
2892
  solveDgnss,
2678
2893
  solvePpp,
2679
2894
  solveSpp,
2680
2895
  sunEcef,
2681
- toRtkEpoch
2896
+ toRtkEpoch,
2897
+ wlWavelength
2682
2898
  });
@@ -714,6 +714,172 @@ 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
+
796
+ /**
797
+ * Wide-lane fractional-cycle bias (FCB) estimation for PPP-AR — the
798
+ * self-contained route to integer ambiguities that needs no external
799
+ * phase-bias product, only a small network of stations.
800
+ *
801
+ * A single receiver cannot resolve ambiguities because its Melbourne–Wübbena
802
+ * wide-lane float is `Ñ_wl = N (integer) + b_rcv + b_sat`, and the integer
803
+ * and the satellite fractional bias `b_sat` are entangled. Across a *network*
804
+ * they separate: every station sees the same `b_sat` for a given satellite
805
+ * but its own integers and receiver bias, so the fractional part common to
806
+ * all stations *is* the satellite FCB. This is the classic Ge/Gendt method.
807
+ *
808
+ * The estimator alternates:
809
+ * 1. round each arc to its integer N = round(Ñ_wl − b_rcv − b_sat);
810
+ * 2. update each satellite FCB = circular-mean over stations of
811
+ * (Ñ_wl − N − b_rcv);
812
+ * 3. update each receiver bias = circular-mean over satellites of
813
+ * (Ñ_wl − N − b_sat);
814
+ * 4. pin the datum (b_rcv of a reference station ≡ 0) — receiver and
815
+ * satellite biases otherwise trade off by an arbitrary constant.
816
+ *
817
+ * The output `satFcb` feeds `resolvePppAmbiguities`' `wlBiasCyc`.
818
+ */
819
+ /** Minimal per-satellite observation for wide-lane extraction. */
820
+ interface WlObs {
821
+ prn: string;
822
+ f1: number;
823
+ f2: number;
824
+ /** Code on f1/f2 (m) and carrier phase on f1/f2 (cycles). */
825
+ c1: number;
826
+ c2: number;
827
+ l1: number;
828
+ l2: number;
829
+ }
830
+ /**
831
+ * Extract arc-averaged Melbourne–Wübbena wide-lanes for one station from its
832
+ * epoch stream. The MW combination
833
+ * MW = (L1 − L2) − [(f1·C1 + f2·C2)/(f1+f2)] / (c/(f1−f2)) [cycles]
834
+ * is geometry-, clock- and (first-order) ionosphere-free, so it holds the
835
+ * wide-lane ambiguity plus biases and is near-constant within an arc. Arcs
836
+ * are split on a running-mean jump (cycle slip) or a time gap.
837
+ */
838
+ declare function extractWidelaneArcs(station: string, epochs: {
839
+ timeMs: number;
840
+ obs: WlObs[];
841
+ }[], opts?: {
842
+ slipCyc?: number;
843
+ gapMs?: number;
844
+ minObs?: number;
845
+ }): WlArc[];
846
+ /** One continuous wide-lane arc at a station. */
847
+ interface WlArc {
848
+ station: string;
849
+ prn: string;
850
+ /** Arc-averaged Melbourne–Wübbena wide-lane float (cycles). */
851
+ wlFloat: number;
852
+ /** Number of epochs averaged (used as the weight). */
853
+ nObs: number;
854
+ }
855
+ interface WlFcbOptions {
856
+ /** Max iterations. Default 50. */
857
+ maxIter?: number;
858
+ /** Convergence threshold on the largest bias change (cycles). Default 1e-4. */
859
+ tol?: number;
860
+ /** Fix-rate acceptance window |resid| (cycles). Default 0.25. */
861
+ fixWindow?: number;
862
+ }
863
+ interface WlFcbResult {
864
+ /** Per-satellite wide-lane FCB (cycles, wrapped to [−0.5, 0.5)). */
865
+ satFcb: Map<string, number>;
866
+ /** Per-station wide-lane bias (cycles); the reference station is 0. */
867
+ rcvBias: Map<string, number>;
868
+ /** RMS of the post-fit arc residuals Ñ_wl − N − b_rcv − b_sat (cycles). */
869
+ residRms: number;
870
+ /** Fraction of arcs whose residual lies within `fixWindow` of an integer. */
871
+ fixRate: number;
872
+ /** Reference station pinning the datum. */
873
+ refStation: string;
874
+ iterations: number;
875
+ }
876
+ /**
877
+ * Estimate per-satellite wide-lane FCBs from a network of stations' arc
878
+ * wide-lane floats. Needs ≥2 stations sharing satellites to break the
879
+ * integer/bias entanglement.
880
+ */
881
+ declare function estimateWidelaneFcb(arcs: WlArc[], opts?: WlFcbOptions): WlFcbResult;
882
+
717
883
  /**
718
884
  * Single-point positioning (SPP) from pseudoranges and broadcast
719
885
  * ephemerides.
@@ -803,4 +969,4 @@ declare function ionoFree(p1: number, p2: number, f1: number, f2: number): numbe
803
969
  */
804
970
  declare function solveSpp(pseudoranges: Map<string, number>, ephemerides: Map<string, Ephemeris>, timeMs: number, opts?: SppOptions): SppSolution | null;
805
971
 
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 };
972
+ 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, type WlArc, type WlFcbOptions, type WlFcbResult, type WlObs, buildPppAntenna, createPppCorrections, estimateWidelaneFcb, extractWidelaneArcs, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, resolvePppAmbiguities, satClockCorrection, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };