gnss-js 2.7.0 → 2.8.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/{chunk-JYWYQ7DW.js → chunk-GLMQRZDL.js} +51 -46
- package/dist/{chunk-BWLLHLLS.js → chunk-PHS7OFHN.js} +3 -24
- package/dist/index.cjs +52 -70
- package/dist/index.js +2 -2
- package/dist/orbit.cjs +50 -46
- package/dist/orbit.d.cts +23 -6
- package/dist/orbit.d.ts +23 -6
- package/dist/orbit.js +1 -1
- package/dist/positioning.cjs +48 -69
- package/dist/positioning.js +2 -2
- package/package.json +1 -1
|
@@ -13,6 +13,30 @@ import {
|
|
|
13
13
|
OMEGA_E
|
|
14
14
|
} from "./chunk-FIEWO4J4.js";
|
|
15
15
|
|
|
16
|
+
// src/orbit/matrix.ts
|
|
17
|
+
function invertMatrix(A) {
|
|
18
|
+
const n = A.length;
|
|
19
|
+
const M = A.map((row, i) => [
|
|
20
|
+
...row,
|
|
21
|
+
...Array.from({ length: n }, (_, j) => i === j ? 1 : 0)
|
|
22
|
+
]);
|
|
23
|
+
for (let col = 0; col < n; col++) {
|
|
24
|
+
let piv = col;
|
|
25
|
+
for (let r = col + 1; r < n; r++)
|
|
26
|
+
if (Math.abs(M[r][col]) > Math.abs(M[piv][col])) piv = r;
|
|
27
|
+
if (Math.abs(M[piv][col]) < 1e-12) return null;
|
|
28
|
+
[M[col], M[piv]] = [M[piv], M[col]];
|
|
29
|
+
const d = M[col][col];
|
|
30
|
+
for (let j = 0; j < 2 * n; j++) M[col][j] /= d;
|
|
31
|
+
for (let r = 0; r < n; r++) {
|
|
32
|
+
if (r === col) continue;
|
|
33
|
+
const f = M[r][col];
|
|
34
|
+
for (let j = 0; j < 2 * n; j++) M[r][j] -= f * M[col][j];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return M.map((row) => row.slice(n));
|
|
38
|
+
}
|
|
39
|
+
|
|
16
40
|
// src/orbit/almanac.ts
|
|
17
41
|
var GM_GPS = 3986005e8;
|
|
18
42
|
var GM_GAL = 3986004418e5;
|
|
@@ -382,15 +406,20 @@ function ecefToAzEl(rxX, rxY, rxZ, satX, satY, satZ) {
|
|
|
382
406
|
}
|
|
383
407
|
function computeDop(satAzEls) {
|
|
384
408
|
const n = satAzEls.length;
|
|
385
|
-
|
|
409
|
+
const clocks = [...new Set(satAzEls.map((s) => s.prn?.[0] ?? ""))];
|
|
410
|
+
const m = 3 + clocks.length;
|
|
411
|
+
if (n < Math.max(4, m)) return null;
|
|
386
412
|
const H = [];
|
|
387
|
-
for (const { az, el } of satAzEls) {
|
|
413
|
+
for (const { az, el, prn } of satAzEls) {
|
|
388
414
|
const cosEl = Math.cos(el);
|
|
389
|
-
|
|
415
|
+
const row = [cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el)];
|
|
416
|
+
const sys = prn?.[0] ?? "";
|
|
417
|
+
for (const c of clocks) row.push(c === sys ? 1 : 0);
|
|
418
|
+
H.push(row);
|
|
390
419
|
}
|
|
391
|
-
const HtH = Array.from({ length:
|
|
392
|
-
for (let i = 0; i <
|
|
393
|
-
for (let j = 0; j <
|
|
420
|
+
const HtH = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
421
|
+
for (let i = 0; i < m; i++) {
|
|
422
|
+
for (let j = 0; j < m; j++) {
|
|
394
423
|
let sum = 0;
|
|
395
424
|
for (let k = 0; k < n; k++) {
|
|
396
425
|
sum += H[k][i] * H[k][j];
|
|
@@ -398,46 +427,18 @@ function computeDop(satAzEls) {
|
|
|
398
427
|
HtH[i][j] = sum;
|
|
399
428
|
}
|
|
400
429
|
}
|
|
401
|
-
const Q =
|
|
430
|
+
const Q = invertMatrix(HtH);
|
|
402
431
|
if (!Q) return null;
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
inv[4] = -a[4] * a[10] * a[15] + a[4] * a[11] * a[14] + a[8] * a[6] * a[15] - a[8] * a[7] * a[14] - a[12] * a[6] * a[11] + a[12] * a[7] * a[10];
|
|
414
|
-
inv[8] = a[4] * a[9] * a[15] - a[4] * a[11] * a[13] - a[8] * a[5] * a[15] + a[8] * a[7] * a[13] + a[12] * a[5] * a[11] - a[12] * a[7] * a[9];
|
|
415
|
-
inv[12] = -a[4] * a[9] * a[14] + a[4] * a[10] * a[13] + a[8] * a[5] * a[14] - a[8] * a[6] * a[13] - a[12] * a[5] * a[10] + a[12] * a[6] * a[9];
|
|
416
|
-
inv[1] = -a[1] * a[10] * a[15] + a[1] * a[11] * a[14] + a[9] * a[2] * a[15] - a[9] * a[3] * a[14] - a[13] * a[2] * a[11] + a[13] * a[3] * a[10];
|
|
417
|
-
inv[5] = a[0] * a[10] * a[15] - a[0] * a[11] * a[14] - a[8] * a[2] * a[15] + a[8] * a[3] * a[14] + a[12] * a[2] * a[11] - a[12] * a[3] * a[10];
|
|
418
|
-
inv[9] = -a[0] * a[9] * a[15] + a[0] * a[11] * a[13] + a[8] * a[1] * a[15] - a[8] * a[3] * a[13] - a[12] * a[1] * a[11] + a[12] * a[3] * a[9];
|
|
419
|
-
inv[13] = a[0] * a[9] * a[14] - a[0] * a[10] * a[13] - a[8] * a[1] * a[14] + a[8] * a[2] * a[13] + a[12] * a[1] * a[10] - a[12] * a[2] * a[9];
|
|
420
|
-
inv[2] = a[1] * a[6] * a[15] - a[1] * a[7] * a[14] - a[5] * a[2] * a[15] + a[5] * a[3] * a[14] + a[13] * a[2] * a[7] - a[13] * a[3] * a[6];
|
|
421
|
-
inv[6] = -a[0] * a[6] * a[15] + a[0] * a[7] * a[14] + a[4] * a[2] * a[15] - a[4] * a[3] * a[14] - a[12] * a[2] * a[7] + a[12] * a[3] * a[6];
|
|
422
|
-
inv[10] = a[0] * a[5] * a[15] - a[0] * a[7] * a[13] - a[4] * a[1] * a[15] + a[4] * a[3] * a[13] + a[12] * a[1] * a[7] - a[12] * a[3] * a[5];
|
|
423
|
-
inv[14] = -a[0] * a[5] * a[14] + a[0] * a[6] * a[13] + a[4] * a[1] * a[14] - a[4] * a[2] * a[13] - a[12] * a[1] * a[6] + a[12] * a[2] * a[5];
|
|
424
|
-
inv[3] = -a[1] * a[6] * a[11] + a[1] * a[7] * a[10] + a[5] * a[2] * a[11] - a[5] * a[3] * a[10] - a[9] * a[2] * a[7] + a[9] * a[3] * a[6];
|
|
425
|
-
inv[7] = a[0] * a[6] * a[11] - a[0] * a[7] * a[10] - a[4] * a[2] * a[11] + a[4] * a[3] * a[10] + a[8] * a[2] * a[7] - a[8] * a[3] * a[6];
|
|
426
|
-
inv[11] = -a[0] * a[5] * a[11] + a[0] * a[7] * a[9] + a[4] * a[1] * a[11] - a[4] * a[3] * a[9] - a[8] * a[1] * a[7] + a[8] * a[3] * a[5];
|
|
427
|
-
inv[15] = a[0] * a[5] * a[10] - a[0] * a[6] * a[9] - a[4] * a[1] * a[10] + a[4] * a[2] * a[9] + a[8] * a[1] * a[6] - a[8] * a[2] * a[5];
|
|
428
|
-
let det = a[0] * inv[0] + a[1] * inv[4] + a[2] * inv[8] + a[3] * inv[12];
|
|
429
|
-
if (Math.abs(det) < 1e-20) return null;
|
|
430
|
-
det = 1 / det;
|
|
431
|
-
const result = Array.from(
|
|
432
|
-
{ length: 4 },
|
|
433
|
-
() => new Array(4).fill(0)
|
|
434
|
-
);
|
|
435
|
-
for (let i = 0; i < 4; i++) {
|
|
436
|
-
for (let j = 0; j < 4; j++) {
|
|
437
|
-
result[i][j] = inv[i * 4 + j] * det;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
return result;
|
|
432
|
+
let clockVar = 0;
|
|
433
|
+
for (let i = 3; i < m; i++) clockVar += Q[i][i];
|
|
434
|
+
const posVar = Q[0][0] + Q[1][1] + Q[2][2];
|
|
435
|
+
return {
|
|
436
|
+
gdop: Math.sqrt(posVar + clockVar),
|
|
437
|
+
pdop: Math.sqrt(posVar),
|
|
438
|
+
hdop: Math.sqrt(Q[0][0] + Q[1][1]),
|
|
439
|
+
vdop: Math.sqrt(Q[2][2]),
|
|
440
|
+
tdop: Math.sqrt(clockVar)
|
|
441
|
+
};
|
|
441
442
|
}
|
|
442
443
|
function selectEphemeris(ephemerides, prn, timeMs) {
|
|
443
444
|
return selectBest(
|
|
@@ -697,6 +698,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
697
698
|
const gdop = new Array(times.length).fill(null);
|
|
698
699
|
const hdop = new Array(times.length).fill(null);
|
|
699
700
|
const vdop = new Array(times.length).fill(null);
|
|
701
|
+
const tdop = new Array(times.length).fill(null);
|
|
700
702
|
const visiblePerEpoch = times.map(() => []);
|
|
701
703
|
for (const prn of all.prns) {
|
|
702
704
|
const series = all.positions[prn];
|
|
@@ -710,7 +712,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
710
712
|
visibleCount[i]++;
|
|
711
713
|
const sys = prn[0];
|
|
712
714
|
(visibleBySystem[sys] ??= new Array(times.length).fill(0))[i]++;
|
|
713
|
-
visiblePerEpoch[i].push({ az: p.az, el: p.el });
|
|
715
|
+
visiblePerEpoch[i].push({ az: p.az, el: p.el, prn });
|
|
714
716
|
}
|
|
715
717
|
}
|
|
716
718
|
}
|
|
@@ -720,6 +722,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
720
722
|
gdop[i] = dop ? dop.gdop : null;
|
|
721
723
|
hdop[i] = dop ? dop.hdop : null;
|
|
722
724
|
vdop[i] = dop ? dop.vdop : null;
|
|
725
|
+
tdop[i] = dop ? dop.tdop : null;
|
|
723
726
|
}
|
|
724
727
|
const passes = [];
|
|
725
728
|
for (const prn of all.prns) {
|
|
@@ -766,11 +769,13 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
766
769
|
gdop,
|
|
767
770
|
hdop,
|
|
768
771
|
vdop,
|
|
772
|
+
tdop,
|
|
769
773
|
passes
|
|
770
774
|
};
|
|
771
775
|
}
|
|
772
776
|
|
|
773
777
|
export {
|
|
778
|
+
invertMatrix,
|
|
774
779
|
almanacEpochMs,
|
|
775
780
|
almanacSatPosition,
|
|
776
781
|
glonassAlmanacEpochMs,
|
|
@@ -5,8 +5,9 @@ import {
|
|
|
5
5
|
computeDop,
|
|
6
6
|
computeSatPosition,
|
|
7
7
|
ecefToAzEl,
|
|
8
|
+
invertMatrix,
|
|
8
9
|
selectEphemeris
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GLMQRZDL.js";
|
|
10
11
|
import {
|
|
11
12
|
ecefToGeodetic,
|
|
12
13
|
getAer,
|
|
@@ -3730,28 +3731,6 @@ function sbasAirTropoVar(elRad) {
|
|
|
3730
3731
|
const sigTropo = 0.12 * m;
|
|
3731
3732
|
return sigMp * sigMp + NOISE_DIVG_AADA * NOISE_DIVG_AADA + sigTropo * sigTropo;
|
|
3732
3733
|
}
|
|
3733
|
-
function invertMatrix(A) {
|
|
3734
|
-
const n = A.length;
|
|
3735
|
-
const M = A.map((row, i) => [
|
|
3736
|
-
...row,
|
|
3737
|
-
...Array.from({ length: n }, (_, j) => i === j ? 1 : 0)
|
|
3738
|
-
]);
|
|
3739
|
-
for (let col = 0; col < n; col++) {
|
|
3740
|
-
let piv = col;
|
|
3741
|
-
for (let r = col + 1; r < n; r++)
|
|
3742
|
-
if (Math.abs(M[r][col]) > Math.abs(M[piv][col])) piv = r;
|
|
3743
|
-
if (Math.abs(M[piv][col]) < 1e-12) return null;
|
|
3744
|
-
[M[col], M[piv]] = [M[piv], M[col]];
|
|
3745
|
-
const d = M[col][col];
|
|
3746
|
-
for (let j = 0; j < 2 * n; j++) M[col][j] /= d;
|
|
3747
|
-
for (let r = 0; r < n; r++) {
|
|
3748
|
-
if (r === col) continue;
|
|
3749
|
-
const f = M[r][col];
|
|
3750
|
-
for (let j = 0; j < 2 * n; j++) M[r][j] -= f * M[col][j];
|
|
3751
|
-
}
|
|
3752
|
-
}
|
|
3753
|
-
return M.map((row) => row.slice(n));
|
|
3754
|
-
}
|
|
3755
3734
|
function sbasProtectionLevels(sats, opts = {}) {
|
|
3756
3735
|
const kH = opts.kH ?? 6;
|
|
3757
3736
|
const kV = opts.kV ?? 5.33;
|
|
@@ -3978,7 +3957,7 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
|
|
|
3978
3957
|
const azel = ecefToAzEl(x, y, z, sat.x, sat.y, sat.z);
|
|
3979
3958
|
if (azel.el >= elevationMaskDeg * Math.PI / 180) {
|
|
3980
3959
|
used.push(prn);
|
|
3981
|
-
azels.push(azel);
|
|
3960
|
+
azels.push({ ...azel, prn });
|
|
3982
3961
|
if (sbas) {
|
|
3983
3962
|
const dx = sat.x - x, dy = sat.y - y, dz = sat.z - z;
|
|
3984
3963
|
const dr = Math.hypot(dx, dy, dz) || 1;
|
package/dist/index.cjs
CHANGED
|
@@ -12288,6 +12288,30 @@ function parseBinex(data) {
|
|
|
12288
12288
|
return { epochs, ephemerides, messageCounts, obsCodes, badCrc: stats.badCrc };
|
|
12289
12289
|
}
|
|
12290
12290
|
|
|
12291
|
+
// src/orbit/matrix.ts
|
|
12292
|
+
function invertMatrix(A) {
|
|
12293
|
+
const n = A.length;
|
|
12294
|
+
const M = A.map((row, i) => [
|
|
12295
|
+
...row,
|
|
12296
|
+
...Array.from({ length: n }, (_, j) => i === j ? 1 : 0)
|
|
12297
|
+
]);
|
|
12298
|
+
for (let col = 0; col < n; col++) {
|
|
12299
|
+
let piv = col;
|
|
12300
|
+
for (let r = col + 1; r < n; r++)
|
|
12301
|
+
if (Math.abs(M[r][col]) > Math.abs(M[piv][col])) piv = r;
|
|
12302
|
+
if (Math.abs(M[piv][col]) < 1e-12) return null;
|
|
12303
|
+
[M[col], M[piv]] = [M[piv], M[col]];
|
|
12304
|
+
const d = M[col][col];
|
|
12305
|
+
for (let j = 0; j < 2 * n; j++) M[col][j] /= d;
|
|
12306
|
+
for (let r = 0; r < n; r++) {
|
|
12307
|
+
if (r === col) continue;
|
|
12308
|
+
const f = M[r][col];
|
|
12309
|
+
for (let j = 0; j < 2 * n; j++) M[r][j] -= f * M[col][j];
|
|
12310
|
+
}
|
|
12311
|
+
}
|
|
12312
|
+
return M.map((row) => row.slice(n));
|
|
12313
|
+
}
|
|
12314
|
+
|
|
12291
12315
|
// src/orbit/almanac.ts
|
|
12292
12316
|
var GM_GPS = 3986005e8;
|
|
12293
12317
|
var GM_GAL = 3986004418e5;
|
|
@@ -12657,15 +12681,20 @@ function ecefToAzEl(rxX, rxY, rxZ, satX, satY, satZ) {
|
|
|
12657
12681
|
}
|
|
12658
12682
|
function computeDop(satAzEls) {
|
|
12659
12683
|
const n = satAzEls.length;
|
|
12660
|
-
|
|
12684
|
+
const clocks = [...new Set(satAzEls.map((s) => s.prn?.[0] ?? ""))];
|
|
12685
|
+
const m = 3 + clocks.length;
|
|
12686
|
+
if (n < Math.max(4, m)) return null;
|
|
12661
12687
|
const H3 = [];
|
|
12662
|
-
for (const { az, el } of satAzEls) {
|
|
12688
|
+
for (const { az, el, prn } of satAzEls) {
|
|
12663
12689
|
const cosEl = Math.cos(el);
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12690
|
+
const row = [cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el)];
|
|
12691
|
+
const sys = prn?.[0] ?? "";
|
|
12692
|
+
for (const c of clocks) row.push(c === sys ? 1 : 0);
|
|
12693
|
+
H3.push(row);
|
|
12694
|
+
}
|
|
12695
|
+
const HtH = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
12696
|
+
for (let i = 0; i < m; i++) {
|
|
12697
|
+
for (let j = 0; j < m; j++) {
|
|
12669
12698
|
let sum = 0;
|
|
12670
12699
|
for (let k = 0; k < n; k++) {
|
|
12671
12700
|
sum += H3[k][i] * H3[k][j];
|
|
@@ -12673,46 +12702,18 @@ function computeDop(satAzEls) {
|
|
|
12673
12702
|
HtH[i][j] = sum;
|
|
12674
12703
|
}
|
|
12675
12704
|
}
|
|
12676
|
-
const Q =
|
|
12705
|
+
const Q = invertMatrix(HtH);
|
|
12677
12706
|
if (!Q) return null;
|
|
12678
|
-
|
|
12679
|
-
|
|
12680
|
-
const
|
|
12681
|
-
|
|
12682
|
-
|
|
12683
|
-
|
|
12684
|
-
|
|
12685
|
-
|
|
12686
|
-
|
|
12687
|
-
|
|
12688
|
-
inv[4] = -a[4] * a[10] * a[15] + a[4] * a[11] * a[14] + a[8] * a[6] * a[15] - a[8] * a[7] * a[14] - a[12] * a[6] * a[11] + a[12] * a[7] * a[10];
|
|
12689
|
-
inv[8] = a[4] * a[9] * a[15] - a[4] * a[11] * a[13] - a[8] * a[5] * a[15] + a[8] * a[7] * a[13] + a[12] * a[5] * a[11] - a[12] * a[7] * a[9];
|
|
12690
|
-
inv[12] = -a[4] * a[9] * a[14] + a[4] * a[10] * a[13] + a[8] * a[5] * a[14] - a[8] * a[6] * a[13] - a[12] * a[5] * a[10] + a[12] * a[6] * a[9];
|
|
12691
|
-
inv[1] = -a[1] * a[10] * a[15] + a[1] * a[11] * a[14] + a[9] * a[2] * a[15] - a[9] * a[3] * a[14] - a[13] * a[2] * a[11] + a[13] * a[3] * a[10];
|
|
12692
|
-
inv[5] = a[0] * a[10] * a[15] - a[0] * a[11] * a[14] - a[8] * a[2] * a[15] + a[8] * a[3] * a[14] + a[12] * a[2] * a[11] - a[12] * a[3] * a[10];
|
|
12693
|
-
inv[9] = -a[0] * a[9] * a[15] + a[0] * a[11] * a[13] + a[8] * a[1] * a[15] - a[8] * a[3] * a[13] - a[12] * a[1] * a[11] + a[12] * a[3] * a[9];
|
|
12694
|
-
inv[13] = a[0] * a[9] * a[14] - a[0] * a[10] * a[13] - a[8] * a[1] * a[14] + a[8] * a[2] * a[13] + a[12] * a[1] * a[10] - a[12] * a[2] * a[9];
|
|
12695
|
-
inv[2] = a[1] * a[6] * a[15] - a[1] * a[7] * a[14] - a[5] * a[2] * a[15] + a[5] * a[3] * a[14] + a[13] * a[2] * a[7] - a[13] * a[3] * a[6];
|
|
12696
|
-
inv[6] = -a[0] * a[6] * a[15] + a[0] * a[7] * a[14] + a[4] * a[2] * a[15] - a[4] * a[3] * a[14] - a[12] * a[2] * a[7] + a[12] * a[3] * a[6];
|
|
12697
|
-
inv[10] = a[0] * a[5] * a[15] - a[0] * a[7] * a[13] - a[4] * a[1] * a[15] + a[4] * a[3] * a[13] + a[12] * a[1] * a[7] - a[12] * a[3] * a[5];
|
|
12698
|
-
inv[14] = -a[0] * a[5] * a[14] + a[0] * a[6] * a[13] + a[4] * a[1] * a[14] - a[4] * a[2] * a[13] - a[12] * a[1] * a[6] + a[12] * a[2] * a[5];
|
|
12699
|
-
inv[3] = -a[1] * a[6] * a[11] + a[1] * a[7] * a[10] + a[5] * a[2] * a[11] - a[5] * a[3] * a[10] - a[9] * a[2] * a[7] + a[9] * a[3] * a[6];
|
|
12700
|
-
inv[7] = a[0] * a[6] * a[11] - a[0] * a[7] * a[10] - a[4] * a[2] * a[11] + a[4] * a[3] * a[10] + a[8] * a[2] * a[7] - a[8] * a[3] * a[6];
|
|
12701
|
-
inv[11] = -a[0] * a[5] * a[11] + a[0] * a[7] * a[9] + a[4] * a[1] * a[11] - a[4] * a[3] * a[9] - a[8] * a[1] * a[7] + a[8] * a[3] * a[5];
|
|
12702
|
-
inv[15] = a[0] * a[5] * a[10] - a[0] * a[6] * a[9] - a[4] * a[1] * a[10] + a[4] * a[2] * a[9] + a[8] * a[1] * a[6] - a[8] * a[2] * a[5];
|
|
12703
|
-
let det = a[0] * inv[0] + a[1] * inv[4] + a[2] * inv[8] + a[3] * inv[12];
|
|
12704
|
-
if (Math.abs(det) < 1e-20) return null;
|
|
12705
|
-
det = 1 / det;
|
|
12706
|
-
const result = Array.from(
|
|
12707
|
-
{ length: 4 },
|
|
12708
|
-
() => new Array(4).fill(0)
|
|
12709
|
-
);
|
|
12710
|
-
for (let i = 0; i < 4; i++) {
|
|
12711
|
-
for (let j = 0; j < 4; j++) {
|
|
12712
|
-
result[i][j] = inv[i * 4 + j] * det;
|
|
12713
|
-
}
|
|
12714
|
-
}
|
|
12715
|
-
return result;
|
|
12707
|
+
let clockVar = 0;
|
|
12708
|
+
for (let i = 3; i < m; i++) clockVar += Q[i][i];
|
|
12709
|
+
const posVar = Q[0][0] + Q[1][1] + Q[2][2];
|
|
12710
|
+
return {
|
|
12711
|
+
gdop: Math.sqrt(posVar + clockVar),
|
|
12712
|
+
pdop: Math.sqrt(posVar),
|
|
12713
|
+
hdop: Math.sqrt(Q[0][0] + Q[1][1]),
|
|
12714
|
+
vdop: Math.sqrt(Q[2][2]),
|
|
12715
|
+
tdop: Math.sqrt(clockVar)
|
|
12716
|
+
};
|
|
12716
12717
|
}
|
|
12717
12718
|
function selectEphemeris(ephemerides, prn, timeMs) {
|
|
12718
12719
|
return selectBest(
|
|
@@ -12972,6 +12973,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
12972
12973
|
const gdop = new Array(times.length).fill(null);
|
|
12973
12974
|
const hdop = new Array(times.length).fill(null);
|
|
12974
12975
|
const vdop = new Array(times.length).fill(null);
|
|
12976
|
+
const tdop = new Array(times.length).fill(null);
|
|
12975
12977
|
const visiblePerEpoch = times.map(() => []);
|
|
12976
12978
|
for (const prn of all.prns) {
|
|
12977
12979
|
const series = all.positions[prn];
|
|
@@ -12985,7 +12987,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
12985
12987
|
visibleCount[i]++;
|
|
12986
12988
|
const sys = prn[0];
|
|
12987
12989
|
(visibleBySystem[sys] ??= new Array(times.length).fill(0))[i]++;
|
|
12988
|
-
visiblePerEpoch[i].push({ az: p.az, el: p.el });
|
|
12990
|
+
visiblePerEpoch[i].push({ az: p.az, el: p.el, prn });
|
|
12989
12991
|
}
|
|
12990
12992
|
}
|
|
12991
12993
|
}
|
|
@@ -12995,6 +12997,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
12995
12997
|
gdop[i] = dop ? dop.gdop : null;
|
|
12996
12998
|
hdop[i] = dop ? dop.hdop : null;
|
|
12997
12999
|
vdop[i] = dop ? dop.vdop : null;
|
|
13000
|
+
tdop[i] = dop ? dop.tdop : null;
|
|
12998
13001
|
}
|
|
12999
13002
|
const passes = [];
|
|
13000
13003
|
for (const prn of all.prns) {
|
|
@@ -13041,6 +13044,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
13041
13044
|
gdop,
|
|
13042
13045
|
hdop,
|
|
13043
13046
|
vdop,
|
|
13047
|
+
tdop,
|
|
13044
13048
|
passes
|
|
13045
13049
|
};
|
|
13046
13050
|
}
|
|
@@ -16966,28 +16970,6 @@ function sbasAirTropoVar(elRad) {
|
|
|
16966
16970
|
const sigTropo = 0.12 * m;
|
|
16967
16971
|
return sigMp * sigMp + NOISE_DIVG_AADA * NOISE_DIVG_AADA + sigTropo * sigTropo;
|
|
16968
16972
|
}
|
|
16969
|
-
function invertMatrix(A) {
|
|
16970
|
-
const n = A.length;
|
|
16971
|
-
const M = A.map((row, i) => [
|
|
16972
|
-
...row,
|
|
16973
|
-
...Array.from({ length: n }, (_, j) => i === j ? 1 : 0)
|
|
16974
|
-
]);
|
|
16975
|
-
for (let col = 0; col < n; col++) {
|
|
16976
|
-
let piv = col;
|
|
16977
|
-
for (let r = col + 1; r < n; r++)
|
|
16978
|
-
if (Math.abs(M[r][col]) > Math.abs(M[piv][col])) piv = r;
|
|
16979
|
-
if (Math.abs(M[piv][col]) < 1e-12) return null;
|
|
16980
|
-
[M[col], M[piv]] = [M[piv], M[col]];
|
|
16981
|
-
const d = M[col][col];
|
|
16982
|
-
for (let j = 0; j < 2 * n; j++) M[col][j] /= d;
|
|
16983
|
-
for (let r = 0; r < n; r++) {
|
|
16984
|
-
if (r === col) continue;
|
|
16985
|
-
const f = M[r][col];
|
|
16986
|
-
for (let j = 0; j < 2 * n; j++) M[r][j] -= f * M[col][j];
|
|
16987
|
-
}
|
|
16988
|
-
}
|
|
16989
|
-
return M.map((row) => row.slice(n));
|
|
16990
|
-
}
|
|
16991
16973
|
function sbasProtectionLevels(sats, opts = {}) {
|
|
16992
16974
|
const kH = opts.kH ?? 6;
|
|
16993
16975
|
const kV = opts.kV ?? 5.33;
|
|
@@ -17214,7 +17196,7 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
|
|
|
17214
17196
|
const azel = ecefToAzEl(x, y, z, sat.x, sat.y, sat.z);
|
|
17215
17197
|
if (azel.el >= elevationMaskDeg * Math.PI / 180) {
|
|
17216
17198
|
used.push(prn);
|
|
17217
|
-
azels.push(azel);
|
|
17199
|
+
azels.push({ ...azel, prn });
|
|
17218
17200
|
if (sbas) {
|
|
17219
17201
|
const dx = sat.x - x, dy = sat.y - y, dz = sat.z - z;
|
|
17220
17202
|
const dr = Math.hypot(dx, dy, dz) || 1;
|
package/dist/index.js
CHANGED
|
@@ -213,7 +213,7 @@ import {
|
|
|
213
213
|
sunEcef,
|
|
214
214
|
toRtkEpoch,
|
|
215
215
|
wlWavelength
|
|
216
|
-
} from "./chunk-
|
|
216
|
+
} from "./chunk-PHS7OFHN.js";
|
|
217
217
|
import "./chunk-WQX354KD.js";
|
|
218
218
|
import {
|
|
219
219
|
almanacEpochMs,
|
|
@@ -235,7 +235,7 @@ import {
|
|
|
235
235
|
navTimesFromEph,
|
|
236
236
|
rangeRate,
|
|
237
237
|
selectEphemeris
|
|
238
|
-
} from "./chunk-
|
|
238
|
+
} from "./chunk-GLMQRZDL.js";
|
|
239
239
|
import {
|
|
240
240
|
getBdsTime,
|
|
241
241
|
getDateFromBdsTime,
|
package/dist/orbit.cjs
CHANGED
|
@@ -174,6 +174,30 @@ function getGpsLeap(date) {
|
|
|
174
174
|
return leap_seconds - 19;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
// src/orbit/matrix.ts
|
|
178
|
+
function invertMatrix(A) {
|
|
179
|
+
const n = A.length;
|
|
180
|
+
const M = A.map((row, i) => [
|
|
181
|
+
...row,
|
|
182
|
+
...Array.from({ length: n }, (_, j) => i === j ? 1 : 0)
|
|
183
|
+
]);
|
|
184
|
+
for (let col = 0; col < n; col++) {
|
|
185
|
+
let piv = col;
|
|
186
|
+
for (let r = col + 1; r < n; r++)
|
|
187
|
+
if (Math.abs(M[r][col]) > Math.abs(M[piv][col])) piv = r;
|
|
188
|
+
if (Math.abs(M[piv][col]) < 1e-12) return null;
|
|
189
|
+
[M[col], M[piv]] = [M[piv], M[col]];
|
|
190
|
+
const d = M[col][col];
|
|
191
|
+
for (let j = 0; j < 2 * n; j++) M[col][j] /= d;
|
|
192
|
+
for (let r = 0; r < n; r++) {
|
|
193
|
+
if (r === col) continue;
|
|
194
|
+
const f = M[r][col];
|
|
195
|
+
for (let j = 0; j < 2 * n; j++) M[r][j] -= f * M[col][j];
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return M.map((row) => row.slice(n));
|
|
199
|
+
}
|
|
200
|
+
|
|
177
201
|
// src/orbit/almanac.ts
|
|
178
202
|
var GM_GPS = 3986005e8;
|
|
179
203
|
var GM_GAL = 3986004418e5;
|
|
@@ -543,15 +567,20 @@ function ecefToAzEl(rxX, rxY, rxZ, satX, satY, satZ) {
|
|
|
543
567
|
}
|
|
544
568
|
function computeDop(satAzEls) {
|
|
545
569
|
const n = satAzEls.length;
|
|
546
|
-
|
|
570
|
+
const clocks = [...new Set(satAzEls.map((s) => s.prn?.[0] ?? ""))];
|
|
571
|
+
const m = 3 + clocks.length;
|
|
572
|
+
if (n < Math.max(4, m)) return null;
|
|
547
573
|
const H = [];
|
|
548
|
-
for (const { az, el } of satAzEls) {
|
|
574
|
+
for (const { az, el, prn } of satAzEls) {
|
|
549
575
|
const cosEl = Math.cos(el);
|
|
550
|
-
|
|
576
|
+
const row = [cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el)];
|
|
577
|
+
const sys = prn?.[0] ?? "";
|
|
578
|
+
for (const c of clocks) row.push(c === sys ? 1 : 0);
|
|
579
|
+
H.push(row);
|
|
551
580
|
}
|
|
552
|
-
const HtH = Array.from({ length:
|
|
553
|
-
for (let i = 0; i <
|
|
554
|
-
for (let j = 0; j <
|
|
581
|
+
const HtH = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
582
|
+
for (let i = 0; i < m; i++) {
|
|
583
|
+
for (let j = 0; j < m; j++) {
|
|
555
584
|
let sum = 0;
|
|
556
585
|
for (let k = 0; k < n; k++) {
|
|
557
586
|
sum += H[k][i] * H[k][j];
|
|
@@ -559,46 +588,18 @@ function computeDop(satAzEls) {
|
|
|
559
588
|
HtH[i][j] = sum;
|
|
560
589
|
}
|
|
561
590
|
}
|
|
562
|
-
const Q =
|
|
591
|
+
const Q = invertMatrix(HtH);
|
|
563
592
|
if (!Q) return null;
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
const
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
inv[4] = -a[4] * a[10] * a[15] + a[4] * a[11] * a[14] + a[8] * a[6] * a[15] - a[8] * a[7] * a[14] - a[12] * a[6] * a[11] + a[12] * a[7] * a[10];
|
|
575
|
-
inv[8] = a[4] * a[9] * a[15] - a[4] * a[11] * a[13] - a[8] * a[5] * a[15] + a[8] * a[7] * a[13] + a[12] * a[5] * a[11] - a[12] * a[7] * a[9];
|
|
576
|
-
inv[12] = -a[4] * a[9] * a[14] + a[4] * a[10] * a[13] + a[8] * a[5] * a[14] - a[8] * a[6] * a[13] - a[12] * a[5] * a[10] + a[12] * a[6] * a[9];
|
|
577
|
-
inv[1] = -a[1] * a[10] * a[15] + a[1] * a[11] * a[14] + a[9] * a[2] * a[15] - a[9] * a[3] * a[14] - a[13] * a[2] * a[11] + a[13] * a[3] * a[10];
|
|
578
|
-
inv[5] = a[0] * a[10] * a[15] - a[0] * a[11] * a[14] - a[8] * a[2] * a[15] + a[8] * a[3] * a[14] + a[12] * a[2] * a[11] - a[12] * a[3] * a[10];
|
|
579
|
-
inv[9] = -a[0] * a[9] * a[15] + a[0] * a[11] * a[13] + a[8] * a[1] * a[15] - a[8] * a[3] * a[13] - a[12] * a[1] * a[11] + a[12] * a[3] * a[9];
|
|
580
|
-
inv[13] = a[0] * a[9] * a[14] - a[0] * a[10] * a[13] - a[8] * a[1] * a[14] + a[8] * a[2] * a[13] + a[12] * a[1] * a[10] - a[12] * a[2] * a[9];
|
|
581
|
-
inv[2] = a[1] * a[6] * a[15] - a[1] * a[7] * a[14] - a[5] * a[2] * a[15] + a[5] * a[3] * a[14] + a[13] * a[2] * a[7] - a[13] * a[3] * a[6];
|
|
582
|
-
inv[6] = -a[0] * a[6] * a[15] + a[0] * a[7] * a[14] + a[4] * a[2] * a[15] - a[4] * a[3] * a[14] - a[12] * a[2] * a[7] + a[12] * a[3] * a[6];
|
|
583
|
-
inv[10] = a[0] * a[5] * a[15] - a[0] * a[7] * a[13] - a[4] * a[1] * a[15] + a[4] * a[3] * a[13] + a[12] * a[1] * a[7] - a[12] * a[3] * a[5];
|
|
584
|
-
inv[14] = -a[0] * a[5] * a[14] + a[0] * a[6] * a[13] + a[4] * a[1] * a[14] - a[4] * a[2] * a[13] - a[12] * a[1] * a[6] + a[12] * a[2] * a[5];
|
|
585
|
-
inv[3] = -a[1] * a[6] * a[11] + a[1] * a[7] * a[10] + a[5] * a[2] * a[11] - a[5] * a[3] * a[10] - a[9] * a[2] * a[7] + a[9] * a[3] * a[6];
|
|
586
|
-
inv[7] = a[0] * a[6] * a[11] - a[0] * a[7] * a[10] - a[4] * a[2] * a[11] + a[4] * a[3] * a[10] + a[8] * a[2] * a[7] - a[8] * a[3] * a[6];
|
|
587
|
-
inv[11] = -a[0] * a[5] * a[11] + a[0] * a[7] * a[9] + a[4] * a[1] * a[11] - a[4] * a[3] * a[9] - a[8] * a[1] * a[7] + a[8] * a[3] * a[5];
|
|
588
|
-
inv[15] = a[0] * a[5] * a[10] - a[0] * a[6] * a[9] - a[4] * a[1] * a[10] + a[4] * a[2] * a[9] + a[8] * a[1] * a[6] - a[8] * a[2] * a[5];
|
|
589
|
-
let det = a[0] * inv[0] + a[1] * inv[4] + a[2] * inv[8] + a[3] * inv[12];
|
|
590
|
-
if (Math.abs(det) < 1e-20) return null;
|
|
591
|
-
det = 1 / det;
|
|
592
|
-
const result = Array.from(
|
|
593
|
-
{ length: 4 },
|
|
594
|
-
() => new Array(4).fill(0)
|
|
595
|
-
);
|
|
596
|
-
for (let i = 0; i < 4; i++) {
|
|
597
|
-
for (let j = 0; j < 4; j++) {
|
|
598
|
-
result[i][j] = inv[i * 4 + j] * det;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
return result;
|
|
593
|
+
let clockVar = 0;
|
|
594
|
+
for (let i = 3; i < m; i++) clockVar += Q[i][i];
|
|
595
|
+
const posVar = Q[0][0] + Q[1][1] + Q[2][2];
|
|
596
|
+
return {
|
|
597
|
+
gdop: Math.sqrt(posVar + clockVar),
|
|
598
|
+
pdop: Math.sqrt(posVar),
|
|
599
|
+
hdop: Math.sqrt(Q[0][0] + Q[1][1]),
|
|
600
|
+
vdop: Math.sqrt(Q[2][2]),
|
|
601
|
+
tdop: Math.sqrt(clockVar)
|
|
602
|
+
};
|
|
602
603
|
}
|
|
603
604
|
function selectEphemeris(ephemerides, prn, timeMs) {
|
|
604
605
|
return selectBest(
|
|
@@ -858,6 +859,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
858
859
|
const gdop = new Array(times.length).fill(null);
|
|
859
860
|
const hdop = new Array(times.length).fill(null);
|
|
860
861
|
const vdop = new Array(times.length).fill(null);
|
|
862
|
+
const tdop = new Array(times.length).fill(null);
|
|
861
863
|
const visiblePerEpoch = times.map(() => []);
|
|
862
864
|
for (const prn of all.prns) {
|
|
863
865
|
const series = all.positions[prn];
|
|
@@ -871,7 +873,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
871
873
|
visibleCount[i]++;
|
|
872
874
|
const sys = prn[0];
|
|
873
875
|
(visibleBySystem[sys] ??= new Array(times.length).fill(0))[i]++;
|
|
874
|
-
visiblePerEpoch[i].push({ az: p.az, el: p.el });
|
|
876
|
+
visiblePerEpoch[i].push({ az: p.az, el: p.el, prn });
|
|
875
877
|
}
|
|
876
878
|
}
|
|
877
879
|
}
|
|
@@ -881,6 +883,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
881
883
|
gdop[i] = dop ? dop.gdop : null;
|
|
882
884
|
hdop[i] = dop ? dop.hdop : null;
|
|
883
885
|
vdop[i] = dop ? dop.vdop : null;
|
|
886
|
+
tdop[i] = dop ? dop.tdop : null;
|
|
884
887
|
}
|
|
885
888
|
const passes = [];
|
|
886
889
|
for (const prn of all.prns) {
|
|
@@ -927,6 +930,7 @@ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
|
|
|
927
930
|
gdop,
|
|
928
931
|
hdop,
|
|
929
932
|
vdop,
|
|
933
|
+
tdop,
|
|
930
934
|
passes
|
|
931
935
|
};
|
|
932
936
|
}
|
package/dist/orbit.d.cts
CHANGED
|
@@ -118,6 +118,11 @@ interface DopValues {
|
|
|
118
118
|
pdop: number;
|
|
119
119
|
hdop: number;
|
|
120
120
|
vdop: number;
|
|
121
|
+
/**
|
|
122
|
+
* Time DOP: root of the summed receiver-clock variances (one clock per
|
|
123
|
+
* constellation in view), so GDOP² = PDOP² + TDOP².
|
|
124
|
+
*/
|
|
125
|
+
tdop: number;
|
|
121
126
|
}
|
|
122
127
|
/**
|
|
123
128
|
* Compute satellite ECEF position and velocity from Keplerian ephemeris.
|
|
@@ -154,12 +159,22 @@ declare function ecefToAzEl(rxX: number, rxY: number, rxZ: number, satX: number,
|
|
|
154
159
|
};
|
|
155
160
|
/**
|
|
156
161
|
* Compute DOP values from a set of satellite az/el.
|
|
157
|
-
*
|
|
158
|
-
*
|
|
162
|
+
*
|
|
163
|
+
* Satellites tagged with a `prn` get one receiver-clock unknown per
|
|
164
|
+
* constellation (the PRN's system letter), matching how a multi-GNSS
|
|
165
|
+
* receiver solves and how `solveSpp` does: each system runs on its own
|
|
166
|
+
* time scale, so every extra constellation costs one observation. Untagged
|
|
167
|
+
* satellites share a single clock (the classic single-system model).
|
|
168
|
+
*
|
|
169
|
+
* @param satAzEls Satellite azimuth/elevation pairs (radians), optionally
|
|
170
|
+
* tagged with their PRN.
|
|
171
|
+
* @returns DOP values, or null when there are fewer satellites than
|
|
172
|
+
* unknowns (3 + one clock per constellation) or the geometry is singular.
|
|
159
173
|
*/
|
|
160
174
|
declare function computeDop(satAzEls: {
|
|
161
175
|
az: number;
|
|
162
176
|
el: number;
|
|
177
|
+
prn?: string;
|
|
163
178
|
}[]): DopValues | null;
|
|
164
179
|
/**
|
|
165
180
|
* Find the best ephemeris for a given PRN at a given time.
|
|
@@ -242,14 +257,16 @@ interface VisibilityResult {
|
|
|
242
257
|
visibleCount: number[];
|
|
243
258
|
/** Per-system visible counts per epoch (system letter → counts). */
|
|
244
259
|
visibleBySystem: Record<string, number[]>;
|
|
245
|
-
/** PDOP per epoch (null when
|
|
260
|
+
/** PDOP per epoch (null when fewer satellites than unknowns). */
|
|
246
261
|
pdop: (number | null)[];
|
|
247
|
-
/** GDOP per epoch (null when
|
|
262
|
+
/** GDOP per epoch (null when fewer satellites than unknowns). */
|
|
248
263
|
gdop: (number | null)[];
|
|
249
|
-
/** HDOP per epoch (null when
|
|
264
|
+
/** HDOP per epoch (null when fewer satellites than unknowns). */
|
|
250
265
|
hdop: (number | null)[];
|
|
251
|
-
/** VDOP per epoch (null when
|
|
266
|
+
/** VDOP per epoch (null when fewer satellites than unknowns). */
|
|
252
267
|
vdop: (number | null)[];
|
|
268
|
+
/** TDOP per epoch (all constellation clocks; null like the others). */
|
|
269
|
+
tdop: (number | null)[];
|
|
253
270
|
/** Discrete above-mask passes, sorted by rise time. */
|
|
254
271
|
passes: VisibilityPass[];
|
|
255
272
|
}
|
package/dist/orbit.d.ts
CHANGED
|
@@ -118,6 +118,11 @@ interface DopValues {
|
|
|
118
118
|
pdop: number;
|
|
119
119
|
hdop: number;
|
|
120
120
|
vdop: number;
|
|
121
|
+
/**
|
|
122
|
+
* Time DOP: root of the summed receiver-clock variances (one clock per
|
|
123
|
+
* constellation in view), so GDOP² = PDOP² + TDOP².
|
|
124
|
+
*/
|
|
125
|
+
tdop: number;
|
|
121
126
|
}
|
|
122
127
|
/**
|
|
123
128
|
* Compute satellite ECEF position and velocity from Keplerian ephemeris.
|
|
@@ -154,12 +159,22 @@ declare function ecefToAzEl(rxX: number, rxY: number, rxZ: number, satX: number,
|
|
|
154
159
|
};
|
|
155
160
|
/**
|
|
156
161
|
* Compute DOP values from a set of satellite az/el.
|
|
157
|
-
*
|
|
158
|
-
*
|
|
162
|
+
*
|
|
163
|
+
* Satellites tagged with a `prn` get one receiver-clock unknown per
|
|
164
|
+
* constellation (the PRN's system letter), matching how a multi-GNSS
|
|
165
|
+
* receiver solves and how `solveSpp` does: each system runs on its own
|
|
166
|
+
* time scale, so every extra constellation costs one observation. Untagged
|
|
167
|
+
* satellites share a single clock (the classic single-system model).
|
|
168
|
+
*
|
|
169
|
+
* @param satAzEls Satellite azimuth/elevation pairs (radians), optionally
|
|
170
|
+
* tagged with their PRN.
|
|
171
|
+
* @returns DOP values, or null when there are fewer satellites than
|
|
172
|
+
* unknowns (3 + one clock per constellation) or the geometry is singular.
|
|
159
173
|
*/
|
|
160
174
|
declare function computeDop(satAzEls: {
|
|
161
175
|
az: number;
|
|
162
176
|
el: number;
|
|
177
|
+
prn?: string;
|
|
163
178
|
}[]): DopValues | null;
|
|
164
179
|
/**
|
|
165
180
|
* Find the best ephemeris for a given PRN at a given time.
|
|
@@ -242,14 +257,16 @@ interface VisibilityResult {
|
|
|
242
257
|
visibleCount: number[];
|
|
243
258
|
/** Per-system visible counts per epoch (system letter → counts). */
|
|
244
259
|
visibleBySystem: Record<string, number[]>;
|
|
245
|
-
/** PDOP per epoch (null when
|
|
260
|
+
/** PDOP per epoch (null when fewer satellites than unknowns). */
|
|
246
261
|
pdop: (number | null)[];
|
|
247
|
-
/** GDOP per epoch (null when
|
|
262
|
+
/** GDOP per epoch (null when fewer satellites than unknowns). */
|
|
248
263
|
gdop: (number | null)[];
|
|
249
|
-
/** HDOP per epoch (null when
|
|
264
|
+
/** HDOP per epoch (null when fewer satellites than unknowns). */
|
|
250
265
|
hdop: (number | null)[];
|
|
251
|
-
/** VDOP per epoch (null when
|
|
266
|
+
/** VDOP per epoch (null when fewer satellites than unknowns). */
|
|
252
267
|
vdop: (number | null)[];
|
|
268
|
+
/** TDOP per epoch (all constellation clocks; null like the others). */
|
|
269
|
+
tdop: (number | null)[];
|
|
253
270
|
/** Discrete above-mask passes, sorted by rise time. */
|
|
254
271
|
passes: VisibilityPass[];
|
|
255
272
|
}
|
package/dist/orbit.js
CHANGED
package/dist/positioning.cjs
CHANGED
|
@@ -230,6 +230,30 @@ function getGpsLeap(date) {
|
|
|
230
230
|
return leap_seconds - 19;
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
// src/orbit/matrix.ts
|
|
234
|
+
function invertMatrix(A) {
|
|
235
|
+
const n = A.length;
|
|
236
|
+
const M = A.map((row, i) => [
|
|
237
|
+
...row,
|
|
238
|
+
...Array.from({ length: n }, (_, j) => i === j ? 1 : 0)
|
|
239
|
+
]);
|
|
240
|
+
for (let col = 0; col < n; col++) {
|
|
241
|
+
let piv = col;
|
|
242
|
+
for (let r = col + 1; r < n; r++)
|
|
243
|
+
if (Math.abs(M[r][col]) > Math.abs(M[piv][col])) piv = r;
|
|
244
|
+
if (Math.abs(M[piv][col]) < 1e-12) return null;
|
|
245
|
+
[M[col], M[piv]] = [M[piv], M[col]];
|
|
246
|
+
const d = M[col][col];
|
|
247
|
+
for (let j = 0; j < 2 * n; j++) M[col][j] /= d;
|
|
248
|
+
for (let r = 0; r < n; r++) {
|
|
249
|
+
if (r === col) continue;
|
|
250
|
+
const f = M[r][col];
|
|
251
|
+
for (let j = 0; j < 2 * n; j++) M[r][j] -= f * M[col][j];
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return M.map((row) => row.slice(n));
|
|
255
|
+
}
|
|
256
|
+
|
|
233
257
|
// src/orbit/index.ts
|
|
234
258
|
var GM_GPS = 3986005e8;
|
|
235
259
|
var GM_GAL = 3986004418e5;
|
|
@@ -415,15 +439,20 @@ function ecefToAzEl(rxX, rxY, rxZ, satX, satY, satZ) {
|
|
|
415
439
|
}
|
|
416
440
|
function computeDop(satAzEls) {
|
|
417
441
|
const n = satAzEls.length;
|
|
418
|
-
|
|
442
|
+
const clocks = [...new Set(satAzEls.map((s) => s.prn?.[0] ?? ""))];
|
|
443
|
+
const m = 3 + clocks.length;
|
|
444
|
+
if (n < Math.max(4, m)) return null;
|
|
419
445
|
const H = [];
|
|
420
|
-
for (const { az, el } of satAzEls) {
|
|
446
|
+
for (const { az, el, prn } of satAzEls) {
|
|
421
447
|
const cosEl = Math.cos(el);
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
448
|
+
const row = [cosEl * Math.sin(az), cosEl * Math.cos(az), Math.sin(el)];
|
|
449
|
+
const sys = prn?.[0] ?? "";
|
|
450
|
+
for (const c of clocks) row.push(c === sys ? 1 : 0);
|
|
451
|
+
H.push(row);
|
|
452
|
+
}
|
|
453
|
+
const HtH = Array.from({ length: m }, () => new Array(m).fill(0));
|
|
454
|
+
for (let i = 0; i < m; i++) {
|
|
455
|
+
for (let j = 0; j < m; j++) {
|
|
427
456
|
let sum = 0;
|
|
428
457
|
for (let k = 0; k < n; k++) {
|
|
429
458
|
sum += H[k][i] * H[k][j];
|
|
@@ -431,46 +460,18 @@ function computeDop(satAzEls) {
|
|
|
431
460
|
HtH[i][j] = sum;
|
|
432
461
|
}
|
|
433
462
|
}
|
|
434
|
-
const Q =
|
|
463
|
+
const Q = invertMatrix(HtH);
|
|
435
464
|
if (!Q) return null;
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
inv[4] = -a[4] * a[10] * a[15] + a[4] * a[11] * a[14] + a[8] * a[6] * a[15] - a[8] * a[7] * a[14] - a[12] * a[6] * a[11] + a[12] * a[7] * a[10];
|
|
447
|
-
inv[8] = a[4] * a[9] * a[15] - a[4] * a[11] * a[13] - a[8] * a[5] * a[15] + a[8] * a[7] * a[13] + a[12] * a[5] * a[11] - a[12] * a[7] * a[9];
|
|
448
|
-
inv[12] = -a[4] * a[9] * a[14] + a[4] * a[10] * a[13] + a[8] * a[5] * a[14] - a[8] * a[6] * a[13] - a[12] * a[5] * a[10] + a[12] * a[6] * a[9];
|
|
449
|
-
inv[1] = -a[1] * a[10] * a[15] + a[1] * a[11] * a[14] + a[9] * a[2] * a[15] - a[9] * a[3] * a[14] - a[13] * a[2] * a[11] + a[13] * a[3] * a[10];
|
|
450
|
-
inv[5] = a[0] * a[10] * a[15] - a[0] * a[11] * a[14] - a[8] * a[2] * a[15] + a[8] * a[3] * a[14] + a[12] * a[2] * a[11] - a[12] * a[3] * a[10];
|
|
451
|
-
inv[9] = -a[0] * a[9] * a[15] + a[0] * a[11] * a[13] + a[8] * a[1] * a[15] - a[8] * a[3] * a[13] - a[12] * a[1] * a[11] + a[12] * a[3] * a[9];
|
|
452
|
-
inv[13] = a[0] * a[9] * a[14] - a[0] * a[10] * a[13] - a[8] * a[1] * a[14] + a[8] * a[2] * a[13] + a[12] * a[1] * a[10] - a[12] * a[2] * a[9];
|
|
453
|
-
inv[2] = a[1] * a[6] * a[15] - a[1] * a[7] * a[14] - a[5] * a[2] * a[15] + a[5] * a[3] * a[14] + a[13] * a[2] * a[7] - a[13] * a[3] * a[6];
|
|
454
|
-
inv[6] = -a[0] * a[6] * a[15] + a[0] * a[7] * a[14] + a[4] * a[2] * a[15] - a[4] * a[3] * a[14] - a[12] * a[2] * a[7] + a[12] * a[3] * a[6];
|
|
455
|
-
inv[10] = a[0] * a[5] * a[15] - a[0] * a[7] * a[13] - a[4] * a[1] * a[15] + a[4] * a[3] * a[13] + a[12] * a[1] * a[7] - a[12] * a[3] * a[5];
|
|
456
|
-
inv[14] = -a[0] * a[5] * a[14] + a[0] * a[6] * a[13] + a[4] * a[1] * a[14] - a[4] * a[2] * a[13] - a[12] * a[1] * a[6] + a[12] * a[2] * a[5];
|
|
457
|
-
inv[3] = -a[1] * a[6] * a[11] + a[1] * a[7] * a[10] + a[5] * a[2] * a[11] - a[5] * a[3] * a[10] - a[9] * a[2] * a[7] + a[9] * a[3] * a[6];
|
|
458
|
-
inv[7] = a[0] * a[6] * a[11] - a[0] * a[7] * a[10] - a[4] * a[2] * a[11] + a[4] * a[3] * a[10] + a[8] * a[2] * a[7] - a[8] * a[3] * a[6];
|
|
459
|
-
inv[11] = -a[0] * a[5] * a[11] + a[0] * a[7] * a[9] + a[4] * a[1] * a[11] - a[4] * a[3] * a[9] - a[8] * a[1] * a[7] + a[8] * a[3] * a[5];
|
|
460
|
-
inv[15] = a[0] * a[5] * a[10] - a[0] * a[6] * a[9] - a[4] * a[1] * a[10] + a[4] * a[2] * a[9] + a[8] * a[1] * a[6] - a[8] * a[2] * a[5];
|
|
461
|
-
let det = a[0] * inv[0] + a[1] * inv[4] + a[2] * inv[8] + a[3] * inv[12];
|
|
462
|
-
if (Math.abs(det) < 1e-20) return null;
|
|
463
|
-
det = 1 / det;
|
|
464
|
-
const result = Array.from(
|
|
465
|
-
{ length: 4 },
|
|
466
|
-
() => new Array(4).fill(0)
|
|
467
|
-
);
|
|
468
|
-
for (let i = 0; i < 4; i++) {
|
|
469
|
-
for (let j = 0; j < 4; j++) {
|
|
470
|
-
result[i][j] = inv[i * 4 + j] * det;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
return result;
|
|
465
|
+
let clockVar = 0;
|
|
466
|
+
for (let i = 3; i < m; i++) clockVar += Q[i][i];
|
|
467
|
+
const posVar = Q[0][0] + Q[1][1] + Q[2][2];
|
|
468
|
+
return {
|
|
469
|
+
gdop: Math.sqrt(posVar + clockVar),
|
|
470
|
+
pdop: Math.sqrt(posVar),
|
|
471
|
+
hdop: Math.sqrt(Q[0][0] + Q[1][1]),
|
|
472
|
+
vdop: Math.sqrt(Q[2][2]),
|
|
473
|
+
tdop: Math.sqrt(clockVar)
|
|
474
|
+
};
|
|
474
475
|
}
|
|
475
476
|
function selectEphemeris(ephemerides, prn, timeMs) {
|
|
476
477
|
return selectBest(
|
|
@@ -4307,28 +4308,6 @@ function sbasAirTropoVar(elRad) {
|
|
|
4307
4308
|
const sigTropo = 0.12 * m;
|
|
4308
4309
|
return sigMp * sigMp + NOISE_DIVG_AADA * NOISE_DIVG_AADA + sigTropo * sigTropo;
|
|
4309
4310
|
}
|
|
4310
|
-
function invertMatrix(A) {
|
|
4311
|
-
const n = A.length;
|
|
4312
|
-
const M = A.map((row, i) => [
|
|
4313
|
-
...row,
|
|
4314
|
-
...Array.from({ length: n }, (_, j) => i === j ? 1 : 0)
|
|
4315
|
-
]);
|
|
4316
|
-
for (let col = 0; col < n; col++) {
|
|
4317
|
-
let piv = col;
|
|
4318
|
-
for (let r = col + 1; r < n; r++)
|
|
4319
|
-
if (Math.abs(M[r][col]) > Math.abs(M[piv][col])) piv = r;
|
|
4320
|
-
if (Math.abs(M[piv][col]) < 1e-12) return null;
|
|
4321
|
-
[M[col], M[piv]] = [M[piv], M[col]];
|
|
4322
|
-
const d = M[col][col];
|
|
4323
|
-
for (let j = 0; j < 2 * n; j++) M[col][j] /= d;
|
|
4324
|
-
for (let r = 0; r < n; r++) {
|
|
4325
|
-
if (r === col) continue;
|
|
4326
|
-
const f = M[r][col];
|
|
4327
|
-
for (let j = 0; j < 2 * n; j++) M[r][j] -= f * M[col][j];
|
|
4328
|
-
}
|
|
4329
|
-
}
|
|
4330
|
-
return M.map((row) => row.slice(n));
|
|
4331
|
-
}
|
|
4332
4311
|
function sbasProtectionLevels(sats, opts = {}) {
|
|
4333
4312
|
const kH = opts.kH ?? 6;
|
|
4334
4313
|
const kV = opts.kV ?? 5.33;
|
|
@@ -4555,7 +4534,7 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
|
|
|
4555
4534
|
const azel = ecefToAzEl(x, y, z, sat.x, sat.y, sat.z);
|
|
4556
4535
|
if (azel.el >= elevationMaskDeg * Math.PI / 180) {
|
|
4557
4536
|
used.push(prn);
|
|
4558
|
-
azels.push(azel);
|
|
4537
|
+
azels.push({ ...azel, prn });
|
|
4559
4538
|
if (sbas) {
|
|
4560
4539
|
const dx = sat.x - x, dy = sat.y - y, dz = sat.z - z;
|
|
4561
4540
|
const dr = Math.hypot(dx, dy, dz) || 1;
|
package/dist/positioning.js
CHANGED
|
@@ -40,9 +40,9 @@ import {
|
|
|
40
40
|
sunEcef,
|
|
41
41
|
toRtkEpoch,
|
|
42
42
|
wlWavelength
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-PHS7OFHN.js";
|
|
44
44
|
import "./chunk-WQX354KD.js";
|
|
45
|
-
import "./chunk-
|
|
45
|
+
import "./chunk-GLMQRZDL.js";
|
|
46
46
|
import "./chunk-HVXYFUCB.js";
|
|
47
47
|
import "./chunk-CVCTRIWU.js";
|
|
48
48
|
import "./chunk-37QNKGTC.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gnss-js",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "Comprehensive GNSS library for JavaScript — time scales, coordinates, RINEX parsing, RTCM3 decoding, orbit computation, and signal analysis",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|