gnss-js 1.3.0 → 1.3.2

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.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { D as DAYS_MJD2000_MJD, a as DAYS_MJD_JULIAN, H as HourCode, M as MILLISECONDS_GPS_TAI, b as MILLISECONDS_IN_DAY, c as MILLISECONDS_IN_HOUR, d as MILLISECONDS_IN_MINUTE, e as MILLISECONDS_IN_SECOND, f as MILLISECONDS_IN_WEEK, g as MILLISECONDS_TT_TAI, R as RINEX_CODES, S as SECONDS_IN_DAY, h as SECONDS_IN_HOUR, i as SECONDS_IN_MINUTE, j as SECONDS_IN_WEEK, k as START_BDS_TIME, l as START_GAL_TIME, m as START_GLO_LEAP, n as START_GPS_TIME, o as START_JULIAN_TAI, p as START_MJD_UNIX_SECONDS, q as START_NTP_TIME, r as START_TAI_TIME, s as START_UNIX_TIME, T as TimeDifference } from './time-DnI1VpE8.js';
2
2
  export { WGS84_ECCENTRICITY_SQUARED, WGS84_FLATTENING, WGS84_SEMI_MAJOR_AXIS, WGS84_SEMI_MINOR_AXIS } from './constants.js';
3
- export { A as ARC_GAP_FACTOR, B as BAND_LABELS, a as BDS_SATELLITES, b as BdsSatellite, C as C_LIGHT, D as DEFAULT_ELEV_MASK_DEG, c as DUAL_FREQ_PAIRS, F as FREQ, G as GLO_CHANNEL_FALLBACK, d as GLO_F1_BASE, e as GLO_F1_STEP, f as GLO_F2_BASE, g as GLO_F2_STEP, h as GLO_F3, O as OnSlipDetected, S as SYSTEM_NAMES, i as SYS_SHORT, j as buildGloChannelMap, k as buildObsIndices, l as formatUTCTime, m as getFreq, n as gloFreq } from './gnss-C-tgoYNa.js';
3
+ export { A as ARC_GAP_FACTOR, B as BAND_LABELS, a as BDS_SATELLITES, b as BdsSatellite, C as C_LIGHT, D as DEFAULT_ELEV_MASK_DEG, c as DUAL_FREQ_PAIRS, F as FREQ, G as GLO_CHANNEL_FALLBACK, d as GLO_F1_BASE, e as GLO_F1_STEP, f as GLO_F2_BASE, g as GLO_F2_STEP, h as GLO_F3, O as OMEGA_E, i as OnSlipDetected, S as SYSTEM_NAMES, j as SYS_SHORT, k as buildGloChannelMap, l as buildObsIndices, m as formatUTCTime, n as getFreq, o as gloFreq } from './gnss-DhnEr0Dy.js';
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';
@@ -9,7 +9,9 @@ export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResul
9
9
  export { E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, p as parseNavFile } from './nav-BAI1a9vK.js';
10
10
  export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.js';
11
11
  export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.js';
12
- export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris } from './orbit.js';
12
+ export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris } from './orbit.js';
13
+ export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.js';
14
+ export { SppOptions, SppSolution, ionoFree, satClockCorrection, solveSpp } from './positioning.js';
13
15
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.js';
14
16
  export { CompleteSatSignal, CompleteSignalStats, CompletenessAccumulator, CompletenessResult, CycleSlipAccumulator, CycleSlipEvent, CycleSlipResult, CycleSlipSignalStats, MultipathAccumulator, MultipathPoint, MultipathResult, MultipathSeries, MultipathSignalStat, QualityResult, analyzeQuality } from './analysis.js';
15
17
  export { AntennaEntry, AntexFile, FrequencyData, frequencyLabel, parseAntex } from './antex.js';
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  CycleSlipAccumulator,
9
9
  MultipathAccumulator,
10
10
  analyzeQuality
