gnss-js 1.0.0 → 1.1.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/README.md +26 -0
- package/dist/analysis.cjs +143 -36
- package/dist/analysis.js +3 -3
- package/dist/{chunk-HKN3PUGN.js → chunk-5SPJH4MG.js} +35 -26
- package/dist/{chunk-WR7LCB52.js → chunk-BJHTBYNG.js} +15 -4
- package/dist/{chunk-Y3R57B5P.js → chunk-G3N4S3DM.js} +37 -8
- package/dist/{chunk-PRSZIWKM.js → chunk-JDO3LEPC.js} +100 -132
- package/dist/{chunk-K7WZQFBV.js → chunk-MIIM4LDY.js} +4 -1
- package/dist/{chunk-CB6EOOLA.js → chunk-OZCYOM5D.js} +70 -21
- package/dist/{chunk-SDRRAJT5.js → chunk-PGHDJFQK.js} +31 -14
- package/dist/{chunk-IS4UUDBV.js → chunk-W4YMQKWH.js} +54 -9
- package/dist/{chunk-354IRDOG.js → chunk-W5WKEV7U.js} +39 -9
- package/dist/constants.cjs +39 -9
- package/dist/constants.js +26 -26
- package/dist/coordinates.cjs +4 -1
- package/dist/coordinates.js +1 -1
- package/dist/{ephemeris-BUWzfmBy.d.cts → ephemeris-Ohl6NAfw.d.cts} +12 -2
- package/dist/{ephemeris-BUWzfmBy.d.ts → ephemeris-Ohl6NAfw.d.ts} +12 -2
- package/dist/index.cjs +366 -220
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +40 -34
- package/dist/ntrip.cjs +15 -4
- package/dist/ntrip.js +1 -1
- package/dist/orbit.cjs +31 -14
- package/dist/orbit.d.cts +1 -1
- package/dist/orbit.d.ts +1 -1
- package/dist/orbit.js +2 -1
- package/dist/rinex.cjs +123 -29
- package/dist/rinex.js +3 -3
- package/dist/rtcm3.cjs +123 -131
- package/dist/rtcm3.d.cts +9 -3
- package/dist/rtcm3.d.ts +9 -3
- package/dist/rtcm3.js +9 -2
- package/dist/signals.cjs +55 -26
- package/dist/signals.d.cts +26 -26
- package/dist/signals.d.ts +26 -26
- package/dist/signals.js +2 -1
- package/package.json +1 -2
|
@@ -1,33 +1,43 @@
|
|
|
1
1
|
import {
|
|
2
2
|
C_LIGHT,
|
|
3
|
+
FREQ,
|
|
3
4
|
GLO_F1_BASE,
|
|
4
5
|
GLO_F1_STEP,
|
|
5
6
|
GLO_F2_BASE,
|
|
6
7
|
GLO_F2_STEP
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-W5WKEV7U.js";
|
|
9
|
+
import {
|
|
10
|
+
MILLISECONDS_IN_WEEK,
|
|
11
|
+
START_BDS_TIME,
|
|
12
|
+
START_GPS_TIME
|
|
13
|
+
} from "./chunk-LEEU5OIO.js";
|
|
8
14
|
|
|
9
15
|
// src/rtcm3/decoder.ts
|
|
16
|
+
var debugHandler = null;
|
|
17
|
+
function setRtcm3DebugHandler(fn) {
|
|
18
|
+
debugHandler = fn;
|
|
19
|
+
}
|
|
20
|
+
function reportDecodeError(context, error) {
|
|
21
|
+
if (debugHandler) debugHandler(context, error);
|
|
22
|
+
}
|
|
10
23
|
var BitReader = class {
|
|
11
24
|
data;
|
|
12
25
|
bitPos = 0;
|
|
13
26
|
constructor(data) {
|
|
14
27
|
this.data = data;
|
|
15
28
|
}
|
|
16
|
-
/** Read `n` bits as unsigned integer (max
|
|
29
|
+
/** Read `n` bits as unsigned integer (max 53). */
|
|
17
30
|
readU(n) {
|
|
18
31
|
if (n === 0) return 0;
|
|
19
32
|
let val = 0;
|
|
20
33
|
for (let i = 0; i < n; i++) {
|
|
21
34
|
const byteIdx = this.bitPos + i >> 3;
|
|
22
35
|
const bitIdx = 7 - (this.bitPos + i & 7);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
} else {
|
|
26
|
-
val <<= 1;
|
|
27
|
-
}
|
|
36
|
+
const bit = byteIdx < this.data.length ? this.data[byteIdx] >> bitIdx & 1 : 0;
|
|
37
|
+
val = val * 2 + bit;
|
|
28
38
|
}
|
|
29
39
|
this.bitPos += n;
|
|
30
|
-
return val
|
|
40
|
+
return val;
|
|
31
41
|
}
|
|
32
42
|
/** Read `n` bits as signed (two's complement) integer. */
|
|
33
43
|
readS(n) {
|
|
@@ -38,9 +48,9 @@ var BitReader = class {
|
|
|
38
48
|
/** Read `n` bits as sign-magnitude integer (MSB = sign, rest = magnitude). */
|
|
39
49
|
readSM(n) {
|
|
40
50
|
const val = this.readU(n);
|
|
41
|
-
const
|
|
42
|
-
const mag = val
|
|
43
|
-
return
|
|
51
|
+
const half = 2 ** (n - 1);
|
|
52
|
+
const mag = val % half;
|
|
53
|
+
return val >= half ? -mag : mag;
|
|
44
54
|
}
|
|
45
55
|
/** Skip `n` bits. */
|
|
46
56
|
skip(n) {
|
|
@@ -544,31 +554,32 @@ function decodeEphemeris(frame) {
|
|
|
544
554
|
default:
|
|
545
555
|
return null;
|
|
546
556
|
}
|
|
547
|
-
} catch {
|
|
557
|
+
} catch (err) {
|
|
558
|
+
reportDecodeError("ephemeris", err);
|
|
548
559
|
return null;
|
|
549
560
|
}
|
|
550
561
|
}
|
|
551
562
|
|
|
552
563
|
// src/rtcm3/msm.ts
|
|
553
|
-
var GPS_L1 =
|
|
554
|
-
var GPS_L2 =
|
|
555
|
-
var GPS_L5 =
|
|
556
|
-
var GLO_L1a =
|
|
557
|
-
var GLO_L2a =
|
|
558
|
-
var GLO_L3 =
|
|
559
|
-
var GAL_E1 =
|
|
560
|
-
var GAL_E5a =
|
|
561
|
-
var GAL_E5b =
|
|
562
|
-
var GAL_E5 =
|
|
563
|
-
var GAL_E6 =
|
|
564
|
-
var BDS_B1 =
|
|
565
|
-
var BDS_B3 =
|
|
566
|
-
var BDS_B2 =
|
|
567
|
-
var BDS_B1C =
|
|
568
|
-
var BDS_B2a =
|
|
569
|
-
var BDS_B2b =
|
|
570
|
-
var QZSS_L6 =
|
|
571
|
-
var NAVIC_S =
|
|
564
|
+
var GPS_L1 = FREQ.G["1"];
|
|
565
|
+
var GPS_L2 = FREQ.G["2"];
|
|
566
|
+
var GPS_L5 = FREQ.G["5"];
|
|
567
|
+
var GLO_L1a = FREQ.R["4"];
|
|
568
|
+
var GLO_L2a = FREQ.R["6"];
|
|
569
|
+
var GLO_L3 = FREQ.R["3"];
|
|
570
|
+
var GAL_E1 = FREQ.E["1"];
|
|
571
|
+
var GAL_E5a = FREQ.E["5"];
|
|
572
|
+
var GAL_E5b = FREQ.E["7"];
|
|
573
|
+
var GAL_E5 = FREQ.E["8"];
|
|
574
|
+
var GAL_E6 = FREQ.E["6"];
|
|
575
|
+
var BDS_B1 = FREQ.C["2"];
|
|
576
|
+
var BDS_B3 = FREQ.C["6"];
|
|
577
|
+
var BDS_B2 = FREQ.C["7"];
|
|
578
|
+
var BDS_B1C = FREQ.C["1"];
|
|
579
|
+
var BDS_B2a = FREQ.C["5"];
|
|
580
|
+
var BDS_B2b = FREQ.C["7"];
|
|
581
|
+
var QZSS_L6 = FREQ.J["6"];
|
|
582
|
+
var NAVIC_S = FREQ.I["9"];
|
|
572
583
|
var EMPTY = { code: "", freq: 0 };
|
|
573
584
|
function sd(code, freq) {
|
|
574
585
|
return { code, freq };
|
|
@@ -820,43 +831,6 @@ function signalTable(sys) {
|
|
|
820
831
|
return GPS_SIGNALS;
|
|
821
832
|
}
|
|
822
833
|
}
|
|
823
|
-
var BitReader2 = class {
|
|
824
|
-
data;
|
|
825
|
-
pos;
|
|
826
|
-
constructor(data, startBit = 0) {
|
|
827
|
-
this.data = data;
|
|
828
|
-
this.pos = startBit;
|
|
829
|
-
}
|
|
830
|
-
/** Read unsigned value of numBits bits */
|
|
831
|
-
u(numBits) {
|
|
832
|
-
let val = 0;
|
|
833
|
-
for (let i = 0; i < numBits; i++) {
|
|
834
|
-
const byteIdx = this.pos + i >>> 3;
|
|
835
|
-
const bitIdx = 7 - (this.pos + i & 7);
|
|
836
|
-
if (byteIdx < this.data.length) {
|
|
837
|
-
val = val << 1 | this.data[byteIdx] >>> bitIdx & 1;
|
|
838
|
-
} else {
|
|
839
|
-
val <<= 1;
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
this.pos += numBits;
|
|
843
|
-
return val;
|
|
844
|
-
}
|
|
845
|
-
/** Read signed value (two's complement) */
|
|
846
|
-
s(numBits) {
|
|
847
|
-
const raw = this.u(numBits);
|
|
848
|
-
const sign = 1 << numBits - 1;
|
|
849
|
-
return (raw & sign - 1) - (raw & sign);
|
|
850
|
-
}
|
|
851
|
-
/** Skip bits */
|
|
852
|
-
skip(n) {
|
|
853
|
-
this.pos += n;
|
|
854
|
-
}
|
|
855
|
-
/** Current bit position */
|
|
856
|
-
get position() {
|
|
857
|
-
return this.pos;
|
|
858
|
-
}
|
|
859
|
-
};
|
|
860
834
|
var gloFreqNum = new Int8Array(64).fill(-128);
|
|
861
835
|
function gloWavelength(satIdx, freqMarker) {
|
|
862
836
|
const k = gloFreqNum[satIdx];
|
|
@@ -891,28 +865,9 @@ function lockTimeSec(msmType, lti) {
|
|
|
891
865
|
if (variant <= 5) {
|
|
892
866
|
return LTI_TABLE_4BIT[lti] ?? 0;
|
|
893
867
|
}
|
|
894
|
-
if (lti < 64) return lti;
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
if (lti < 160) return (lti - 128) * 8 + 256;
|
|
898
|
-
if (lti < 192) return (lti - 160) * 16 + 512;
|
|
899
|
-
if (lti < 224) return (lti - 192) * 32 + 1024;
|
|
900
|
-
if (lti < 256) return (lti - 224) * 64 + 2048;
|
|
901
|
-
if (lti < 288) return (lti - 256) * 128 + 4096;
|
|
902
|
-
if (lti < 320) return (lti - 288) * 256 + 8192;
|
|
903
|
-
if (lti < 352) return (lti - 320) * 512 + 16384;
|
|
904
|
-
if (lti < 384) return (lti - 352) * 1024 + 32768;
|
|
905
|
-
if (lti < 416) return (lti - 384) * 2048 + 65536;
|
|
906
|
-
if (lti < 448) return (lti - 416) * 4096 + 131072;
|
|
907
|
-
if (lti < 480) return (lti - 448) * 8192 + 262144;
|
|
908
|
-
if (lti < 512) return (lti - 480) * 16384 + 524288;
|
|
909
|
-
if (lti < 544) return (lti - 512) * 32768 + 1048576;
|
|
910
|
-
if (lti < 576) return (lti - 544) * 65536 + 2097152;
|
|
911
|
-
if (lti < 608) return (lti - 576) * 131072 + 4194304;
|
|
912
|
-
if (lti < 640) return (lti - 608) * 262144 + 8388608;
|
|
913
|
-
if (lti < 672) return (lti - 640) * 524288 + 16777216;
|
|
914
|
-
if (lti < 704) return (lti - 672) * 1048576 + 33554432;
|
|
915
|
-
return (lti - 704) * 2097152 + 67108864;
|
|
868
|
+
if (lti < 64) return lti / 1e3;
|
|
869
|
+
const n = Math.min(20, Math.floor((lti - 64) / 32));
|
|
870
|
+
return ((lti - 64 - 32 * n) * 2 ** (n + 1) + 2 ** (n + 6)) / 1e3;
|
|
916
871
|
}
|
|
917
872
|
function msmSystem(type) {
|
|
918
873
|
if (type >= 1071 && type <= 1077) return "G";
|
|
@@ -938,10 +893,10 @@ function decodeMsmFull(frame) {
|
|
|
938
893
|
const payload = frame.payload;
|
|
939
894
|
if (!payload || payload.length < 10) return null;
|
|
940
895
|
try {
|
|
941
|
-
const bits = new
|
|
896
|
+
const bits = new BitReader(payload);
|
|
942
897
|
bits.skip(12);
|
|
943
898
|
bits.skip(12);
|
|
944
|
-
const epochMs = bits.
|
|
899
|
+
const epochMs = bits.readU(30);
|
|
945
900
|
bits.skip(1);
|
|
946
901
|
bits.skip(3);
|
|
947
902
|
bits.skip(7);
|
|
@@ -949,8 +904,8 @@ function decodeMsmFull(frame) {
|
|
|
949
904
|
bits.skip(2);
|
|
950
905
|
bits.skip(1);
|
|
951
906
|
bits.skip(3);
|
|
952
|
-
const satMaskHi = bits.
|
|
953
|
-
const satMaskLo = bits.
|
|
907
|
+
const satMaskHi = bits.readU(32) >>> 0;
|
|
908
|
+
const satMaskLo = bits.readU(32) >>> 0;
|
|
954
909
|
const satIndices = [];
|
|
955
910
|
for (let i = 0; i < 32; i++) {
|
|
956
911
|
if (satMaskHi & 1 << 31 - i) satIndices.push(i + 1);
|
|
@@ -960,7 +915,7 @@ function decodeMsmFull(frame) {
|
|
|
960
915
|
}
|
|
961
916
|
const numSat = satIndices.length;
|
|
962
917
|
if (numSat === 0) return null;
|
|
963
|
-
const sigMask = bits.
|
|
918
|
+
const sigMask = bits.readU(32) >>> 0;
|
|
964
919
|
const sigIndices = [];
|
|
965
920
|
for (let i = 0; i < 32; i++) {
|
|
966
921
|
if (sigMask & 1 << 31 - i) sigIndices.push(i);
|
|
@@ -970,7 +925,7 @@ function decodeMsmFull(frame) {
|
|
|
970
925
|
const numCells = numSat * numSig;
|
|
971
926
|
const cellMask = [];
|
|
972
927
|
for (let i = 0; i < numCells; i++) {
|
|
973
|
-
cellMask.push(bits.
|
|
928
|
+
cellMask.push(bits.readU(1) === 1);
|
|
974
929
|
}
|
|
975
930
|
let activeCells = 0;
|
|
976
931
|
for (const c of cellMask) if (c) activeCells++;
|
|
@@ -980,14 +935,13 @@ function decodeMsmFull(frame) {
|
|
|
980
935
|
const extsat = new Int8Array(numSat);
|
|
981
936
|
const rdop = new Float64Array(numSat);
|
|
982
937
|
if (variant === 4 || variant === 6) {
|
|
983
|
-
for (let j = 0; j < numSat; j++) rrint[j] = bits.
|
|
984
|
-
for (let j = 0; j < numSat; j++)
|
|
985
|
-
for (let j = 0; j < numSat; j++) rrmod[j] = bits.u(10) / 1024;
|
|
938
|
+
for (let j = 0; j < numSat; j++) rrint[j] = bits.readU(8);
|
|
939
|
+
for (let j = 0; j < numSat; j++) rrmod[j] = bits.readU(10) / 1024;
|
|
986
940
|
} else {
|
|
987
|
-
for (let j = 0; j < numSat; j++) rrint[j] = bits.
|
|
988
|
-
for (let j = 0; j < numSat; j++) extsat[j] = bits.
|
|
989
|
-
for (let j = 0; j < numSat; j++) rrmod[j] = bits.
|
|
990
|
-
for (let j = 0; j < numSat; j++) rdop[j] = bits.
|
|
941
|
+
for (let j = 0; j < numSat; j++) rrint[j] = bits.readU(8);
|
|
942
|
+
for (let j = 0; j < numSat; j++) extsat[j] = bits.readU(4);
|
|
943
|
+
for (let j = 0; j < numSat; j++) rrmod[j] = bits.readU(10) / 1024;
|
|
944
|
+
for (let j = 0; j < numSat; j++) rdop[j] = bits.readS(14) * 1;
|
|
991
945
|
}
|
|
992
946
|
if (sys === "R") {
|
|
993
947
|
for (let j = 0; j < numSat; j++) {
|
|
@@ -1007,31 +961,31 @@ function decodeMsmFull(frame) {
|
|
|
1007
961
|
cp.fill(-1e30);
|
|
1008
962
|
dop.fill(-1e30);
|
|
1009
963
|
if (variant === 4) {
|
|
1010
|
-
for (let i = 0; i < activeCells; i++) psr[i] = bits.
|
|
1011
|
-
for (let i = 0; i < activeCells; i++) cp[i] = bits.
|
|
1012
|
-
for (let i = 0; i < activeCells; i++) ll[i] = bits.
|
|
1013
|
-
for (let i = 0; i < activeCells; i++) hc[i] = bits.
|
|
1014
|
-
for (let i = 0; i < activeCells; i++) cnr[i] = bits.
|
|
964
|
+
for (let i = 0; i < activeCells; i++) psr[i] = bits.readS(15) / 2 ** 24;
|
|
965
|
+
for (let i = 0; i < activeCells; i++) cp[i] = bits.readS(22) / 2 ** 29;
|
|
966
|
+
for (let i = 0; i < activeCells; i++) ll[i] = bits.readU(4);
|
|
967
|
+
for (let i = 0; i < activeCells; i++) hc[i] = bits.readU(1);
|
|
968
|
+
for (let i = 0; i < activeCells; i++) cnr[i] = bits.readU(6);
|
|
1015
969
|
} else if (variant === 5) {
|
|
1016
|
-
for (let i = 0; i < activeCells; i++) psr[i] = bits.
|
|
1017
|
-
for (let i = 0; i < activeCells; i++) cp[i] = bits.
|
|
1018
|
-
for (let i = 0; i < activeCells; i++) ll[i] = bits.
|
|
1019
|
-
for (let i = 0; i < activeCells; i++) hc[i] = bits.
|
|
1020
|
-
for (let i = 0; i < activeCells; i++) cnr[i] = bits.
|
|
1021
|
-
for (let i = 0; i < activeCells; i++) dop[i] = bits.
|
|
970
|
+
for (let i = 0; i < activeCells; i++) psr[i] = bits.readS(15) / 2 ** 24;
|
|
971
|
+
for (let i = 0; i < activeCells; i++) cp[i] = bits.readS(22) / 2 ** 29;
|
|
972
|
+
for (let i = 0; i < activeCells; i++) ll[i] = bits.readU(4);
|
|
973
|
+
for (let i = 0; i < activeCells; i++) hc[i] = bits.readU(1);
|
|
974
|
+
for (let i = 0; i < activeCells; i++) cnr[i] = bits.readU(6);
|
|
975
|
+
for (let i = 0; i < activeCells; i++) dop[i] = bits.readS(15) * 1e-4;
|
|
1022
976
|
} else if (variant === 6) {
|
|
1023
|
-
for (let i = 0; i < activeCells; i++) psr[i] = bits.
|
|
1024
|
-
for (let i = 0; i < activeCells; i++) cp[i] = bits.
|
|
1025
|
-
for (let i = 0; i < activeCells; i++) ll[i] = bits.
|
|
1026
|
-
for (let i = 0; i < activeCells; i++) hc[i] = bits.
|
|
1027
|
-
for (let i = 0; i < activeCells; i++) cnr[i] = bits.
|
|
977
|
+
for (let i = 0; i < activeCells; i++) psr[i] = bits.readS(20) / 2 ** 29;
|
|
978
|
+
for (let i = 0; i < activeCells; i++) cp[i] = bits.readS(24) / 2 ** 31;
|
|
979
|
+
for (let i = 0; i < activeCells; i++) ll[i] = bits.readU(10);
|
|
980
|
+
for (let i = 0; i < activeCells; i++) hc[i] = bits.readU(1);
|
|
981
|
+
for (let i = 0; i < activeCells; i++) cnr[i] = bits.readU(10) / 16;
|
|
1028
982
|
} else {
|
|
1029
|
-
for (let i = 0; i < activeCells; i++) psr[i] = bits.
|
|
1030
|
-
for (let i = 0; i < activeCells; i++) cp[i] = bits.
|
|
1031
|
-
for (let i = 0; i < activeCells; i++) ll[i] = bits.
|
|
1032
|
-
for (let i = 0; i < activeCells; i++) hc[i] = bits.
|
|
1033
|
-
for (let i = 0; i < activeCells; i++) cnr[i] = bits.
|
|
1034
|
-
for (let i = 0; i < activeCells; i++) dop[i] = bits.
|
|
983
|
+
for (let i = 0; i < activeCells; i++) psr[i] = bits.readS(20) / 2 ** 29;
|
|
984
|
+
for (let i = 0; i < activeCells; i++) cp[i] = bits.readS(24) / 2 ** 31;
|
|
985
|
+
for (let i = 0; i < activeCells; i++) ll[i] = bits.readU(10);
|
|
986
|
+
for (let i = 0; i < activeCells; i++) hc[i] = bits.readU(1);
|
|
987
|
+
for (let i = 0; i < activeCells; i++) cnr[i] = bits.readU(10) / 16;
|
|
988
|
+
for (let i = 0; i < activeCells; i++) dop[i] = bits.readS(15) * 1e-4;
|
|
1035
989
|
}
|
|
1036
990
|
const sigTable = signalTable(sys);
|
|
1037
991
|
const observations = [];
|
|
@@ -1065,11 +1019,11 @@ function decodeMsmFull(frame) {
|
|
|
1065
1019
|
wavelength
|
|
1066
1020
|
};
|
|
1067
1021
|
const psrVal = psr[cellIdx];
|
|
1068
|
-
if (psrVal > -
|
|
1022
|
+
if (psrVal > -(2 ** -10)) {
|
|
1069
1023
|
signal.pseudorange = psrVal * C_LIGHT / 1e3 + roughRange_m;
|
|
1070
1024
|
}
|
|
1071
1025
|
const cpVal = cp[cellIdx];
|
|
1072
|
-
if (cpVal > -
|
|
1026
|
+
if (cpVal > -(2 ** -8) && wavelength > 0) {
|
|
1073
1027
|
signal.phase = cpVal * C_LIGHT / 1e3 / wavelength + roughRange_m / wavelength;
|
|
1074
1028
|
}
|
|
1075
1029
|
if (variant === 5 || variant === 7) {
|
|
@@ -1097,12 +1051,13 @@ function decodeMsmFull(frame) {
|
|
|
1097
1051
|
system: sys,
|
|
1098
1052
|
observations
|
|
1099
1053
|
};
|
|
1100
|
-
} catch {
|
|
1054
|
+
} catch (err) {
|
|
1055
|
+
reportDecodeError("msm", err);
|
|
1101
1056
|
return null;
|
|
1102
1057
|
}
|
|
1103
1058
|
}
|
|
1104
|
-
var GPS_EPOCH =
|
|
1105
|
-
var MS_PER_WEEK =
|
|
1059
|
+
var GPS_EPOCH = START_GPS_TIME.getTime();
|
|
1060
|
+
var MS_PER_WEEK = MILLISECONDS_IN_WEEK;
|
|
1106
1061
|
function msmEpochToDate(sys, epochMs, refTime = /* @__PURE__ */ new Date()) {
|
|
1107
1062
|
const refMs = refTime.getTime();
|
|
1108
1063
|
if (sys === "R") {
|
|
@@ -1117,11 +1072,12 @@ function msmEpochToDate(sys, epochMs, refTime = /* @__PURE__ */ new Date()) {
|
|
|
1117
1072
|
return new Date(t2);
|
|
1118
1073
|
}
|
|
1119
1074
|
if (sys === "C") {
|
|
1120
|
-
const BDS_EPOCH =
|
|
1075
|
+
const BDS_EPOCH = START_BDS_TIME.getTime();
|
|
1121
1076
|
const weeksSinceEpoch2 = Math.floor((refMs - BDS_EPOCH) / MS_PER_WEEK);
|
|
1122
1077
|
let t2 = BDS_EPOCH + weeksSinceEpoch2 * MS_PER_WEEK + epochMs;
|
|
1123
1078
|
if (t2 - refMs > MS_PER_WEEK / 2) t2 -= MS_PER_WEEK;
|
|
1124
1079
|
else if (refMs - t2 > MS_PER_WEEK / 2) t2 += MS_PER_WEEK;
|
|
1080
|
+
t2 -= 18e3;
|
|
1125
1081
|
return new Date(t2);
|
|
1126
1082
|
}
|
|
1127
1083
|
const weeksSinceEpoch = Math.floor((refMs - GPS_EPOCH) / MS_PER_WEEK);
|
|
@@ -1131,6 +1087,11 @@ function msmEpochToDate(sys, epochMs, refTime = /* @__PURE__ */ new Date()) {
|
|
|
1131
1087
|
t -= 18e3;
|
|
1132
1088
|
return new Date(t);
|
|
1133
1089
|
}
|
|
1090
|
+
function setGloFreqNumber(slot, k) {
|
|
1091
|
+
if (slot >= 1 && slot <= 64 && k >= -7 && k <= 13) {
|
|
1092
|
+
gloFreqNum[slot - 1] = k;
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1134
1095
|
function resetGloFreqCache() {
|
|
1135
1096
|
gloFreqNum.fill(-128);
|
|
1136
1097
|
}
|
|
@@ -1264,7 +1225,8 @@ function updateStationMeta(meta, frame) {
|
|
|
1264
1225
|
default:
|
|
1265
1226
|
return false;
|
|
1266
1227
|
}
|
|
1267
|
-
} catch {
|
|
1228
|
+
} catch (err) {
|
|
1229
|
+
reportDecodeError("station", err);
|
|
1268
1230
|
return false;
|
|
1269
1231
|
}
|
|
1270
1232
|
}
|
|
@@ -1452,6 +1414,9 @@ function updateStreamStats(stats, frames, rawBytes) {
|
|
|
1452
1414
|
const eph = decodeEphemeris(frame);
|
|
1453
1415
|
if (eph) {
|
|
1454
1416
|
stats.ephemerides.set(eph.prn, eph);
|
|
1417
|
+
if (eph.freqChannel !== void 0 && eph.prn.startsWith("R")) {
|
|
1418
|
+
setGloFreqNumber(parseInt(eph.prn.slice(1), 10), eph.freqChannel);
|
|
1419
|
+
}
|
|
1455
1420
|
}
|
|
1456
1421
|
updateStationMeta(stats.stationMeta, frame);
|
|
1457
1422
|
}
|
|
@@ -1466,12 +1431,15 @@ function updateStreamStats(stats, frames, rawBytes) {
|
|
|
1466
1431
|
}
|
|
1467
1432
|
|
|
1468
1433
|
export {
|
|
1434
|
+
setRtcm3DebugHandler,
|
|
1435
|
+
reportDecodeError,
|
|
1469
1436
|
BitReader,
|
|
1470
1437
|
Rtcm3Decoder,
|
|
1471
1438
|
readString,
|
|
1472
1439
|
decodeEphemeris,
|
|
1473
1440
|
decodeMsmFull,
|
|
1474
1441
|
msmEpochToDate,
|
|
1442
|
+
setGloFreqNumber,
|
|
1475
1443
|
resetGloFreqCache,
|
|
1476
1444
|
createStationMeta,
|
|
1477
1445
|
updateStationMeta,
|
|
@@ -63,7 +63,10 @@ function vincenty(lat1, lon1, lat2, lon2) {
|
|
|
63
63
|
const cosLat2 = Math.cos(lat2), sinLat2 = Math.sin(lat2);
|
|
64
64
|
const dLon = lon2 - lon1;
|
|
65
65
|
sigma = Math.acos(
|
|
66
|
-
Math.min(
|
|
66
|
+
Math.min(
|
|
67
|
+
1,
|
|
68
|
+
Math.max(-1, sinLat1 * sinLat2 + cosLat1 * cosLat2 * Math.cos(dLon))
|
|
69
|
+
)
|
|
67
70
|
);
|
|
68
71
|
const distance2 = WGS84_SEMI_MAJOR_AXIS * sigma;
|
|
69
72
|
const ib = Math.atan2(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SYSTEM_NAMES
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-W5WKEV7U.js";
|
|
4
4
|
|
|
5
5
|
// src/rinex/crx.ts
|
|
6
6
|
function crxRepair(old, diff) {
|
|
@@ -42,10 +42,20 @@ function parseCrxDataLine(line, ntype) {
|
|
|
42
42
|
if (token.length >= 3 && token[1] === "&") {
|
|
43
43
|
const arcOrder = parseInt(token[0]);
|
|
44
44
|
const value = parseInt(token.substring(2));
|
|
45
|
-
fields.push({
|
|
45
|
+
fields.push({
|
|
46
|
+
empty: false,
|
|
47
|
+
init: true,
|
|
48
|
+
arcOrder,
|
|
49
|
+
value: isNaN(value) ? 0 : value
|
|
50
|
+
});
|
|
46
51
|
} else {
|
|
47
52
|
const value = parseInt(token);
|
|
48
|
-
fields.push({
|
|
53
|
+
fields.push({
|
|
54
|
+
empty: false,
|
|
55
|
+
init: false,
|
|
56
|
+
arcOrder: -1,
|
|
57
|
+
value: isNaN(value) ? 0 : value
|
|
58
|
+
});
|
|
49
59
|
}
|
|
50
60
|
}
|
|
51
61
|
const flagStr = pos < line.length ? line.substring(pos) : "";
|
|
@@ -55,7 +65,10 @@ function crxDecompress(prev, field) {
|
|
|
55
65
|
if (field.init) {
|
|
56
66
|
const a = new Array(Math.max(field.arcOrder + 1, 1)).fill(0);
|
|
57
67
|
a[0] = field.value;
|
|
58
|
-
return {
|
|
68
|
+
return {
|
|
69
|
+
state: { accum: a, order: 0, arcOrder: field.arcOrder },
|
|
70
|
+
result: field.value
|
|
71
|
+
};
|
|
59
72
|
}
|
|
60
73
|
if (!prev) {
|
|
61
74
|
return { state: { accum: [0], order: 0, arcOrder: 0 }, result: 0 };
|
|
@@ -68,7 +81,10 @@ function crxDecompress(prev, field) {
|
|
|
68
81
|
for (let k = order; k >= 1; k--) {
|
|
69
82
|
accum[k - 1] += accum[k];
|
|
70
83
|
}
|
|
71
|
-
return {
|
|
84
|
+
return {
|
|
85
|
+
state: { accum, order, arcOrder: prev.arcOrder },
|
|
86
|
+
result: accum[0]
|
|
87
|
+
};
|
|
72
88
|
}
|
|
73
89
|
|
|
74
90
|
// src/rinex/parser.ts
|
|
@@ -76,7 +92,9 @@ var CHUNK_SIZE = 2 * 1024 * 1024;
|
|
|
76
92
|
var yieldToMain = () => new Promise((r) => setTimeout(r, 0));
|
|
77
93
|
var noYield = () => Promise.resolve();
|
|
78
94
|
var SYSTEM_ORDER = ["G", "R", "E", "C", "J", "I", "S"];
|
|
79
|
-
var SYSTEM_RANK = Object.fromEntries(
|
|
95
|
+
var SYSTEM_RANK = Object.fromEntries(
|
|
96
|
+
SYSTEM_ORDER.map((s, i) => [s, i])
|
|
97
|
+
);
|
|
80
98
|
function systemCmp(a, b) {
|
|
81
99
|
const ra = SYSTEM_RANK[a.charAt(0)] ?? 99;
|
|
82
100
|
const rb = SYSTEM_RANK[b.charAt(0)] ?? 99;
|
|
@@ -262,7 +280,11 @@ function parseEpochLine3(line) {
|
|
|
262
280
|
const wholeSec = Math.floor(sc);
|
|
263
281
|
const ms = Math.round((sc - wholeSec) * 1e3);
|
|
264
282
|
const time = Date.UTC(yr, mo - 1, dy, hr, mn, wholeSec, ms);
|
|
265
|
-
return {
|
|
283
|
+
return {
|
|
284
|
+
time,
|
|
285
|
+
flag: isNaN(flag) ? 0 : flag,
|
|
286
|
+
numSats: isNaN(numSats) ? 0 : numSats
|
|
287
|
+
};
|
|
266
288
|
}
|
|
267
289
|
function parseEpochLine2(line) {
|
|
268
290
|
const yr2 = parseInt(line.substring(1, 3));
|
|
@@ -284,7 +306,12 @@ function parseEpochLine2(line) {
|
|
|
284
306
|
const id = satPart.substring(i, i + 3).trim();
|
|
285
307
|
if (id) satIds.push(id);
|
|
286
308
|
}
|
|
287
|
-
return {
|
|
309
|
+
return {
|
|
310
|
+
time,
|
|
311
|
+
flag: isNaN(flag) ? 0 : flag,
|
|
312
|
+
numSats: isNaN(numSats) ? 0 : numSats,
|
|
313
|
+
satIds
|
|
314
|
+
};
|
|
288
315
|
}
|
|
289
316
|
async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode) {
|
|
290
317
|
const skipEpochs = !!workerMode;
|
|
@@ -337,16 +364,19 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
337
364
|
if (!skipEpochs) {
|
|
338
365
|
const snrBySys = {};
|
|
339
366
|
for (const [sys, vals] of Object.entries(snrPerSystemAccum)) {
|
|
340
|
-
if (vals.length > 0)
|
|
367
|
+
if (vals.length > 0)
|
|
368
|
+
snrBySys[sys] = vals.reduce((a, b) => a + b, 0) / vals.length;
|
|
341
369
|
}
|
|
342
370
|
const meanSnr = snrValues.length > 0 ? snrValues.reduce((a, b) => a + b, 0) / snrValues.length : null;
|
|
343
371
|
const snrPerSat = {};
|
|
344
372
|
for (const [prn, vals] of Object.entries(snrPerSatAccum)) {
|
|
345
|
-
if (vals.length > 0)
|
|
373
|
+
if (vals.length > 0)
|
|
374
|
+
snrPerSat[prn] = vals.reduce((a, b) => a + b, 0) / vals.length;
|
|
346
375
|
}
|
|
347
376
|
const snrPerSatBand = {};
|
|
348
377
|
for (const [key, vals] of Object.entries(snrPerSatBandAccum)) {
|
|
349
|
-
if (vals.length > 0)
|
|
378
|
+
if (vals.length > 0)
|
|
379
|
+
snrPerSatBand[key] = vals.reduce((a, b) => a + b, 0) / vals.length;
|
|
350
380
|
}
|
|
351
381
|
epochs.push({
|
|
352
382
|
time: epochInfo.time,
|
|
@@ -391,7 +421,8 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
391
421
|
const codes = header.obsTypes[sys] ?? [];
|
|
392
422
|
if (onSatObs && epochInfo) {
|
|
393
423
|
const values = new Array(codes.length);
|
|
394
|
-
for (let i = 0; i < codes.length; i++)
|
|
424
|
+
for (let i = 0; i < codes.length; i++)
|
|
425
|
+
values[i] = readObsValue(obsLine, i);
|
|
395
426
|
if (!skipEpochs) {
|
|
396
427
|
for (const { idx, band } of getSnrIndices(sys)) {
|
|
397
428
|
const val = values[idx] ?? null;
|
|
@@ -628,7 +659,10 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
628
659
|
v2SnrBandInfo = snrIndicesWithBandV2(header.obsTypes);
|
|
629
660
|
v2SatIndex = 0;
|
|
630
661
|
v2CurrentSatLine = 0;
|
|
631
|
-
const continuationLines = Math.max(
|
|
662
|
+
const continuationLines = Math.max(
|
|
663
|
+
0,
|
|
664
|
+
Math.ceil((info.numSats - 12) / 12)
|
|
665
|
+
);
|
|
632
666
|
if (continuationLines > 0) {
|
|
633
667
|
v2ContinuationSatsRemaining = continuationLines;
|
|
634
668
|
} else {
|
|
@@ -668,7 +702,9 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
668
702
|
const magic = new Uint8Array(await file.slice(0, 2).arrayBuffer());
|
|
669
703
|
const isGz = magic[0] === 31 && magic[1] === 139;
|
|
670
704
|
if (magic[0] === 31 && magic[1] === 157) {
|
|
671
|
-
throw new Error(
|
|
705
|
+
throw new Error(
|
|
706
|
+
"Unix compress (.Z) files are not supported. Please decompress first (e.g. uncompress or gzip -d)."
|
|
707
|
+
);
|
|
672
708
|
}
|
|
673
709
|
if (isGz) {
|
|
674
710
|
let bytesRead = 0;
|
|
@@ -684,7 +720,9 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
684
720
|
if (done) break;
|
|
685
721
|
bytesRead += value.byteLength;
|
|
686
722
|
processChunkText(decoder.decode(value, { stream: true }), false);
|
|
687
|
-
onProgress?.(
|
|
723
|
+
onProgress?.(
|
|
724
|
+
Math.min(99, Math.round(bytesRead / (file.size * 4) * 100))
|
|
725
|
+
);
|
|
688
726
|
await yield_();
|
|
689
727
|
}
|
|
690
728
|
processChunkText(decoder.decode(), true);
|
|
@@ -694,7 +732,10 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
694
732
|
const end = Math.min(offset + CHUNK_SIZE, file.size);
|
|
695
733
|
const slice = file.slice(offset, end);
|
|
696
734
|
const arrayBuf = await slice.arrayBuffer();
|
|
697
|
-
processChunkText(
|
|
735
|
+
processChunkText(
|
|
736
|
+
decoder.decode(arrayBuf, { stream: end < file.size }),
|
|
737
|
+
false
|
|
738
|
+
);
|
|
698
739
|
onProgress?.(Math.min(99, Math.round(end / file.size * 100)));
|
|
699
740
|
await yield_();
|
|
700
741
|
}
|
|
@@ -702,19 +743,27 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
|
|
|
702
743
|
processChunkText("", true);
|
|
703
744
|
}
|
|
704
745
|
}
|
|
705
|
-
if (epochInfo && satLinesRemaining === 0 && crxPhase === "epoch")
|
|
706
|
-
|
|
746
|
+
if (epochInfo && satLinesRemaining === 0 && crxPhase === "epoch")
|
|
747
|
+
finishEpoch();
|
|
748
|
+
if (!header)
|
|
749
|
+
throw new Error("No valid RINEX header found (missing END OF HEADER).");
|
|
707
750
|
onProgress?.(100);
|
|
708
|
-
return {
|
|
751
|
+
return {
|
|
752
|
+
header,
|
|
753
|
+
epochs,
|
|
754
|
+
stats: computeStats(header, epochs, satellitesSeen)
|
|
755
|
+
};
|
|
709
756
|
}
|
|
710
757
|
function computeStats(header, epochs, satellitesSeen) {
|
|
711
758
|
const n = epochs.length;
|
|
712
759
|
const startTime = n > 0 ? new Date(epochs[0].time) : header.timeOfFirstObs;
|
|
713
760
|
const endTime = n > 0 ? new Date(epochs[n - 1].time) : header.timeOfLastObs;
|
|
714
761
|
let duration = null;
|
|
715
|
-
if (startTime && endTime)
|
|
762
|
+
if (startTime && endTime)
|
|
763
|
+
duration = (endTime.getTime() - startTime.getTime()) / 1e3;
|
|
716
764
|
let interval = header.interval;
|
|
717
|
-
if (interval === null && n >= 2)
|
|
765
|
+
if (interval === null && n >= 2)
|
|
766
|
+
interval = (epochs[1].time - epochs[0].time) / 1e3;
|
|
718
767
|
const uniqueSatsPerSystem = {};
|
|
719
768
|
let totalUnique = 0;
|
|
720
769
|
const systems = [];
|