gnss-js 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -75,6 +75,7 @@ __export(src_exports, {
75
75
  MILLISECONDS_IN_WEEK: () => MILLISECONDS_IN_WEEK,
76
76
  MILLISECONDS_TT_TAI: () => MILLISECONDS_TT_TAI,
77
77
  MultipathAccumulator: () => MultipathAccumulator,
78
+ REFERENCE_FRAMES: () => REFERENCE_FRAMES,
78
79
  RINEX_CODES: () => RINEX_CODES,
79
80
  RTCM3_MESSAGE_NAMES: () => RTCM3_MESSAGE_NAMES,
80
81
  Rtcm3Decoder: () => Rtcm3Decoder,
@@ -101,6 +102,7 @@ __export(src_exports, {
101
102
  WGS84_SEMI_MINOR_AXIS: () => WGS84_SEMI_MINOR_AXIS,
102
103
  WarningAccumulator: () => WarningAccumulator,
103
104
  analyzeQuality: () => analyzeQuality,
105
+ applyHelmert: () => applyHelmert,
104
106
  buildGloChannelMap: () => buildGloChannelMap,
105
107
  buildObsIndices: () => buildObsIndices,
106
108
  clampUnit: () => clampUnit,
@@ -116,12 +118,14 @@ __export(src_exports, {
116
118
  createStreamStats: () => createStreamStats,
117
119
  crxDecompress: () => crxDecompress,
118
120
  crxRepair: () => crxRepair,
121
+ dateToEpoch: () => dateToEpoch,
119
122
  decodeEphemeris: () => decodeEphemeris,
120
123
  decodeMsmFull: () => decodeMsmFull,
121
124
  deg2dms: () => deg2dms,
122
125
  deg2rad: () => deg2rad,
123
126
  ecefToAzEl: () => ecefToAzEl,
124
127
  ecefToGeodetic: () => ecefToGeodetic,
128
+ ephInfoToEphemeris: () => ephInfoToEphemeris,
125
129
  euclidean3D: () => euclidean3D,
126
130
  fetchSourcetable: () => fetchSourcetable,
127
131
  fmtF: () => fmtF,
@@ -189,6 +193,7 @@ __export(src_exports, {
189
193
  greatCircleMidpoint: () => greatCircleMidpoint,
190
194
  hdrLine: () => hdrLine,
191
195
  horizonDistance: () => horizonDistance,
196
+ ionoFree: () => ionoFree,
192
197
  keplerPosition: () => keplerPosition,
193
198
  msmEpochToDate: () => msmEpochToDate,
194
199
  navTimesFromEph: () => navTimesFromEph,
@@ -211,11 +216,14 @@ __export(src_exports, {
211
216
  resetGloFreqCache: () => resetGloFreqCache,
212
217
  rhumbLine: () => rhumbLine,
213
218
  rtcm3Constellation: () => rtcm3Constellation,
219
+ satClockCorrection: () => satClockCorrection,
214
220
  selectEphemeris: () => selectEphemeris,
215
221
  setGloFreqNumber: () => setGloFreqNumber,
216
222
  setRtcm3DebugHandler: () => setRtcm3DebugHandler,
223
+ solveSpp: () => solveSpp,
217
224
  systemCmp: () => systemCmp,
218
225
  systemName: () => systemName,
226
+ transformFrame: () => transformFrame,
219
227
  updateStationMeta: () => updateStationMeta,
220
228
  updateStreamStats: () => updateStreamStats,
221
229
  verifyChecksum: () => verifyChecksum,
@@ -4129,17 +4137,17 @@ function ecefToAzEl(rxX, rxY, rxZ, satX, satY, satZ) {
4129
4137
  function computeDop(satAzEls) {
4130
4138
  const n = satAzEls.length;
4131
4139
  if (n < 4) return null;
4132
- const H = [];
4140
+ const H2 = [];
4133
4141
  for (const { az, el } of satAzEls) {
4134
4142
  const cosEl = Math.cos(el);
4135
- H.push([cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el), 1]);
4143
+ H2.push([cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el), 1]);
4136
4144
  }
4137
4145
  const HtH = Array.from({ length: 4 }, () => new Array(4).fill(0));
4138
4146
  for (let i = 0; i < 4; i++) {
4139
4147
  for (let j = 0; j < 4; j++) {
4140
4148
  let sum = 0;
4141
4149
  for (let k = 0; k < n; k++) {
4142
- sum += H[k][i] * H[k][j];
4150
+ sum += H2[k][i] * H2[k][j];
4143
4151
  }
4144
4152
  HtH[i][j] = sum;
4145
4153
  }
@@ -4192,7 +4200,8 @@ function selectEphemeris(ephemerides, prn, timeMs) {
4192
4200
  if (eph.prn !== prn) continue;
4193
4201
  const ephTime = eph.tocDate.getTime();
4194
4202
  const dt = Math.abs(timeMs - ephTime);
4195
- if (dt > 4 * 3600 * 1e3) continue;
4203
+ const maxAge = eph.system === "R" || eph.system === "S" ? 18e5 : 4 * 36e5;
4204
+ if (dt > maxAge) continue;
4196
4205
  if (dt < bestDt) {
4197
4206
  bestDt = dt;
4198
4207
  best = eph;
@@ -4300,13 +4309,13 @@ function ephInfoToEphemeris(info) {
4300
4309
  return null;
4301
4310
  if (info.vx === void 0 || info.vy === void 0 || info.vz === void 0)
4302
4311
  return null;
4303
- const now = new Date(info.lastReceived);
4312
+ const moscow = new Date(info.lastReceived + 3 * 3600 * 1e3);
4304
4313
  const utcMidnight = Date.UTC(
4305
- now.getUTCFullYear(),
4306
- now.getUTCMonth(),
4307
- now.getUTCDate()
4314
+ moscow.getUTCFullYear(),
4315
+ moscow.getUTCMonth(),
4316
+ moscow.getUTCDate()
4308
4317
  );
4309
- const tbSec = (info.tb ?? 0) * 900;
4318
+ const tbSec = (info.tb ?? 0) * 60;
4310
4319
  const moscowOffset = 3 * 3600;
4311
4320
  const tocMs = utcMidnight + (tbSec - moscowOffset) * 1e3;
4312
4321
  return {
@@ -4469,6 +4478,415 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
4469
4478
  return { times, elevation, visibleCount, pdop, passes };
4470
4479
  }
4471
4480
 
4481
+ // src/frames/index.ts
4482
+ var H = (t, d, r, tDot, dDot, rDot, epoch) => ({ t, d, r, tDot, dDot, rDot, epoch });
4483
+ var Z = [0, 0, 0];
4484
+ var FROM_ITRF2020 = {
4485
+ ITRF2014: H([-1.4, -0.9, 1.4], -0.42, Z, [0, -0.1, 0.2], 0, Z, 2015),
4486
+ ITRF2008: H([0.2, 1, 3.3], -0.29, Z, [0, -0.1, 0.1], 0.03, Z, 2015),
4487
+ ITRF2005: H([2.7, 0.1, -1.4], 0.65, Z, [0.3, -0.1, 0.1], 0.03, Z, 2015),
4488
+ ITRF2000: H([-0.2, 0.8, -34.2], 2.25, Z, [0.1, 0, -1.7], 0.11, Z, 2015),
4489
+ ITRF97: H(
4490
+ [6.5, -3.9, -77.9],
4491
+ 3.98,
4492
+ [0, 0, 0.36],
4493
+ [0.1, -0.6, -3.1],
4494
+ 0.12,
4495
+ [0, 0, 0.02],
4496
+ 2015
4497
+ ),
4498
+ ITRF96: H(
4499
+ [6.5, -3.9, -77.9],
4500
+ 3.98,
4501
+ [0, 0, 0.36],
4502
+ [0.1, -0.6, -3.1],
4503
+ 0.12,
4504
+ [0, 0, 0.02],
4505
+ 2015
4506
+ ),
4507
+ ITRF94: H(
4508
+ [6.5, -3.9, -77.9],
4509
+ 3.98,
4510
+ [0, 0, 0.36],
4511
+ [0.1, -0.6, -3.1],
4512
+ 0.12,
4513
+ [0, 0, 0.02],
4514
+ 2015
4515
+ ),
4516
+ ITRF93: H(
4517
+ [-65.8, 1.9, -71.3],
4518
+ 4.47,
4519
+ [-3.36, -4.33, 0.75],
4520
+ [-2.8, -0.2, -2.3],
4521
+ 0.12,
4522
+ [-0.11, -0.19, 0.07],
4523
+ 2015
4524
+ ),
4525
+ ITRF92: H(
4526
+ [14.5, -1.9, -85.9],
4527
+ 3.27,
4528
+ [0, 0, 0.36],
4529
+ [0.1, -0.6, -3.1],
4530
+ 0.12,
4531
+ [0, 0, 0.02],
4532
+ 2015
4533
+ ),
4534
+ ITRF91: H(
4535
+ [26.5, 12.1, -91.9],
4536
+ 4.67,
4537
+ [0, 0, 0.36],
4538
+ [0.1, -0.6, -3.1],
4539
+ 0.12,
4540
+ [0, 0, 0.02],
4541
+ 2015
4542
+ ),
4543
+ ITRF90: H(
4544
+ [24.5, 8.1, -107.9],
4545
+ 4.97,
4546
+ [0, 0, 0.36],
4547
+ [0.1, -0.6, -3.1],
4548
+ 0.12,
4549
+ [0, 0, 0.02],
4550
+ 2015
4551
+ ),
4552
+ ITRF89: H(
4553
+ [29.5, 32.1, -145.9],
4554
+ 8.37,
4555
+ [0, 0, 0.36],
4556
+ [0.1, -0.6, -3.1],
4557
+ 0.12,
4558
+ [0, 0, 0.02],
4559
+ 2015
4560
+ ),
4561
+ ITRF88: H(
4562
+ [24.5, -3.9, -169.9],
4563
+ 11.47,
4564
+ [0.1, 0, 0.36],
4565
+ [0.1, -0.6, -3.1],
4566
+ 0.12,
4567
+ [0, 0, 0.02],
4568
+ 2015
4569
+ ),
4570
+ /** ITRF2020 → ETRF2020, EPSG:10572 (epoch-1989 variant) */
4571
+ ETRF2020: H(Z, 0, Z, Z, 0, [0.086, 0.519, -0.753], 1989)
4572
+ };
4573
+ var ITRF2014_TO_ETRF2014 = H(Z, 0, Z, Z, 0, [0.085, 0.531, -0.77], 1989);
4574
+ var ITRF2014_TO_ETRF2000 = H(
4575
+ [54.7, 52.2, -74.1],
4576
+ 2.12,
4577
+ [1.701, 10.29, -16.632],
4578
+ [0.1, 0.1, -1.9],
4579
+ 0.11,
4580
+ [0.081, 0.49, -0.792],
4581
+ 2010
4582
+ );
4583
+ var ITRF2014_TO_NAD83_2011 = H(
4584
+ [1005.3, -1909.21, -541.57],
4585
+ 0.36891,
4586
+ [-26.78138, 0.42027, -10.93206],
4587
+ [0.79, -0.6, -1.44],
4588
+ -0.07201,
4589
+ [-0.06667, 0.75744, 0.05133],
4590
+ 2010
4591
+ );
4592
+ var MAS_TO_RAD = Math.PI / (180 * 3600 * 1e3);
4593
+ function applyHelmert(xyz, p, epoch, inverse = false) {
4594
+ const dt = epoch - p.epoch;
4595
+ const sign = inverse ? -1 : 1;
4596
+ const tx = sign * (p.t[0] + p.tDot[0] * dt) / 1e3;
4597
+ const ty = sign * (p.t[1] + p.tDot[1] * dt) / 1e3;
4598
+ const tz = sign * (p.t[2] + p.tDot[2] * dt) / 1e3;
4599
+ const d = sign * (p.d + p.dDot * dt) * 1e-9;
4600
+ const rx = sign * (p.r[0] + p.rDot[0] * dt) * MAS_TO_RAD;
4601
+ const ry = sign * (p.r[1] + p.rDot[1] * dt) * MAS_TO_RAD;
4602
+ const rz = sign * (p.r[2] + p.rDot[2] * dt) * MAS_TO_RAD;
4603
+ const [x, y, z] = xyz;
4604
+ return [
4605
+ x + tx + d * x - rz * y + ry * z,
4606
+ y + ty + rz * x + d * y - rx * z,
4607
+ z + tz - ry * x + rx * y + d * z
4608
+ ];
4609
+ }
4610
+ var EDGES = [
4611
+ ...Object.entries(FROM_ITRF2020).map(([to, p]) => ({
4612
+ from: "ITRF2020",
4613
+ to,
4614
+ p
4615
+ })),
4616
+ { from: "ITRF2014", to: "ETRF2014", p: ITRF2014_TO_ETRF2014 },
4617
+ { from: "ITRF2014", to: "ETRF2000", p: ITRF2014_TO_ETRF2000 },
4618
+ { from: "ITRF2014", to: "NAD83(2011)", p: ITRF2014_TO_NAD83_2011 }
4619
+ ];
4620
+ var REFERENCE_FRAMES = [
4621
+ "WGS84",
4622
+ "ITRF2020",
4623
+ "ITRF2014",
4624
+ "ITRF2008",
4625
+ "ITRF2005",
4626
+ "ITRF2000",
4627
+ "ITRF97",
4628
+ "ITRF96",
4629
+ "ITRF94",
4630
+ "ITRF93",
4631
+ "ITRF92",
4632
+ "ITRF91",
4633
+ "ITRF90",
4634
+ "ITRF89",
4635
+ "ITRF88",
4636
+ "ETRF2020",
4637
+ "ETRF2014",
4638
+ "ETRF2000",
4639
+ "NAD83(2011)"
4640
+ ];
4641
+ function resolveAlias(f) {
4642
+ return f === "WGS84" ? "ITRF2020" : f;
4643
+ }
4644
+ function findPath(from, to) {
4645
+ if (from === to) return [];
4646
+ const queue = [from];
4647
+ const cameFrom = /* @__PURE__ */ new Map();
4648
+ const seen = /* @__PURE__ */ new Set([from]);
4649
+ while (queue.length > 0) {
4650
+ const cur = queue.shift();
4651
+ for (const edge of EDGES) {
4652
+ let next = null;
4653
+ let inverse = false;
4654
+ if (edge.from === cur) {
4655
+ next = edge.to;
4656
+ } else if (edge.to === cur) {
4657
+ next = edge.from;
4658
+ inverse = true;
4659
+ }
4660
+ if (next === null || seen.has(next)) continue;
4661
+ seen.add(next);
4662
+ cameFrom.set(next, { prev: cur, edge, inverse });
4663
+ if (next === to) {
4664
+ const path = [];
4665
+ let node = to;
4666
+ while (node !== from) {
4667
+ const step = cameFrom.get(node);
4668
+ path.unshift({ edge: step.edge, inverse: step.inverse });
4669
+ node = step.prev;
4670
+ }
4671
+ return path;
4672
+ }
4673
+ queue.push(next);
4674
+ }
4675
+ }
4676
+ return null;
4677
+ }
4678
+ function transformFrame(xyz, from, to, epoch) {
4679
+ const src = resolveAlias(from);
4680
+ const dst = resolveAlias(to);
4681
+ const path = findPath(src, dst);
4682
+ if (!path) {
4683
+ throw new Error(`No transformation path from ${from} to ${to}`);
4684
+ }
4685
+ let out = [xyz[0], xyz[1], xyz[2]];
4686
+ for (const { edge, inverse } of path) {
4687
+ out = applyHelmert(out, edge.p, epoch, inverse);
4688
+ }
4689
+ return out;
4690
+ }
4691
+ function dateToEpoch(date) {
4692
+ const year = date.getUTCFullYear();
4693
+ const start = Date.UTC(year, 0, 1);
4694
+ const end = Date.UTC(year + 1, 0, 1);
4695
+ return year + (date.getTime() - start) / (end - start);
4696
+ }
4697
+
4698
+ // src/positioning/index.ts
4699
+ var GM_GPS2 = 3986005e8;
4700
+ var F_REL = -4442807633e-19;
4701
+ function satClockCorrection(eph, tMs) {
4702
+ if (eph.system === "R" || eph.system === "S") {
4703
+ const dt2 = (tMs - eph.tocDate.getTime()) / 1e3;
4704
+ return eph.tauN + eph.gammaN * dt2;
4705
+ }
4706
+ const k = eph;
4707
+ const dt = (tMs - k.tocDate.getTime()) / 1e3;
4708
+ const poly = k.af0 + k.af1 * dt + k.af2 * dt * dt;
4709
+ const a = k.sqrtA * k.sqrtA;
4710
+ const n = Math.sqrt(GM_GPS2 / (a * a * a)) + k.deltaN;
4711
+ const tk = dt;
4712
+ const Mk = k.m0 + n * tk;
4713
+ let Ek = Mk;
4714
+ for (let i = 0; i < 8; i++) {
4715
+ Ek = Mk + k.e * Math.sin(Ek);
4716
+ }
4717
+ const rel = F_REL * k.e * k.sqrtA * Math.sin(Ek);
4718
+ return poly + rel;
4719
+ }
4720
+ function ionoFree(p1, p2, f1, f2) {
4721
+ const g = f1 * f1 / (f1 * f1 - f2 * f2);
4722
+ return g * p1 - (g - 1) * p2;
4723
+ }
4724
+ function tropoDelay(elevationRad) {
4725
+ const sinEl = Math.sin(elevationRad);
4726
+ return 2.47 / (sinEl + 0.0121);
4727
+ }
4728
+ function sagnac(pos, travelTimeS) {
4729
+ const OMEGA_E2 = 72921151467e-15;
4730
+ const theta = OMEGA_E2 * travelTimeS;
4731
+ const c = Math.cos(theta);
4732
+ const s = Math.sin(theta);
4733
+ return [pos.x * c + pos.y * s, -pos.x * s + pos.y * c, pos.z];
4734
+ }
4735
+ function solveLinear(A, b) {
4736
+ const n = b.length;
4737
+ const M = A.map((row, i) => [...row, b[i]]);
4738
+ for (let col = 0; col < n; col++) {
4739
+ let pivot = col;
4740
+ for (let r = col + 1; r < n; r++) {
4741
+ if (Math.abs(M[r][col]) > Math.abs(M[pivot][col])) pivot = r;
4742
+ }
4743
+ if (Math.abs(M[pivot][col]) < 1e-12) return null;
4744
+ [M[col], M[pivot]] = [M[pivot], M[col]];
4745
+ for (let r = 0; r < n; r++) {
4746
+ if (r === col) continue;
4747
+ const f = M[r][col] / M[col][col];
4748
+ for (let c = col; c <= n; c++) M[r][c] -= f * M[col][c];
4749
+ }
4750
+ }
4751
+ return M.map((row, i) => row[n] / M[i][i]);
4752
+ }
4753
+ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
4754
+ const {
4755
+ elevationMaskDeg = 10,
4756
+ troposphere = true,
4757
+ maxIterations = 15,
4758
+ convergenceM = 1e-4,
4759
+ tgd = true
4760
+ } = opts;
4761
+ const all = [...pseudoranges.keys()].filter((p) => ephemerides.has(p));
4762
+ const minSats = (list) => 3 + new Set(list.map((p) => p[0])).size;
4763
+ if (all.length < minSats(all)) return null;
4764
+ const gaussNewton = (prns) => {
4765
+ const systems = [...new Set(prns.map((p) => p[0]))].sort();
4766
+ const dim = 3 + systems.length;
4767
+ const sysIndex = new Map(systems.map((s, i) => [s, 3 + i]));
4768
+ let x2 = 0;
4769
+ let y2 = 0;
4770
+ let z2 = 0;
4771
+ const clock2 = new Map(systems.map((s) => [s, 0]));
4772
+ const residuals2 = {};
4773
+ let iterations2 = 0;
4774
+ let converged2 = false;
4775
+ for (let iter = 0; iter < maxIterations; iter++) {
4776
+ iterations2 = iter + 1;
4777
+ const HtH = Array.from(
4778
+ { length: dim },
4779
+ () => new Array(dim).fill(0)
4780
+ );
4781
+ const Htv = new Array(dim).fill(0);
4782
+ let rows = 0;
4783
+ for (const k of Object.keys(residuals2)) delete residuals2[k];
4784
+ for (const prn of prns) {
4785
+ const psr = pseudoranges.get(prn);
4786
+ const eph = ephemerides.get(prn);
4787
+ const sys = prn[0];
4788
+ const clk = clock2.get(sys);
4789
+ const tTx = timeMs - psr / C_LIGHT * 1e3;
4790
+ const dtsClock = satClockCorrection(eph, tTx);
4791
+ const sat = computeSatPosition(eph, tTx - dtsClock * 1e3);
4792
+ if (!Number.isFinite(sat.x)) continue;
4793
+ const isKepler2 = eph.system !== "R" && eph.system !== "S";
4794
+ const dts = dtsClock - (tgd && isKepler2 ? eph.tgd : 0);
4795
+ const travel = Math.hypot(sat.x - x2, sat.y - y2, sat.z - z2) / C_LIGHT;
4796
+ const [sx, sy, sz] = sagnac(sat, travel);
4797
+ const rho = Math.hypot(sx - x2, sy - y2, sz - z2);
4798
+ const ux = (x2 - sx) / rho;
4799
+ const uy = (y2 - sy) / rho;
4800
+ const uz = (z2 - sz) / rho;
4801
+ let elev = Math.PI / 2;
4802
+ let weight = 1;
4803
+ const positionSane = x2 * x2 + y2 * y2 + z2 * z2 > 1e12;
4804
+ if (positionSane) {
4805
+ const azel = ecefToAzEl(x2, y2, z2, sx, sy, sz);
4806
+ elev = azel.el;
4807
+ if (iter >= 2 && elev < elevationMaskDeg * Math.PI / 180) continue;
4808
+ const sinEl = Math.max(Math.sin(elev), 0.1);
4809
+ weight = sinEl * sinEl;
4810
+ }
4811
+ const tropo = troposphere && positionSane ? tropoDelay(elev) : 0;
4812
+ const predicted = rho + clk - C_LIGHT * dts + tropo;
4813
+ const v = psr - predicted;
4814
+ const h = new Array(dim).fill(0);
4815
+ h[0] = ux;
4816
+ h[1] = uy;
4817
+ h[2] = uz;
4818
+ h[sysIndex.get(sys)] = 1;
4819
+ for (let i = 0; i < dim; i++) {
4820
+ for (let j = 0; j < dim; j++) HtH[i][j] += weight * h[i] * h[j];
4821
+ Htv[i] += weight * h[i] * v;
4822
+ }
4823
+ residuals2[prn] = v;
4824
+ rows++;
4825
+ }
4826
+ if (rows < dim) return null;
4827
+ const dx = solveLinear(HtH, Htv);
4828
+ if (!dx) return null;
4829
+ x2 += dx[0];
4830
+ y2 += dx[1];
4831
+ z2 += dx[2];
4832
+ for (const s of systems)
4833
+ clock2.set(s, clock2.get(s) + dx[sysIndex.get(s)]);
4834
+ if (Math.hypot(dx[0], dx[1], dx[2]) < convergenceM) {
4835
+ converged2 = true;
4836
+ break;
4837
+ }
4838
+ }
4839
+ return { x: x2, y: y2, z: z2, clock: clock2, residuals: residuals2, iterations: iterations2, converged: converged2 };
4840
+ };
4841
+ const REJECT_THRESHOLD_M = 50;
4842
+ let candidates = all;
4843
+ const rejected = [];
4844
+ let inner = null;
4845
+ for (let round = 0; round <= all.length; round++) {
4846
+ inner = gaussNewton(candidates);
4847
+ if (!inner) return null;
4848
+ const vals = Object.entries(inner.residuals);
4849
+ let worst = null;
4850
+ let worstAbs = REJECT_THRESHOLD_M;
4851
+ for (const [prn, v] of vals) {
4852
+ if (Math.abs(v) > worstAbs) {
4853
+ worstAbs = Math.abs(v);
4854
+ worst = prn;
4855
+ }
4856
+ }
4857
+ if (!worst) break;
4858
+ const remaining = candidates.filter((p) => p !== worst);
4859
+ if (remaining.length < minSats(remaining)) break;
4860
+ rejected.push(worst);
4861
+ candidates = remaining;
4862
+ }
4863
+ if (!inner) return null;
4864
+ const { x, y, z, clock, residuals, iterations, converged } = inner;
4865
+ const used = [];
4866
+ const azels = [];
4867
+ for (const prn of candidates) {
4868
+ if (!(prn in residuals)) continue;
4869
+ const eph = ephemerides.get(prn);
4870
+ const sat = computeSatPosition(eph, timeMs);
4871
+ if (!Number.isFinite(sat.x)) continue;
4872
+ const azel = ecefToAzEl(x, y, z, sat.x, sat.y, sat.z);
4873
+ if (azel.el >= elevationMaskDeg * Math.PI / 180) {
4874
+ used.push(prn);
4875
+ azels.push(azel);
4876
+ }
4877
+ }
4878
+ return {
4879
+ position: [x, y, z],
4880
+ clockBias: Object.fromEntries(clock),
4881
+ usedSatellites: used,
4882
+ rejectedSatellites: rejected,
4883
+ residuals,
4884
+ dop: computeDop(azels),
4885
+ iterations,
4886
+ converged
4887
+ };
4888
+ }
4889
+
4472
4890
  // src/ntrip/index.ts
4473
4891
  function parseStreamEntry(fields) {
4474
4892
  if (fields.length < 19) return null;
@@ -6345,6 +6763,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
6345
6763
  MILLISECONDS_IN_WEEK,
6346
6764
  MILLISECONDS_TT_TAI,
6347
6765
  MultipathAccumulator,
6766
+ REFERENCE_FRAMES,
6348
6767
  RINEX_CODES,
6349
6768
  RTCM3_MESSAGE_NAMES,
6350
6769
  Rtcm3Decoder,
@@ -6371,6 +6790,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
6371
6790
  WGS84_SEMI_MINOR_AXIS,
6372
6791
  WarningAccumulator,
6373
6792
  analyzeQuality,
6793
+ applyHelmert,
6374
6794
  buildGloChannelMap,
6375
6795
  buildObsIndices,
6376
6796
  clampUnit,
@@ -6386,12 +6806,14 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
6386
6806
  createStreamStats,
6387
6807
  crxDecompress,
6388
6808
  crxRepair,
6809
+ dateToEpoch,
6389
6810
  decodeEphemeris,
6390
6811
  decodeMsmFull,
6391
6812
  deg2dms,
6392
6813
  deg2rad,
6393
6814
  ecefToAzEl,
6394
6815
  ecefToGeodetic,
6816
+ ephInfoToEphemeris,
6395
6817
  euclidean3D,
6396
6818
  fetchSourcetable,
6397
6819
  fmtF,
@@ -6459,6 +6881,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
6459
6881
  greatCircleMidpoint,
6460
6882
  hdrLine,
6461
6883
  horizonDistance,
6884
+ ionoFree,
6462
6885
  keplerPosition,
6463
6886
  msmEpochToDate,
6464
6887
  navTimesFromEph,
@@ -6481,11 +6904,14 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
6481
6904
  resetGloFreqCache,
6482
6905
  rhumbLine,
6483
6906
  rtcm3Constellation,
6907
+ satClockCorrection,
6484
6908
  selectEphemeris,
6485
6909
  setGloFreqNumber,
6486
6910
  setRtcm3DebugHandler,
6911
+ solveSpp,
6487
6912
  systemCmp,
6488
6913
  systemName,
6914
+ transformFrame,
6489
6915
  updateStationMeta,
6490
6916
  updateStreamStats,
6491
6917
  verifyChecksum,
package/dist/index.d.cts CHANGED
@@ -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.cjs';
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.cjs';
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.cjs';
12
- export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris } from './orbit.cjs';
12
+ export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris } from './orbit.cjs';
13
+ export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.cjs';
14
+ export { SppOptions, SppSolution, ionoFree, satClockCorrection, solveSpp } from './positioning.cjs';
13
15
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.cjs';
14
16
  export { CompleteSatSignal, CompleteSignalStats, CompletenessAccumulator, CompletenessResult, CycleSlipAccumulator, CycleSlipEvent, CycleSlipResult, CycleSlipSignalStats, MultipathAccumulator, MultipathPoint, MultipathResult, MultipathSeries, MultipathSignalStat, QualityResult, analyzeQuality } from './analysis.cjs';
15
17
  export { AntennaEntry, AntexFile, FrequencyData, frequencyLabel, parseAntex } from './antex.cjs';
package/dist/index.d.ts CHANGED
@@ -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
@@ -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-USHP4IND.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-CC2R4JGS.js";
102
114
  import {
103
115
  getBdsTime,
104
116
  getDateFromBdsTime,
@@ -288,6 +300,7 @@ export {
288
300
  MILLISECONDS_IN_WEEK,
289
301
  MILLISECONDS_TT_TAI,
290
302
  MultipathAccumulator,
303
+ REFERENCE_FRAMES,
291
304
  RINEX_CODES,
292
305
  RTCM3_MESSAGE_NAMES,
293
306
  Rtcm3Decoder,
@@ -314,6 +327,7 @@ export {
314
327
  WGS84_SEMI_MINOR_AXIS,
315
328
  WarningAccumulator,
316
329
  analyzeQuality,
330
+ applyHelmert,
317
331
  buildGloChannelMap,
318
332
  buildObsIndices,
319
333
  clampUnit,
@@ -329,12 +343,14 @@ export {
329
343
  createStreamStats,
330
344
  crxDecompress,
331
345
  crxRepair,
346
+ dateToEpoch,
332
347
  decodeEphemeris,
333
348
  decodeMsmFull,
334
349
  deg2dms,
335
350
  deg2rad,
336
351
  ecefToAzEl,
337
352
  ecefToGeodetic,
353
+ ephInfoToEphemeris,
338
354
  euclidean3D,
339
355
  fetchSourcetable,
340
356
  fmtF,
@@ -402,6 +418,7 @@ export {
402
418
  greatCircleMidpoint,
403
419
  hdrLine,
404
420
  horizonDistance,
421
+ ionoFree,
405
422
  keplerPosition,
406
423
  msmEpochToDate,
407
424
  navTimesFromEph,
@@ -424,11 +441,14 @@ export {
424
441
  resetGloFreqCache,
425
442
  rhumbLine,
426
443
  rtcm3Constellation,
444
+ satClockCorrection,
427
445
  selectEphemeris,
428
446
  setGloFreqNumber,
429
447
  setRtcm3DebugHandler,
448
+ solveSpp,
430
449
  systemCmp,
431
450
  systemName,
451
+ transformFrame,
432
452
  updateStationMeta,
433
453
  updateStreamStats,
434
454
  verifyChecksum,