11
- } from "./chunk-G3N4S3DM.js";
11
+ } from "./chunk-AW6BORTZ.js";
12
12
  import {
13
13
  frequencyLabel,
14
14
  parseAntex
@@ -53,7 +53,7 @@ import {
53
53
  phiBOCc,
54
54
  phiBOCs,
55
55
  phiBPSK
56
- } from "./chunk-5SPJH4MG.js";
56
+ } from "./chunk-2K3FCJBX.js";
57
57
  import {
58
58
  Scale,
59
59
  getDateFromDayOfWeek,
@@ -87,6 +87,17 @@ import {
87
87
  rhumbLine,
88
88
  vincenty
89
89
  } from "./chunk-MIIM4LDY.js";
90
+ import {
91
+ REFERENCE_FRAMES,
92
+ applyHelmert,
93
+ dateToEpoch,
94
+ transformFrame
95
+ } from "./chunk-4KOXMHUW.js";
96
+ import {
97
+ ionoFree,
98
+ satClockCorrection,
99
+ solveSpp
100
+ } from "./chunk-PX7TPPTQ.js";
90
101
  import {
91
102
  computeAllPositions,
92
103
  computeDop,
@@ -94,11 +105,12 @@ import {
94
105
  computeSatPosition,
95
106
  computeVisibility,
96
107
  ecefToAzEl,
108
+ ephInfoToEphemeris,
97
109
  glonassPosition,
98
110
  keplerPosition,
99
111
  navTimesFromEph,
100
112
  selectEphemeris
101
- } from "./chunk-ZCNXERQ2.js";
113
+ } from "./chunk-PQYBTE42.js";
102
114
  import {
103
115
  getBdsTime,
104
116
  getDateFromBdsTime,
@@ -166,7 +178,7 @@ import {
166
178
  parseRinexStream,
167
179
  systemCmp,
168
180
  systemName
169
- } from "./chunk-OZCYOM5D.js";
181
+ } from "./chunk-3U5AX7PY.js";
170
182
  import {
171
183
  BitReader,
172
184
  RTCM3_MESSAGE_NAMES,
@@ -184,7 +196,7 @@ import {
184
196
  setRtcm3DebugHandler,
185
197
  updateStationMeta,
186
198
  updateStreamStats
187
- } from "./chunk-7EEWQ5DU.js";
199
+ } from "./chunk-65CQINSB.js";
188
200
  import {
189
201
  DAYS_MJD2000_MJD,
190
202
  DAYS_MJD_JULIAN,
@@ -224,6 +236,7 @@ import {
224
236
  GLO_F2_BASE,
225
237
  GLO_F2_STEP,
226
238
  GLO_F3,
239
+ OMEGA_E,
227
240
  SYSTEM_NAMES,
228
241
  SYS_SHORT,
229
242
  buildGloChannelMap,
@@ -231,7 +244,7 @@ import {
231
244
  formatUTCTime,
232
245
  getFreq,
233
246
  gloFreq
234
- } from "./chunk-W5WKEV7U.js";
247
+ } from "./chunk-FIEWO4J4.js";
235
248
  export {
236
249
  ARC_GAP_FACTOR,
237
250
  BAND_LABELS,
@@ -288,6 +301,8 @@ export {
288
301
  MILLISECONDS_IN_WEEK,
289
302
  MILLISECONDS_TT_TAI,
290
303
  MultipathAccumulator,
304
+ OMEGA_E,
305
+ REFERENCE_FRAMES,
291
306
  RINEX_CODES,
292
307
  RTCM3_MESSAGE_NAMES,
293
308
  Rtcm3Decoder,
@@ -314,6 +329,7 @@ export {
314
329
  WGS84_SEMI_MINOR_AXIS,
315
330
  WarningAccumulator,
316
331
  analyzeQuality,
332
+ applyHelmert,
317
333
  buildGloChannelMap,
318
334
  buildObsIndices,
319
335
  clampUnit,
@@ -329,12 +345,14 @@ export {
329
345
  createStreamStats,
330
346
  crxDecompress,
331
347
  crxRepair,
348
+ dateToEpoch,
332
349
  decodeEphemeris,
333
350
  decodeMsmFull,
334
351
  deg2dms,
335
352
  deg2rad,
336
353
  ecefToAzEl,
337
354
  ecefToGeodetic,
355
+ ephInfoToEphemeris,
338
356
  euclidean3D,
339
357
  fetchSourcetable,
340
358
  fmtF,
@@ -402,6 +420,7 @@ export {
402
420
  greatCircleMidpoint,
403
421
  hdrLine,
404
422
  horizonDistance,
423
+ ionoFree,
405
424
  keplerPosition,
406
425
  msmEpochToDate,
407
426
  navTimesFromEph,
@@ -424,11 +443,14 @@ export {
424
443
  resetGloFreqCache,
425
444
  rhumbLine,
426
445
  rtcm3Constellation,
446
+ satClockCorrection,
427
447
  selectEphemeris,
428
448
  setGloFreqNumber,
429
449
  setRtcm3DebugHandler,
450
+ solveSpp,
430
451
  systemCmp,
431
452
  systemName,
453
+ transformFrame,
432
454
  updateStationMeta,
433
455
  updateStreamStats,
434
456
  verifyChecksum,
package/dist/orbit.cjs CHANGED
@@ -27,6 +27,7 @@ __export(orbit_exports, {
27
27
  computeVisibility: () => computeVisibility,
28
28
  ecefToAzEl: () => ecefToAzEl,
29
29
  ecefToGeodetic: () => ecefToGeodetic,
30
+ ephInfoToEphemeris: () => ephInfoToEphemeris,
30
31
  geodeticToEcef: () => geodeticToEcef,
31
32
  glonassPosition: () => glonassPosition,
32
33
  keplerPosition: () => keplerPosition,
@@ -79,6 +80,9 @@ var START_GPS_TIME = /* @__PURE__ */ new Date("1980-01-06T00:00:00Z");
79
80
  var START_BDS_TIME = /* @__PURE__ */ new Date("2006-01-01T00:00:14Z");
80
81
  var START_NTP_TIME = /* @__PURE__ */ new Date("1900-01-01T00:00:00Z");
81
82
 
83
+ // src/constants/gnss.ts
84
+ var OMEGA_E = 72921151467e-15;
85
+
82
86
  // src/time/gnss.ts
83
87
  function getTaiDate(date) {
84
88
  return new Date(date.getTime() + MILLISECONDS_GPS_TAI);
@@ -166,7 +170,6 @@ var GM_GPS = 3986005e8;
166
170
  var GM_GAL = 3986004418e5;
167
171
  var GM_BDS = 3986004418e5;
168
172
  var GM_GLO = 39860044e7;
169
- var OMEGA_E = 72921151467e-15;
170
173
  var BDS_GEO_MAX_INCLINATION_RAD = 0.1;
171
174
  var BDS_GEO_MIN_SEMIMAJOR_AXIS_M = 4e7;
172
175
  var AE_GLO = 6378136;
@@ -375,7 +378,8 @@ function selectEphemeris(ephemerides, prn, timeMs) {
375
378
  if (eph.prn !== prn) continue;
376
379
  const ephTime = eph.tocDate.getTime();
377
380
  const dt = Math.abs(timeMs - ephTime);
378
- if (dt > 4 * 3600 * 1e3) continue;
381
+ const maxAge = eph.system === "R" || eph.system === "S" ? 18e5 : 4 * 36e5;
382
+ if (dt > maxAge) continue;
379
383
  if (dt < bestDt) {
380
384
  bestDt = dt;
381
385
  best = eph;
@@ -483,13 +487,13 @@ function ephInfoToEphemeris(info) {
483
487
  return null;
484
488
  if (info.vx === void 0 || info.vy === void 0 || info.vz === void 0)
485
489
  return null;
486
- const now = new Date(info.lastReceived);
490
+ const moscow = new Date(info.lastReceived + 3 * 3600 * 1e3);
487
491
  const utcMidnight = Date.UTC(
488
- now.getUTCFullYear(),
489
- now.getUTCMonth(),
490
- now.getUTCDate()
492
+ moscow.getUTCFullYear(),
493
+ moscow.getUTCMonth(),
494
+ moscow.getUTCDate()
491
495
  );
492
- const tbSec = (info.tb ?? 0) * 900;
496
+ const tbSec = (info.tb ?? 0) * 60;
493
497
  const moscowOffset = 3 * 3600;
494
498
  const tocMs = utcMidnight + (tbSec - moscowOffset) * 1e3;
495
499
  return {
@@ -660,6 +664,7 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
660
664
  computeVisibility,
661
665
  ecefToAzEl,
662
666
  ecefToGeodetic,
667
+ ephInfoToEphemeris,
663
668
  geodeticToEcef,
664
669
  glonassPosition,
665
670
  keplerPosition,
package/dist/orbit.d.cts CHANGED
@@ -108,6 +108,8 @@ interface AllPositionsData {
108
108
  * When rxPos is provided, az/el are computed; otherwise they are 0.
109
109
  */
110
110
  declare function computeAllPositions(ephemerides: Ephemeris[], times: number[], rxPos?: [number, number, number]): AllPositionsData;
111
+ /** Convert an RTCM3 EphemerisInfo to the Ephemeris type used by orbit computation. */
112
+ declare function ephInfoToEphemeris(info: EphemerisInfo): Ephemeris | null;
111
113
  /**
112
114
  * Compute current satellite az/el from live RTCM3 ephemeris data.
113
115
  * Returns array of SatAzEl for all satellites with valid ephemeris.
@@ -151,4 +153,4 @@ interface VisibilityResult {
151
153
  */
152
154
  declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number): VisibilityResult;
153
155
 
154
- export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris };
156
+ export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris };
package/dist/orbit.d.ts CHANGED
@@ -108,6 +108,8 @@ interface AllPositionsData {
108
108
  * When rxPos is provided, az/el are computed; otherwise they are 0.
109
109
  */
110
110
  declare function computeAllPositions(ephemerides: Ephemeris[], times: number[], rxPos?: [number, number, number]): AllPositionsData;
111
+ /** Convert an RTCM3 EphemerisInfo to the Ephemeris type used by orbit computation. */
112
+ declare function ephInfoToEphemeris(info: EphemerisInfo): Ephemeris | null;
111
113
  /**
112
114
  * Compute current satellite az/el from live RTCM3 ephemeris data.
113
115
  * Returns array of SatAzEl for all satellites with valid ephemeris.
@@ -151,4 +153,4 @@ interface VisibilityResult {
151
153
  */
152
154
  declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number): VisibilityResult;
153
155
 
154
- export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris };
156
+ export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris };
package/dist/orbit.js CHANGED
@@ -5,11 +5,12 @@ import {
5
5
  computeSatPosition,
6
6
  computeVisibility,
7
7
  ecefToAzEl,
8
+ ephInfoToEphemeris,
8
9
  glonassPosition,
9
10
  keplerPosition,
10
11
  navTimesFromEph,
11
12
  selectEphemeris
12
- } from "./chunk-ZCNXERQ2.js";
13
+ } from "./chunk-PQYBTE42.js";
13
14
  import "./chunk-HVXYFUCB.js";
14
15
  import {
15
16
  ecefToGeodetic,
@@ -17,6 +18,7 @@ import {
17
18
  } from "./chunk-37QNKGTC.js";
18
19
  import "./chunk-6FAL6P4G.js";
19
20
  import "./chunk-LEEU5OIO.js";
21
+ import "./chunk-FIEWO4J4.js";
20
22
  export {
21
23
  computeAllPositions,
22
24
  computeDop,
@@ -25,6 +27,7 @@ export {
25
27
  computeVisibility,
26
28
  ecefToAzEl,
27
29
  ecefToGeodetic,
30
+ ephInfoToEphemeris,
28
31
  geodeticToEcef,
29
32
  glonassPosition,
30
33
  keplerPosition,
@@ -63,6 +63,10 @@ var START_GPS_TIME = /* @__PURE__ */ new Date("1980-01-06T00:00:00Z");
63
63
  var START_BDS_TIME = /* @__PURE__ */ new Date("2006-01-01T00:00:14Z");
64
64
  var START_NTP_TIME = /* @__PURE__ */ new Date("1900-01-01T00:00:00Z");
65
65
 
66
+ // src/constants/gnss.ts
67
+ var C_LIGHT = 299792458;
68
+ var OMEGA_E = 72921151467e-15;
69
+
66
70
  // src/time/gnss.ts
67
71
  function getTaiDate(date) {
68
72
  return new Date(date.getTime() + MILLISECONDS_GPS_TAI);
@@ -150,7 +154,6 @@ var GM_GPS = 3986005e8;
150
154
  var GM_GAL = 3986004418e5;
151
155
  var GM_BDS = 3986004418e5;
152
156
  var GM_GLO = 39860044e7;
153
- var OMEGA_E = 72921151467e-15;
154
157
  var BDS_GEO_MAX_INCLINATION_RAD = 0.1;
155
158
  var BDS_GEO_MIN_SEMIMAJOR_AXIS_M = 4e7;
156
159
  var AE_GLO = 6378136;
@@ -366,9 +369,6 @@ function computeSatPosition(eph, timeMs) {
366
369
  var GPS_EPOCH_MS = START_GPS_TIME.getTime();
367
370
  var BDS_EPOCH_MS = START_BDS_TIME.getTime();
368
371
 
369
- // src/constants/gnss.ts
370
- var C_LIGHT = 299792458;
371
-
372
372
  // src/positioning/index.ts
373
373
  var GM_GPS2 = 3986005e8;
374
374
  var F_REL = -4442807633e-19;
@@ -400,8 +400,7 @@ function tropoDelay(elevationRad) {
400
400
  return 2.47 / (sinEl + 0.0121);
401
401
  }
402
402
  function sagnac(pos, travelTimeS) {
403
- const OMEGA_E2 = 72921151467e-15;
404
- const theta = OMEGA_E2 * travelTimeS;
403
+ const theta = OMEGA_E * travelTimeS;
405
404
  const c = Math.cos(theta);
406
405
  const s = Math.sin(theta);
407
406
  return [pos.x * c + pos.y * s, -pos.x * s + pos.y * c, pos.z];
@@ -429,7 +428,8 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
429
428
  elevationMaskDeg = 10,
430
429
  troposphere = true,
431
430
  maxIterations = 15,
432
- convergenceM = 1e-4
431
+ convergenceM = 1e-4,
432
+ tgd = true
433
433
  } = opts;
434
434
  const all = [...pseudoranges.keys()].filter((p) => ephemerides.has(p));
435
435
  const minSats = (list) => 3 + new Set(list.map((p) => p[0])).size;
@@ -460,9 +460,11 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
460
460
  const sys = prn[0];
461
461
  const clk = clock2.get(sys);
462
462
  const tTx = timeMs - psr / C_LIGHT * 1e3;
463
- const sat = computeSatPosition(eph, tTx);
463
+ const dtsClock = satClockCorrection(eph, tTx);
464
+ const sat = computeSatPosition(eph, tTx - dtsClock * 1e3);
464
465
  if (!Number.isFinite(sat.x)) continue;
465
- const dts = satClockCorrection(eph, tTx);
466
+ const isKepler = eph.system !== "R" && eph.system !== "S";
467
+ const dts = dtsClock - (tgd && isKepler ? eph.tgd : 0);
466
468
  const travel = Math.hypot(sat.x - x2, sat.y - y2, sat.z - z2) / C_LIGHT;
467
469
  const [sx, sy, sz] = sagnac(sat, travel);
468
470
  const rho = Math.hypot(sx - x2, sy - y2, sz - z2);
@@ -9,9 +9,9 @@ import './ecef-CF0uAysr.cjs';
9
9
  *
10
10
  * Weighted iterative least squares with one receiver-clock unknown per
11
11
  * constellation (absorbing inter-system time offsets), satellite clock
12
- * polynomial + relativistic correction, Sagnac (Earth-rotation)
13
- * correction, elevation masking/weighting, and a simple tropospheric
14
- * model. Ionospheric delay is NOT modelled — use the iono-free
12
+ * polynomial + relativistic correction, broadcast group delay
13
+ * (TGD/BGD), Sagnac (Earth-rotation) correction, elevation
14
+ * masking/weighting, and a simple tropospheric model. Ionospheric delay is NOT modelled — use the iono-free
15
15
  * combination (ionoFree helper) with dual-frequency pseudoranges for
16
16
  * metre-level results, or expect ~2–10 m of iono bias on L1-only.
17
17
  */
@@ -25,6 +25,14 @@ interface SppOptions {
25
25
  maxIterations?: number;
26
26
  /** Convergence threshold on the position update (m). Default 1e-4. */
27
27
  convergenceM?: number;
28
+ /**
29
+ * Apply the broadcast group-delay correction (GPS TGD, Galileo
30
+ * BGD E5a/E1, BeiDou TGD1) to the satellite clock. Correct for
31
+ * single-frequency measurements on the primary frequency (C1C/E1/B1I)
32
+ * — the default. Disable when feeding iono-free combinations, whose
33
+ * reference the broadcast clock already matches. Default true.
34
+ */
35
+ tgd?: boolean;
28
36
  }
29
37
  interface SppSolution {
30
38
  /** Receiver position, ECEF meters. */
@@ -9,9 +9,9 @@ import './ecef-CF0uAysr.js';
9
9
  *
10
10
  * Weighted iterative least squares with one receiver-clock unknown per
11
11
  * constellation (absorbing inter-system time offsets), satellite clock
12
- * polynomial + relativistic correction, Sagnac (Earth-rotation)
13
- * correction, elevation masking/weighting, and a simple tropospheric
14
- * model. Ionospheric delay is NOT modelled — use the iono-free
12
+ * polynomial + relativistic correction, broadcast group delay
13
+ * (TGD/BGD), Sagnac (Earth-rotation) correction, elevation
14
+ * masking/weighting, and a simple tropospheric model. Ionospheric delay is NOT modelled — use the iono-free
15
15
  * combination (ionoFree helper) with dual-frequency pseudoranges for
16
16
  * metre-level results, or expect ~2–10 m of iono bias on L1-only.
17
17
  */
@@ -25,6 +25,14 @@ interface SppOptions {
25
25
  maxIterations?: number;
26
26
  /** Convergence threshold on the position update (m). Default 1e-4. */
27
27
  convergenceM?: number;
28
+ /**
29
+ * Apply the broadcast group-delay correction (GPS TGD, Galileo
30
+ * BGD E5a/E1, BeiDou TGD1) to the satellite clock. Correct for
31
+ * single-frequency measurements on the primary frequency (C1C/E1/B1I)
32
+ * — the default. Disable when feeding iono-free combinations, whose
33
+ * reference the broadcast clock already matches. Default true.
34
+ */
35
+ tgd?: boolean;
28
36
  }
29
37
  interface SppSolution {
30
38
  /** Receiver position, ECEF meters. */
@@ -1,204 +1,14 @@
1
1
  import {
2
- computeDop,
3
- computeSatPosition,
4
- ecefToAzEl
5
- } from "./chunk-ZCNXERQ2.js";
2
+ ionoFree,
3
+ satClockCorrection,
4
+ solveSpp
5
+ } from "./chunk-PX7TPPTQ.js";
6
+ import "./chunk-PQYBTE42.js";
6
7
  import "./chunk-HVXYFUCB.js";
7
8
  import "./chunk-37QNKGTC.js";
8
9
  import "./chunk-6FAL6P4G.js";
9
10
  import "./chunk-LEEU5OIO.js";
10
- import {
11
- C_LIGHT
12
- } from "./chunk-W5WKEV7U.js";
13
-
14
- // src/positioning/index.ts
15
- var GM_GPS = 3986005e8;
16
- var F_REL = -4442807633e-19;
17
- function satClockCorrection(eph, tMs) {
18
- if (eph.system === "R" || eph.system === "S") {
19
- const dt2 = (tMs - eph.tocDate.getTime()) / 1e3;
20
- return eph.tauN + eph.gammaN * dt2;
21
- }
22
- const k = eph;
23
- const dt = (tMs - k.tocDate.getTime()) / 1e3;
24
- const poly = k.af0 + k.af1 * dt + k.af2 * dt * dt;
25
- const a = k.sqrtA * k.sqrtA;
26
- const n = Math.sqrt(GM_GPS / (a * a * a)) + k.deltaN;
27
- const tk = dt;
28
- const Mk = k.m0 + n * tk;
29
- let Ek = Mk;
30
- for (let i = 0; i < 8; i++) {
31
- Ek = Mk + k.e * Math.sin(Ek);
32
- }
33
- const rel = F_REL * k.e * k.sqrtA * Math.sin(Ek);
34
- return poly + rel;
35
- }
36
- function ionoFree(p1, p2, f1, f2) {
37
- const g = f1 * f1 / (f1 * f1 - f2 * f2);
38
- return g * p1 - (g - 1) * p2;
39
- }
40
- function tropoDelay(elevationRad) {
41
- const sinEl = Math.sin(elevationRad);
42
- return 2.47 / (sinEl + 0.0121);
43
- }
44
- function sagnac(pos, travelTimeS) {
45
- const OMEGA_E = 72921151467e-15;
46
- const theta = OMEGA_E * travelTimeS;
47
- const c = Math.cos(theta);
48
- const s = Math.sin(theta);
49
- return [pos.x * c + pos.y * s, -pos.x * s + pos.y * c, pos.z];
50
- }
51
- function solveLinear(A, b) {
52
- const n = b.length;
53
- const M = A.map((row, i) => [...row, b[i]]);
54
- for (let col = 0; col < n; col++) {
55
- let pivot = col;
56
- for (let r = col + 1; r < n; r++) {
57
- if (Math.abs(M[r][col]) > Math.abs(M[pivot][col])) pivot = r;
58
- }
59
- if (Math.abs(M[pivot][col]) < 1e-12) return null;
60
- [M[col], M[pivot]] = [M[pivot], M[col]];
61
- for (let r = 0; r < n; r++) {
62
- if (r === col) continue;
63
- const f = M[r][col] / M[col][col];
64
- for (let c = col; c <= n; c++) M[r][c] -= f * M[col][c];
65
- }
66
- }
67
- return M.map((row, i) => row[n] / M[i][i]);
68
- }
69
- function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
70
- const {
71
- elevationMaskDeg = 10,
72
- troposphere = true,
73
- maxIterations = 15,
74
- convergenceM = 1e-4
75
- } = opts;
76
- const all = [...pseudoranges.keys()].filter((p) => ephemerides.has(p));
77
- const minSats = (list) => 3 + new Set(list.map((p) => p[0])).size;
78
- if (all.length < minSats(all)) return null;
79
- const gaussNewton = (prns) => {
80
- const systems = [...new Set(prns.map((p) => p[0]))].sort();
81
- const dim = 3 + systems.length;
82
- const sysIndex = new Map(systems.map((s, i) => [s, 3 + i]));
83
- let x2 = 0;
84
- let y2 = 0;
85
- let z2 = 0;
86
- const clock2 = new Map(systems.map((s) => [s, 0]));
87
- const residuals2 = {};
88
- let iterations2 = 0;
89
- let converged2 = false;
90
- for (let iter = 0; iter < maxIterations; iter++) {
91
- iterations2 = iter + 1;
92
- const HtH = Array.from(
93
- { length: dim },
94
- () => new Array(dim).fill(0)
95
- );
96
- const Htv = new Array(dim).fill(0);
97
- let rows = 0;
98
- for (const k of Object.keys(residuals2)) delete residuals2[k];
99
- for (const prn of prns) {
100
- const psr = pseudoranges.get(prn);
101
- const eph = ephemerides.get(prn);
102
- const sys = prn[0];
103
- const clk = clock2.get(sys);
104
- const tTx = timeMs - psr / C_LIGHT * 1e3;
105
- const sat = computeSatPosition(eph, tTx);
106
- if (!Number.isFinite(sat.x)) continue;
107
- const dts = satClockCorrection(eph, tTx);
108
- const travel = Math.hypot(sat.x - x2, sat.y - y2, sat.z - z2) / C_LIGHT;
109
- const [sx, sy, sz] = sagnac(sat, travel);
110
- const rho = Math.hypot(sx - x2, sy - y2, sz - z2);
111
- const ux = (x2 - sx) / rho;
112
- const uy = (y2 - sy) / rho;
113
- const uz = (z2 - sz) / rho;
114
- let elev = Math.PI / 2;
115
- let weight = 1;
116
- const positionSane = x2 * x2 + y2 * y2 + z2 * z2 > 1e12;
117
- if (positionSane) {
118
- const azel = ecefToAzEl(x2, y2, z2, sx, sy, sz);
119
- elev = azel.el;
120
- if (iter >= 2 && elev < elevationMaskDeg * Math.PI / 180) continue;
121
- const sinEl = Math.max(Math.sin(elev), 0.1);
122
- weight = sinEl * sinEl;
123
- }
124
- const tropo = troposphere && positionSane ? tropoDelay(elev) : 0;
125
- const predicted = rho + clk - C_LIGHT * dts + tropo;
126
- const v = psr - predicted;
127
- const h = new Array(dim).fill(0);
128
- h[0] = ux;
129
- h[1] = uy;
130
- h[2] = uz;
131
- h[sysIndex.get(sys)] = 1;
132
- for (let i = 0; i < dim; i++) {
133
- for (let j = 0; j < dim; j++) HtH[i][j] += weight * h[i] * h[j];
134
- Htv[i] += weight * h[i] * v;
135
- }
136
- residuals2[prn] = v;
137
- rows++;
138
- }
139
- if (rows < dim) return null;
140
- const dx = solveLinear(HtH, Htv);
141
- if (!dx) return null;
142
- x2 += dx[0];
143
- y2 += dx[1];
144
- z2 += dx[2];
145
- for (const s of systems)
146
- clock2.set(s, clock2.get(s) + dx[sysIndex.get(s)]);
147
- if (Math.hypot(dx[0], dx[1], dx[2]) < convergenceM) {
148
- converged2 = true;
149
- break;
150
- }
151
- }
152
- return { x: x2, y: y2, z: z2, clock: clock2, residuals: residuals2, iterations: iterations2, converged: converged2 };
153
- };
154
- const REJECT_THRESHOLD_M = 50;
155
- let candidates = all;
156
- const rejected = [];
157
- let inner = null;
158
- for (let round = 0; round <= all.length; round++) {
159
- inner = gaussNewton(candidates);
160
- if (!inner) return null;
161
- const vals = Object.entries(inner.residuals);
162
- let worst = null;
163
- let worstAbs = REJECT_THRESHOLD_M;
164
- for (const [prn, v] of vals) {
165
- if (Math.abs(v) > worstAbs) {
166
- worstAbs = Math.abs(v);
167
- worst = prn;
168
- }
169
- }
170
- if (!worst) break;
171
- const remaining = candidates.filter((p) => p !== worst);
172
- if (remaining.length < minSats(remaining)) break;
173
- rejected.push(worst);
174
- candidates = remaining;
175
- }
176
- if (!inner) return null;
177
- const { x, y, z, clock, residuals, iterations, converged } = inner;
178
- const used = [];
179
- const azels = [];
180
- for (const prn of candidates) {
181
- if (!(prn in residuals)) continue;
182
- const eph = ephemerides.get(prn);
183
- const sat = computeSatPosition(eph, timeMs);
184
- if (!Number.isFinite(sat.x)) continue;
185
- const azel = ecefToAzEl(x, y, z, sat.x, sat.y, sat.z);
186
- if (azel.el >= elevationMaskDeg * Math.PI / 180) {
187
- used.push(prn);
188
- azels.push(azel);
189
- }
190
- }
191
- return {
192
- position: [x, y, z],
193
- clockBias: Object.fromEntries(clock),
194
- usedSatellites: used,
195
- rejectedSatellites: rejected,
196
- residuals,
197
- dop: computeDop(azels),
198
- iterations,
199
- converged
200
- };
201
- }
11
+ import "./chunk-FIEWO4J4.js";
202
12
  export {
203
13
  ionoFree,
204
14
  satClockCorrection,
package/dist/rinex.js CHANGED
@@ -16,8 +16,8 @@ import {
16
16
  parseRinexStream,
17
17
  systemCmp,
18
18
  systemName
19
- } from "./chunk-OZCYOM5D.js";
20
- import "./chunk-W5WKEV7U.js";
19
+ } from "./chunk-3U5AX7PY.js";
20
+ import "./chunk-FIEWO4J4.js";
21
21
  export {
22
22
  EMPTY_WARNINGS,
23
23
  SYSTEM_ORDER,
package/dist/rtcm3.cjs CHANGED
@@ -1319,6 +1319,7 @@ var RTCM3_MESSAGE_NAMES = {
1319
1319
  1031: "GLONASS Network RTK Residual",
1320
1320
  1032: "Physical Reference Station",
1321
1321
  1033: "Receiver+Antenna Descriptor",
1322
+ 1041: "NavIC Ephemeris",
1322
1323
  1042: "BeiDou Ephemeris",
1323
1324
  1043: "SBAS Ephemeris",
1324
1325
  1044: "QZSS Ephemeris",
@@ -1383,6 +1384,8 @@ var RTCM3_MESSAGE_NAMES = {
1383
1384
  1064: "GLONASS SSR Clock",
1384
1385
  1065: "GLONASS SSR Code Bias",
1385
1386
  1066: "GLONASS SSR Orbit+Clock",
1387
+ // Biases
1388
+ 1230: "GLONASS Code-Phase Biases",
1386
1389
  // IGS SSR
1387
1390
  4076: "IGS SSR"
1388
1391
  };
@@ -1391,6 +1394,7 @@ function rtcm3Constellation(msgType) {
1391
1394
  if (msgType >= 1009 && msgType <= 1012) return "GLONASS";
1392
1395
  if (msgType === 1019) return "GPS";
1393
1396
  if (msgType === 1020) return "GLONASS";
1397
+ if (msgType === 1041) return "NavIC";
1394
1398
  if (msgType === 1042) return "BeiDou";
1395
1399
  if (msgType === 1043) return "SBAS";
1396
1400
  if (msgType === 1044) return "QZSS";
@@ -1402,6 +1406,7 @@ function rtcm3Constellation(msgType) {
1402
1406
  if (msgType >= 1111 && msgType <= 1117) return "QZSS";
1403
1407
  if (msgType >= 1121 && msgType <= 1127) return "BeiDou";
1404
1408
  if (msgType >= 1131 && msgType <= 1137) return "NavIC";
1409
+ if (msgType === 1230) return "GLONASS";
1405
1410
  return null;
1406
1411
  }
1407
1412
  function createStreamStats() {
package/dist/rtcm3.js CHANGED
@@ -15,9 +15,9 @@ import {
15
15
  setRtcm3DebugHandler,
16
16
  updateStationMeta,
17
17
  updateStreamStats
18
- } from "./chunk-7EEWQ5DU.js";
18
+ } from "./chunk-65CQINSB.js";
19
19
  import "./chunk-LEEU5OIO.js";
20
- import "./chunk-W5WKEV7U.js";
20
+ import "./chunk-FIEWO4J4.js";
21
21
  export {
22
22
  BitReader,
23
23
  RTCM3_MESSAGE_NAMES,