gnss-js 1.0.1 → 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 +3 -3
- package/dist/analysis.js +3 -3
- package/dist/{chunk-HKN3PUGN.js → chunk-5SPJH4MG.js} +35 -26
- package/dist/{chunk-SO3POWWR.js → chunk-G3N4S3DM.js} +2 -2
- package/dist/{chunk-WP2JFDLA.js → chunk-JDO3LEPC.js} +93 -118
- package/dist/{chunk-HBLU2EJ4.js → chunk-OZCYOM5D.js} +1 -1
- package/dist/{chunk-4YN353Q7.js → chunk-PGHDJFQK.js} +15 -5
- package/dist/{chunk-LWNTWBHB.js → chunk-W5WKEV7U.js} +3 -2
- package/dist/constants.cjs +3 -2
- package/dist/constants.js +26 -26
- package/dist/{ephemeris-C10stHhM.d.cts → ephemeris-Ohl6NAfw.d.cts} +11 -1
- package/dist/{ephemeris-C10stHhM.d.ts → ephemeris-Ohl6NAfw.d.ts} +11 -1
- package/dist/index.cjs +130 -150
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +37 -31
- package/dist/orbit.cjs +15 -5
- package/dist/orbit.d.cts +1 -1
- package/dist/orbit.d.ts +1 -1
- package/dist/orbit.js +2 -1
- package/dist/rinex.js +2 -2
- package/dist/rtcm3.cjs +116 -117
- 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
package/README.md
CHANGED
|
@@ -167,6 +167,32 @@ Every exported function has JSDoc with `@param` and `@returns` annotations inclu
|
|
|
167
167
|
- **Class-based API** — Ergonomic wrappers like `GnssTime.fromUtc(date).gps` and `Position.fromGeodetic(lat, lon, h).utm` on top of the existing functional core
|
|
168
168
|
- **RINEX observation writers** (RINEX 2/3/4 with gzip compression)
|
|
169
169
|
|
|
170
|
+
## Development
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
pnpm install
|
|
174
|
+
bash scripts/fetch-test-data.sh # RINEX test fixtures (~5 MB, checksummed; gitignored)
|
|
175
|
+
pnpm test
|
|
176
|
+
pnpm run lint
|
|
177
|
+
pnpm run build
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Without the fixtures, the nav-file test suites are skipped silently (`describe.skipIf`), so run the fetch script before trusting a green test run.
|
|
181
|
+
|
|
182
|
+
**Releasing**: bump the version and push the tag — CI publishes to npm via Trusted Publishing (one-time setup: npm package settings → Trusted Publisher → this repo + publish.yml) and creates the GitHub Release:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
npm version patch # or minor/major; updates package.json + creates the tag
|
|
186
|
+
git push --follow-tags
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Developing against [gnsscalc](https://github.com/MiguelPuntoEs/gnsscalc)** without publishing:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
cd ../gnsscalc && pnpm link ../gnss-js # then `pnpm run build --watch` here
|
|
193
|
+
# undo with: pnpm unlink gnss-js && pnpm install
|
|
194
|
+
```
|
|
195
|
+
|
|
170
196
|
## License
|
|
171
197
|
|
|
172
198
|
This project is dual-licensed:
|
package/dist/analysis.cjs
CHANGED
|
@@ -40,7 +40,8 @@ var SYSTEM_NAMES = {
|
|
|
40
40
|
var C_LIGHT = 299792458;
|
|
41
41
|
var FREQ = {
|
|
42
42
|
G: { "1": 157542e4, "2": 12276e5, "5": 117645e4 },
|
|
43
|
-
R
|
|
43
|
+
// R bands 4/6 are the CDMA L1OC/L2OC center frequencies
|
|
44
|
+
R: { "3": 1202025e3, "4": 1600995e3, "6": 124806e4 },
|
|
44
45
|
E: {
|
|
45
46
|
"1": 157542e4,
|
|
46
47
|
"5": 117645e4,
|
|
@@ -98,7 +99,6 @@ var GLO_F1_BASE = 1602e6;
|
|
|
98
99
|
var GLO_F1_STEP = 562500;
|
|
99
100
|
var GLO_F2_BASE = 1246e6;
|
|
100
101
|
var GLO_F2_STEP = 437500;
|
|
101
|
-
var GLO_F3 = 1202025e3;
|
|
102
102
|
var GLO_CHANNEL_FALLBACK = {
|
|
103
103
|
R01: 1,
|
|
104
104
|
R02: -4,
|
|
@@ -134,11 +134,11 @@ function buildGloChannelMap(slots) {
|
|
|
134
134
|
return map;
|
|
135
135
|
}
|
|
136
136
|
function gloFreq(gloChannels, prn, band) {
|
|
137
|
+
if (band === "3" || band === "4" || band === "6") return FREQ.R[band];
|
|
137
138
|
const k = gloChannels[prn];
|
|
138
139
|
if (k === void 0) return void 0;
|
|
139
140
|
if (band === "1") return GLO_F1_BASE + k * GLO_F1_STEP;
|
|
140
141
|
if (band === "2") return GLO_F2_BASE + k * GLO_F2_STEP;
|
|
141
|
-
if (band === "3") return GLO_F3;
|
|
142
142
|
return void 0;
|
|
143
143
|
}
|
|
144
144
|
function getFreq(gloChannels, prn, band) {
|
package/dist/analysis.js
CHANGED
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
CycleSlipAccumulator,
|
|
4
4
|
MultipathAccumulator,
|
|
5
5
|
analyzeQuality
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-G3N4S3DM.js";
|
|
7
|
+
import "./chunk-OZCYOM5D.js";
|
|
8
|
+
import "./chunk-W5WKEV7U.js";
|
|
9
9
|
export {
|
|
10
10
|
CompletenessAccumulator,
|
|
11
11
|
CycleSlipAccumulator,
|
|
@@ -1,30 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FREQ,
|
|
3
|
+
GLO_F1_BASE,
|
|
4
|
+
GLO_F1_STEP,
|
|
5
|
+
GLO_F2_BASE,
|
|
6
|
+
GLO_F2_STEP
|
|
7
|
+
} from "./chunk-W5WKEV7U.js";
|
|
8
|
+
|
|
1
9
|
// src/signals/definitions.ts
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
var
|
|
14
|
-
var
|
|
15
|
-
var
|
|
16
|
-
var
|
|
17
|
-
var
|
|
18
|
-
var
|
|
19
|
-
var
|
|
20
|
-
var
|
|
21
|
-
var
|
|
22
|
-
var
|
|
23
|
-
var
|
|
24
|
-
var
|
|
25
|
-
var
|
|
26
|
-
var
|
|
27
|
-
var
|
|
10
|
+
var MHz = 1e6;
|
|
11
|
+
var FREQ_GPS_L1 = FREQ.G["1"] / MHz;
|
|
12
|
+
var FREQ_GPS_L2 = FREQ.G["2"] / MHz;
|
|
13
|
+
var FREQ_GPS_L5 = FREQ.G["5"] / MHz;
|
|
14
|
+
var FREQ_GLO_L1 = GLO_F1_BASE / MHz;
|
|
15
|
+
var FREQ_GLO_L2 = GLO_F2_BASE / MHz;
|
|
16
|
+
var DELTA_GLO_L1 = GLO_F1_STEP / MHz;
|
|
17
|
+
var DELTA_GLO_L2 = GLO_F2_STEP / MHz;
|
|
18
|
+
var FREQ_GLO_L1OC = FREQ.R["4"] / MHz;
|
|
19
|
+
var FREQ_GLO_L2OC = FREQ.R["6"] / MHz;
|
|
20
|
+
var FREQ_GLO_L3OC = FREQ.R["3"] / MHz;
|
|
21
|
+
var FREQ_GAL_E1 = FREQ.E["1"] / MHz;
|
|
22
|
+
var FREQ_GAL_E5 = FREQ.E["8"] / MHz;
|
|
23
|
+
var FREQ_GAL_E5a = FREQ.E["5"] / MHz;
|
|
24
|
+
var FREQ_GAL_E5b = FREQ.E["7"] / MHz;
|
|
25
|
+
var FREQ_GAL_E6 = FREQ.E["6"] / MHz;
|
|
26
|
+
var FREQ_BDS_B1I = FREQ.C["2"] / MHz;
|
|
27
|
+
var FREQ_BDS_B2I = FREQ.C["7"] / MHz;
|
|
28
|
+
var FREQ_BDS_B3I = FREQ.C["6"] / MHz;
|
|
29
|
+
var FREQ_BDS_B1A = FREQ.C["1"] / MHz;
|
|
30
|
+
var FREQ_BDS_B1C = FREQ.C["1"] / MHz;
|
|
31
|
+
var FREQ_BDS_B3A = FREQ.C["6"] / MHz;
|
|
32
|
+
var FREQ_QZS_L1 = FREQ.J["1"] / MHz;
|
|
33
|
+
var FREQ_QZS_L2 = FREQ.J["2"] / MHz;
|
|
34
|
+
var FREQ_QZS_L5 = FREQ.J["5"] / MHz;
|
|
35
|
+
var FREQ_QZS_L6 = FREQ.J["6"] / MHz;
|
|
36
|
+
var FREQ_NAVIC_L5 = FREQ.I["5"] / MHz;
|
|
28
37
|
var GPS_COLOR = "#4ade80";
|
|
29
38
|
var GPS_M_COLOR = "#ef4444";
|
|
30
39
|
var GPS_P_COLOR = "#dbc51f";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseRinexStream
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-OZCYOM5D.js";
|
|
4
4
|
import {
|
|
5
5
|
ARC_GAP_FACTOR,
|
|
6
6
|
BAND_LABELS,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
buildGloChannelMap,
|
|
12
12
|
buildObsIndices,
|
|
13
13
|
getFreq
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-W5WKEV7U.js";
|
|
15
15
|
|
|
16
16
|
// src/analysis/multipath.ts
|
|
17
17
|
var MIN_ARC_LENGTH = 10;
|
|
@@ -1,12 +1,25 @@
|
|
|
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;
|
|
@@ -541,31 +554,32 @@ function decodeEphemeris(frame) {
|
|
|
541
554
|
default:
|
|
542
555
|
return null;
|
|
543
556
|
}
|
|
544
|
-
} catch {
|
|
557
|
+
} catch (err) {
|
|
558
|
+
reportDecodeError("ephemeris", err);
|
|
545
559
|
return null;
|
|
546
560
|
}
|
|
547
561
|
}
|
|
548
562
|
|
|
549
563
|
// src/rtcm3/msm.ts
|
|
550
|
-
var GPS_L1 =
|
|
551
|
-
var GPS_L2 =
|
|
552
|
-
var GPS_L5 =
|
|
553
|
-
var GLO_L1a =
|
|
554
|
-
var GLO_L2a =
|
|
555
|
-
var GLO_L3 =
|
|
556
|
-
var GAL_E1 =
|
|
557
|
-
var GAL_E5a =
|
|
558
|
-
var GAL_E5b =
|
|
559
|
-
var GAL_E5 =
|
|
560
|
-
var GAL_E6 =
|
|
561
|
-
var BDS_B1 =
|
|
562
|
-
var BDS_B3 =
|
|
563
|
-
var BDS_B2 =
|
|
564
|
-
var BDS_B1C =
|
|
565
|
-
var BDS_B2a =
|
|
566
|
-
var BDS_B2b =
|
|
567
|
-
var QZSS_L6 =
|
|
568
|
-
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"];
|
|
569
583
|
var EMPTY = { code: "", freq: 0 };
|
|
570
584
|
function sd(code, freq) {
|
|
571
585
|
return { code, freq };
|
|
@@ -817,40 +831,6 @@ function signalTable(sys) {
|
|
|
817
831
|
return GPS_SIGNALS;
|
|
818
832
|
}
|
|
819
833
|
}
|
|
820
|
-
var BitReader2 = class {
|
|
821
|
-
data;
|
|
822
|
-
pos;
|
|
823
|
-
constructor(data, startBit = 0) {
|
|
824
|
-
this.data = data;
|
|
825
|
-
this.pos = startBit;
|
|
826
|
-
}
|
|
827
|
-
/** Read unsigned value of numBits bits (max 53) */
|
|
828
|
-
u(numBits) {
|
|
829
|
-
let val = 0;
|
|
830
|
-
for (let i = 0; i < numBits; i++) {
|
|
831
|
-
const byteIdx = this.pos + i >>> 3;
|
|
832
|
-
const bitIdx = 7 - (this.pos + i & 7);
|
|
833
|
-
const bit = byteIdx < this.data.length ? this.data[byteIdx] >>> bitIdx & 1 : 0;
|
|
834
|
-
val = val * 2 + bit;
|
|
835
|
-
}
|
|
836
|
-
this.pos += numBits;
|
|
837
|
-
return val;
|
|
838
|
-
}
|
|
839
|
-
/** Read signed value (two's complement) */
|
|
840
|
-
s(numBits) {
|
|
841
|
-
const raw = this.u(numBits);
|
|
842
|
-
const half = 2 ** (numBits - 1);
|
|
843
|
-
return raw >= half ? raw - 2 ** numBits : raw;
|
|
844
|
-
}
|
|
845
|
-
/** Skip bits */
|
|
846
|
-
skip(n) {
|
|
847
|
-
this.pos += n;
|
|
848
|
-
}
|
|
849
|
-
/** Current bit position */
|
|
850
|
-
get position() {
|
|
851
|
-
return this.pos;
|
|
852
|
-
}
|
|
853
|
-
};
|
|
854
834
|
var gloFreqNum = new Int8Array(64).fill(-128);
|
|
855
835
|
function gloWavelength(satIdx, freqMarker) {
|
|
856
836
|
const k = gloFreqNum[satIdx];
|
|
@@ -885,28 +865,9 @@ function lockTimeSec(msmType, lti) {
|
|
|
885
865
|
if (variant <= 5) {
|
|
886
866
|
return LTI_TABLE_4BIT[lti] ?? 0;
|
|
887
867
|
}
|
|
888
|
-
if (lti < 64) return lti;
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
if (lti < 160) return (lti - 128) * 8 + 256;
|
|
892
|
-
if (lti < 192) return (lti - 160) * 16 + 512;
|
|
893
|
-
if (lti < 224) return (lti - 192) * 32 + 1024;
|
|
894
|
-
if (lti < 256) return (lti - 224) * 64 + 2048;
|
|
895
|
-
if (lti < 288) return (lti - 256) * 128 + 4096;
|
|
896
|
-
if (lti < 320) return (lti - 288) * 256 + 8192;
|
|
897
|
-
if (lti < 352) return (lti - 320) * 512 + 16384;
|
|
898
|
-
if (lti < 384) return (lti - 352) * 1024 + 32768;
|
|
899
|
-
if (lti < 416) return (lti - 384) * 2048 + 65536;
|
|
900
|
-
if (lti < 448) return (lti - 416) * 4096 + 131072;
|
|
901
|
-
if (lti < 480) return (lti - 448) * 8192 + 262144;
|
|
902
|
-
if (lti < 512) return (lti - 480) * 16384 + 524288;
|
|
903
|
-
if (lti < 544) return (lti - 512) * 32768 + 1048576;
|
|
904
|
-
if (lti < 576) return (lti - 544) * 65536 + 2097152;
|
|
905
|
-
if (lti < 608) return (lti - 576) * 131072 + 4194304;
|
|
906
|
-
if (lti < 640) return (lti - 608) * 262144 + 8388608;
|
|
907
|
-
if (lti < 672) return (lti - 640) * 524288 + 16777216;
|
|
908
|
-
if (lti < 704) return (lti - 672) * 1048576 + 33554432;
|
|
909
|
-
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;
|
|
910
871
|
}
|
|
911
872
|
function msmSystem(type) {
|
|
912
873
|
if (type >= 1071 && type <= 1077) return "G";
|
|
@@ -932,10 +893,10 @@ function decodeMsmFull(frame) {
|
|
|
932
893
|
const payload = frame.payload;
|
|
933
894
|
if (!payload || payload.length < 10) return null;
|
|
934
895
|
try {
|
|
935
|
-
const bits = new
|
|
896
|
+
const bits = new BitReader(payload);
|
|
936
897
|
bits.skip(12);
|
|
937
898
|
bits.skip(12);
|
|
938
|
-
const epochMs = bits.
|
|
899
|
+
const epochMs = bits.readU(30);
|
|
939
900
|
bits.skip(1);
|
|
940
901
|
bits.skip(3);
|
|
941
902
|
bits.skip(7);
|
|
@@ -943,8 +904,8 @@ function decodeMsmFull(frame) {
|
|
|
943
904
|
bits.skip(2);
|
|
944
905
|
bits.skip(1);
|
|
945
906
|
bits.skip(3);
|
|
946
|
-
const satMaskHi = bits.
|
|
947
|
-
const satMaskLo = bits.
|
|
907
|
+
const satMaskHi = bits.readU(32) >>> 0;
|
|
908
|
+
const satMaskLo = bits.readU(32) >>> 0;
|
|
948
909
|
const satIndices = [];
|
|
949
910
|
for (let i = 0; i < 32; i++) {
|
|
950
911
|
if (satMaskHi & 1 << 31 - i) satIndices.push(i + 1);
|
|
@@ -954,7 +915,7 @@ function decodeMsmFull(frame) {
|
|
|
954
915
|
}
|
|
955
916
|
const numSat = satIndices.length;
|
|
956
917
|
if (numSat === 0) return null;
|
|
957
|
-
const sigMask = bits.
|
|
918
|
+
const sigMask = bits.readU(32) >>> 0;
|
|
958
919
|
const sigIndices = [];
|
|
959
920
|
for (let i = 0; i < 32; i++) {
|
|
960
921
|
if (sigMask & 1 << 31 - i) sigIndices.push(i);
|
|
@@ -964,7 +925,7 @@ function decodeMsmFull(frame) {
|
|
|
964
925
|
const numCells = numSat * numSig;
|
|
965
926
|
const cellMask = [];
|
|
966
927
|
for (let i = 0; i < numCells; i++) {
|
|
967
|
-
cellMask.push(bits.
|
|
928
|
+
cellMask.push(bits.readU(1) === 1);
|
|
968
929
|
}
|
|
969
930
|
let activeCells = 0;
|
|
970
931
|
for (const c of cellMask) if (c) activeCells++;
|
|
@@ -974,13 +935,13 @@ function decodeMsmFull(frame) {
|
|
|
974
935
|
const extsat = new Int8Array(numSat);
|
|
975
936
|
const rdop = new Float64Array(numSat);
|
|
976
937
|
if (variant === 4 || variant === 6) {
|
|
977
|
-
for (let j = 0; j < numSat; j++) rrint[j] = bits.
|
|
978
|
-
for (let j = 0; j < numSat; j++) rrmod[j] = bits.
|
|
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;
|
|
979
940
|
} else {
|
|
980
|
-
for (let j = 0; j < numSat; j++) rrint[j] = bits.
|
|
981
|
-
for (let j = 0; j < numSat; j++) extsat[j] = bits.
|
|
982
|
-
for (let j = 0; j < numSat; j++) rrmod[j] = bits.
|
|
983
|
-
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;
|
|
984
945
|
}
|
|
985
946
|
if (sys === "R") {
|
|
986
947
|
for (let j = 0; j < numSat; j++) {
|
|
@@ -1000,31 +961,31 @@ function decodeMsmFull(frame) {
|
|
|
1000
961
|
cp.fill(-1e30);
|
|
1001
962
|
dop.fill(-1e30);
|
|
1002
963
|
if (variant === 4) {
|
|
1003
|
-
for (let i = 0; i < activeCells; i++) psr[i] = bits.
|
|
1004
|
-
for (let i = 0; i < activeCells; i++) cp[i] = bits.
|
|
1005
|
-
for (let i = 0; i < activeCells; i++) ll[i] = bits.
|
|
1006
|
-
for (let i = 0; i < activeCells; i++) hc[i] = bits.
|
|
1007
|
-
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);
|
|
1008
969
|
} else if (variant === 5) {
|
|
1009
|
-
for (let i = 0; i < activeCells; i++) psr[i] = bits.
|
|
1010
|
-
for (let i = 0; i < activeCells; i++) cp[i] = bits.
|
|
1011
|
-
for (let i = 0; i < activeCells; i++) ll[i] = bits.
|
|
1012
|
-
for (let i = 0; i < activeCells; i++) hc[i] = bits.
|
|
1013
|
-
for (let i = 0; i < activeCells; i++) cnr[i] = bits.
|
|
1014
|
-
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;
|
|
1015
976
|
} else if (variant === 6) {
|
|
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.
|
|
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;
|
|
1021
982
|
} else {
|
|
1022
|
-
for (let i = 0; i < activeCells; i++) psr[i] = bits.
|
|
1023
|
-
for (let i = 0; i < activeCells; i++) cp[i] = bits.
|
|
1024
|
-
for (let i = 0; i < activeCells; i++) ll[i] = bits.
|
|
1025
|
-
for (let i = 0; i < activeCells; i++) hc[i] = bits.
|
|
1026
|
-
for (let i = 0; i < activeCells; i++) cnr[i] = bits.
|
|
1027
|
-
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;
|
|
1028
989
|
}
|
|
1029
990
|
const sigTable = signalTable(sys);
|
|
1030
991
|
const observations = [];
|
|
@@ -1058,11 +1019,11 @@ function decodeMsmFull(frame) {
|
|
|
1058
1019
|
wavelength
|
|
1059
1020
|
};
|
|
1060
1021
|
const psrVal = psr[cellIdx];
|
|
1061
|
-
if (psrVal > -
|
|
1022
|
+
if (psrVal > -(2 ** -10)) {
|
|
1062
1023
|
signal.pseudorange = psrVal * C_LIGHT / 1e3 + roughRange_m;
|
|
1063
1024
|
}
|
|
1064
1025
|
const cpVal = cp[cellIdx];
|
|
1065
|
-
if (cpVal > -
|
|
1026
|
+
if (cpVal > -(2 ** -8) && wavelength > 0) {
|
|
1066
1027
|
signal.phase = cpVal * C_LIGHT / 1e3 / wavelength + roughRange_m / wavelength;
|
|
1067
1028
|
}
|
|
1068
1029
|
if (variant === 5 || variant === 7) {
|
|
@@ -1090,12 +1051,13 @@ function decodeMsmFull(frame) {
|
|
|
1090
1051
|
system: sys,
|
|
1091
1052
|
observations
|
|
1092
1053
|
};
|
|
1093
|
-
} catch {
|
|
1054
|
+
} catch (err) {
|
|
1055
|
+
reportDecodeError("msm", err);
|
|
1094
1056
|
return null;
|
|
1095
1057
|
}
|
|
1096
1058
|
}
|
|
1097
|
-
var GPS_EPOCH =
|
|
1098
|
-
var MS_PER_WEEK =
|
|
1059
|
+
var GPS_EPOCH = START_GPS_TIME.getTime();
|
|
1060
|
+
var MS_PER_WEEK = MILLISECONDS_IN_WEEK;
|
|
1099
1061
|
function msmEpochToDate(sys, epochMs, refTime = /* @__PURE__ */ new Date()) {
|
|
1100
1062
|
const refMs = refTime.getTime();
|
|
1101
1063
|
if (sys === "R") {
|
|
@@ -1110,11 +1072,12 @@ function msmEpochToDate(sys, epochMs, refTime = /* @__PURE__ */ new Date()) {
|
|
|
1110
1072
|
return new Date(t2);
|
|
1111
1073
|
}
|
|
1112
1074
|
if (sys === "C") {
|
|
1113
|
-
const BDS_EPOCH =
|
|
1075
|
+
const BDS_EPOCH = START_BDS_TIME.getTime();
|
|
1114
1076
|
const weeksSinceEpoch2 = Math.floor((refMs - BDS_EPOCH) / MS_PER_WEEK);
|
|
1115
1077
|
let t2 = BDS_EPOCH + weeksSinceEpoch2 * MS_PER_WEEK + epochMs;
|
|
1116
1078
|
if (t2 - refMs > MS_PER_WEEK / 2) t2 -= MS_PER_WEEK;
|
|
1117
1079
|
else if (refMs - t2 > MS_PER_WEEK / 2) t2 += MS_PER_WEEK;
|
|
1080
|
+
t2 -= 18e3;
|
|
1118
1081
|
return new Date(t2);
|
|
1119
1082
|
}
|
|
1120
1083
|
const weeksSinceEpoch = Math.floor((refMs - GPS_EPOCH) / MS_PER_WEEK);
|
|
@@ -1124,6 +1087,11 @@ function msmEpochToDate(sys, epochMs, refTime = /* @__PURE__ */ new Date()) {
|
|
|
1124
1087
|
t -= 18e3;
|
|
1125
1088
|
return new Date(t);
|
|
1126
1089
|
}
|
|
1090
|
+
function setGloFreqNumber(slot, k) {
|
|
1091
|
+
if (slot >= 1 && slot <= 64 && k >= -7 && k <= 13) {
|
|
1092
|
+
gloFreqNum[slot - 1] = k;
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1127
1095
|
function resetGloFreqCache() {
|
|
1128
1096
|
gloFreqNum.fill(-128);
|
|
1129
1097
|
}
|
|
@@ -1257,7 +1225,8 @@ function updateStationMeta(meta, frame) {
|
|
|
1257
1225
|
default:
|
|
1258
1226
|
return false;
|
|
1259
1227
|
}
|
|
1260
|
-
} catch {
|
|
1228
|
+
} catch (err) {
|
|
1229
|
+
reportDecodeError("station", err);
|
|
1261
1230
|
return false;
|
|
1262
1231
|
}
|
|
1263
1232
|
}
|
|
@@ -1445,6 +1414,9 @@ function updateStreamStats(stats, frames, rawBytes) {
|
|
|
1445
1414
|
const eph = decodeEphemeris(frame);
|
|
1446
1415
|
if (eph) {
|
|
1447
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
|
+
}
|
|
1448
1420
|
}
|
|
1449
1421
|
updateStationMeta(stats.stationMeta, frame);
|
|
1450
1422
|
}
|
|
@@ -1459,12 +1431,15 @@ function updateStreamStats(stats, frames, rawBytes) {
|
|
|
1459
1431
|
}
|
|
1460
1432
|
|
|
1461
1433
|
export {
|
|
1434
|
+
setRtcm3DebugHandler,
|
|
1435
|
+
reportDecodeError,
|
|
1462
1436
|
BitReader,
|
|
1463
1437
|
Rtcm3Decoder,
|
|
1464
1438
|
readString,
|
|
1465
1439
|
decodeEphemeris,
|
|
1466
1440
|
decodeMsmFull,
|
|
1467
1441
|
msmEpochToDate,
|
|
1442
|
+
setGloFreqNumber,
|
|
1468
1443
|
resetGloFreqCache,
|
|
1469
1444
|
createStationMeta,
|
|
1470
1445
|
updateStationMeta,
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ecefToGeodetic
|
|
3
3
|
} from "./chunk-37QNKGTC.js";
|
|
4
|
+
import {
|
|
5
|
+
START_BDS_TIME,
|
|
6
|
+
START_GPS_TIME
|
|
7
|
+
} from "./chunk-LEEU5OIO.js";
|
|
4
8
|
|
|
5
9
|
// src/orbit/index.ts
|
|
6
10
|
var GM_GPS = 3986005e8;
|
|
@@ -8,6 +12,8 @@ var GM_GAL = 3986004418e5;
|
|
|
8
12
|
var GM_BDS = 3986004418e5;
|
|
9
13
|
var GM_GLO = 39860044e7;
|
|
10
14
|
var OMEGA_E = 72921151467e-15;
|
|
15
|
+
var BDS_GEO_MAX_INCLINATION_RAD = 0.1;
|
|
16
|
+
var BDS_GEO_MIN_SEMIMAJOR_AXIS_M = 4e7;
|
|
11
17
|
var AE_GLO = 6378136;
|
|
12
18
|
var J2_GLO = 108263e-8;
|
|
13
19
|
var TWO_PI = 2 * Math.PI;
|
|
@@ -45,7 +51,7 @@ function keplerPosition(eph, t) {
|
|
|
45
51
|
const ik = eph.i0 + dik + eph.idot * tk;
|
|
46
52
|
const xp = rk * Math.cos(uk);
|
|
47
53
|
const yp = rk * Math.sin(uk);
|
|
48
|
-
const isBdsGeo = eph.system === "C" && Math.abs(eph.i0) <
|
|
54
|
+
const isBdsGeo = eph.system === "C" && Math.abs(eph.i0) < BDS_GEO_MAX_INCLINATION_RAD && a > BDS_GEO_MIN_SEMIMAJOR_AXIS_M;
|
|
49
55
|
if (isBdsGeo) {
|
|
50
56
|
const omegak2 = eph.omega0 + eph.omegaDot * tk - OMEGA_E * eph.toe;
|
|
51
57
|
const cosO2 = Math.cos(omegak2);
|
|
@@ -226,9 +232,10 @@ function computeSatPosition(eph, timeMs) {
|
|
|
226
232
|
if (eph.system === "R" || eph.system === "S") {
|
|
227
233
|
return glonassPosition(eph, timeMs / 1e3);
|
|
228
234
|
}
|
|
229
|
-
const GPS_EPOCH =
|
|
235
|
+
const GPS_EPOCH = START_GPS_TIME.getTime();
|
|
230
236
|
const gpsSeconds = (timeMs - GPS_EPOCH) / 1e3;
|
|
231
|
-
|
|
237
|
+
let tow = gpsSeconds % (7 * 86400);
|
|
238
|
+
if (eph.system === "C") tow = (tow - 14 + 604800) % 604800;
|
|
232
239
|
return keplerPosition(eph, tow);
|
|
233
240
|
}
|
|
234
241
|
function navTimesFromEph(ephs) {
|
|
@@ -310,8 +317,8 @@ function selectBest(ephs, timeMs) {
|
|
|
310
317
|
}
|
|
311
318
|
return best;
|
|
312
319
|
}
|
|
313
|
-
var GPS_EPOCH_MS =
|
|
314
|
-
var BDS_EPOCH_MS =
|
|
320
|
+
var GPS_EPOCH_MS = START_GPS_TIME.getTime();
|
|
321
|
+
var BDS_EPOCH_MS = START_BDS_TIME.getTime();
|
|
315
322
|
var GAL_EPOCH_MS = GPS_EPOCH_MS;
|
|
316
323
|
function ephInfoToEphemeris(info) {
|
|
317
324
|
const sys = info.prn.charAt(0);
|
|
@@ -352,6 +359,9 @@ function ephInfoToEphemeris(info) {
|
|
|
352
359
|
}
|
|
353
360
|
if (info.sqrtA === void 0 || info.eccentricity === void 0 || info.inclination === void 0 || info.omega0 === void 0 || info.argPerigee === void 0 || info.meanAnomaly === void 0 || info.toe === void 0 || info.week === void 0)
|
|
354
361
|
return null;
|
|
362
|
+
if (info.eccentricity < 0 || info.eccentricity >= 1 || info.sqrtA < 3e3 || info.sqrtA > 9e3 || info.toe < 0 || info.toe > 604800) {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
355
365
|
let epochMs;
|
|
356
366
|
const tocSec = info.toc ?? info.toe;
|
|
357
367
|
if (sys === "C") {
|
|
@@ -20,7 +20,8 @@ var SYS_SHORT = {
|
|
|
20
20
|
var C_LIGHT = 299792458;
|
|
21
21
|
var FREQ = {
|
|
22
22
|
G: { "1": 157542e4, "2": 12276e5, "5": 117645e4 },
|
|
23
|
-
R
|
|
23
|
+
// R bands 4/6 are the CDMA L1OC/L2OC center frequencies
|
|
24
|
+
R: { "3": 1202025e3, "4": 1600995e3, "6": 124806e4 },
|
|
24
25
|
E: {
|
|
25
26
|
"1": 157542e4,
|
|
26
27
|
"5": 117645e4,
|
|
@@ -114,11 +115,11 @@ function buildGloChannelMap(slots) {
|
|
|
114
115
|
return map;
|
|
115
116
|
}
|
|
116
117
|
function gloFreq(gloChannels, prn, band) {
|
|
118
|
+
if (band === "3" || band === "4" || band === "6") return FREQ.R[band];
|
|
117
119
|
const k = gloChannels[prn];
|
|
118
120
|
if (k === void 0) return void 0;
|
|
119
121
|
if (band === "1") return GLO_F1_BASE + k * GLO_F1_STEP;
|
|
120
122
|
if (band === "2") return GLO_F2_BASE + k * GLO_F2_STEP;
|
|
121
|
-
if (band === "3") return GLO_F3;
|
|
122
123
|
return void 0;
|
|
123
124
|
}
|
|
124
125
|
function getFreq(gloChannels, prn, band) {
|
package/dist/constants.cjs
CHANGED
|
@@ -148,7 +148,8 @@ var SYS_SHORT = {
|
|
|
148
148
|
var C_LIGHT = 299792458;
|
|
149
149
|
var FREQ = {
|
|
150
150
|
G: { "1": 157542e4, "2": 12276e5, "5": 117645e4 },
|
|
151
|
-
R
|
|
151
|
+
// R bands 4/6 are the CDMA L1OC/L2OC center frequencies
|
|
152
|
+
R: { "3": 1202025e3, "4": 1600995e3, "6": 124806e4 },
|
|
152
153
|
E: {
|
|
153
154
|
"1": 157542e4,
|
|
154
155
|
"5": 117645e4,
|
|
@@ -242,11 +243,11 @@ function buildGloChannelMap(slots) {
|
|
|
242
243
|
return map;
|
|
243
244
|
}
|
|
244
245
|
function gloFreq(gloChannels, prn, band) {
|
|
246
|
+
if (band === "3" || band === "4" || band === "6") return FREQ.R[band];
|
|
245
247
|
const k = gloChannels[prn];
|
|
246
248
|
if (k === void 0) return void 0;
|
|
247
249
|
if (band === "1") return GLO_F1_BASE + k * GLO_F1_STEP;
|
|
248
250
|
if (band === "2") return GLO_F2_BASE + k * GLO_F2_STEP;
|
|
249
|
-
if (band === "3") return GLO_F3;
|
|
250
251
|
return void 0;
|
|
251
252
|
}
|
|
252
253
|
function getFreq(gloChannels, prn, band) {
|