gnss-js 2.10.1 → 2.11.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 +1 -1
- package/dist/binex.d.cts +1 -1
- package/dist/binex.d.ts +1 -1
- package/dist/{chunk-WQX354KD.js → chunk-H3AKFD25.js} +1 -1
- package/dist/{chunk-YUW33VXK.js → chunk-HUXQABJI.js} +2 -0
- package/dist/{chunk-GH7MYXON.js → chunk-IQHQHUOB.js} +3 -3
- package/dist/{chunk-56HM5B6T.js → chunk-MDO77CCC.js} +132 -9
- package/dist/chunk-NL2ORX75.js +319 -0
- package/dist/{chunk-74IVYOQV.js → chunk-RFPR4LKM.js} +110 -4
- package/dist/{chunk-3KSDL3CO.js → chunk-SSWFX3P3.js} +1 -1
- package/dist/{chunk-SEYH4BEN.js → chunk-SZP4TLYR.js} +2 -2
- package/dist/{chunk-K3GLUWZI.js → chunk-UMINQTMK.js} +1 -1
- package/dist/index.cjs +625 -109
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +11 -8
- package/dist/{nav-DImXUdbp.d.ts → nav-COp0Vmlw.d.cts} +83 -2
- package/dist/{nav-DImXUdbp.d.cts → nav-COp0Vmlw.d.ts} +83 -2
- package/dist/{nav-BYmYoh9A.d.cts → nav-CvZXmumD.d.cts} +1 -1
- package/dist/{nav-CN8rxL4h.d.ts → nav-D2DFlVpa.d.ts} +1 -1
- package/dist/novatel.d.cts +1 -1
- package/dist/novatel.d.ts +1 -1
- package/dist/novatel.js +3 -3
- package/dist/orbit.d.cts +2 -2
- package/dist/orbit.d.ts +2 -2
- package/dist/positioning.d.cts +2 -2
- package/dist/positioning.d.ts +2 -2
- package/dist/positioning.js +3 -3
- package/dist/rinex.cjs +140 -11
- package/dist/rinex.d.cts +9 -6
- package/dist/rinex.d.ts +9 -6
- package/dist/rinex.js +3 -2
- package/dist/sbf.cjs +420 -24
- package/dist/sbf.d.cts +46 -5
- package/dist/sbf.d.ts +46 -5
- package/dist/sbf.js +7 -4
- package/dist/trimble.d.cts +1 -1
- package/dist/trimble.d.ts +1 -1
- package/dist/ubx.d.cts +1 -1
- package/dist/ubx.d.ts +1 -1
- package/dist/ubx.js +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Everything is exposed through subpath exports (`gnss-js/rinex`, `gnss-js/positio
|
|
|
16
16
|
|
|
17
17
|
- **Formats in** — RINEX 2/3/4 obs + nav (plain, Hatanaka `.crx`, `.gz`), SP3, RINEX CLK, IONEX, SINEX bias; RTCM3 (MSM + legacy obs, ephemeris, SSR/IGS-SSR, station); RTCM 2.x; and the receiver binaries SBF, UBX, NovAtel OEM4, Trimble, BINEX.
|
|
18
18
|
- **Formats out** — RINEX 2/3/4 observation + navigation writers and Hatanaka (CRINEX) compression.
|
|
19
|
-
- **Navigation** — Keplerian/GLONASS ephemeris handling plus raw-frame decoding of GPS LNAV/CNAV, Galileo I/NAV + F/NAV, BeiDou D1/D2, GLONASS strings, and Galileo HAS (E6 C/NAV) corrections.
|
|
19
|
+
- **Navigation** — Keplerian/GLONASS ephemeris handling plus raw-frame decoding of GPS LNAV/CNAV, Galileo I/NAV + F/NAV, BeiDou D1/D2 and B-CNAV1/2/3 (B1C/B2a/B2b), GLONASS strings, and Galileo HAS (E6 C/NAV) corrections.
|
|
20
20
|
- **Orbits** — satellite position/velocity, Doppler, DOP, azimuth/elevation, pass prediction and almanac propagation.
|
|
21
21
|
- **Positioning** — SPP, static and kinematic float PPP, PPP-AR (LAMBDA + wide-/narrow-lane FCB estimation), post-processed RTK, DGNSS, and SBAS/DFMC augmentation.
|
|
22
22
|
- **Quality** — multipath, cycle slips, completeness and slant-TEC ionosphere analysis, with SINEX-DCB calibration.
|
package/dist/binex.d.cts
CHANGED
package/dist/binex.d.ts
CHANGED
|
@@ -5,15 +5,15 @@ import {
|
|
|
5
5
|
bdsSubframeParityOk,
|
|
6
6
|
galInavPageCrcOk,
|
|
7
7
|
testGloString
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SSWFX3P3.js";
|
|
9
9
|
import {
|
|
10
10
|
decodeSbasGeoNav,
|
|
11
11
|
sbasCrcOk
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-H3AKFD25.js";
|
|
13
13
|
import {
|
|
14
14
|
CnavAssembler,
|
|
15
15
|
cnavCrcOk
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-HUXQABJI.js";
|
|
17
17
|
import {
|
|
18
18
|
GpsLnavAssembler,
|
|
19
19
|
getBitS,
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
bdsCnavAref
|
|
3
|
+
} from "./chunk-NL2ORX75.js";
|
|
1
4
|
import {
|
|
2
5
|
CNAV_A_REF,
|
|
3
6
|
CNAV_OMEGA_DOT_REF
|
|
4
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HUXQABJI.js";
|
|
5
8
|
import {
|
|
6
9
|
GPS_PI
|
|
7
10
|
} from "./chunk-V2D5KUKH.js";
|
|
@@ -661,10 +664,11 @@ var R4_MSG_LINES = {
|
|
|
661
664
|
// RINEX 4 adds orbit-4 (status flags) vs 3 in RINEX 3
|
|
662
665
|
// EPH type parsed into RinexCnavEphemeris for G/J (skipped otherwise)
|
|
663
666
|
CNAV: 9,
|
|
664
|
-
//
|
|
667
|
+
// BeiDou-3 B-CNAV, parsed into BdsCnavEphemeris
|
|
665
668
|
CNV1: 10,
|
|
666
669
|
CNV2: 10,
|
|
667
670
|
CNV3: 9,
|
|
671
|
+
// EPH types we skip (different field layout)
|
|
668
672
|
L1NV: 8,
|
|
669
673
|
L1OC: 9,
|
|
670
674
|
L3OC: 9
|
|
@@ -873,6 +877,68 @@ function buildCnavEphemeris(sys, prn, date, epochVals, d) {
|
|
|
873
877
|
tow: num(7, 0)
|
|
874
878
|
};
|
|
875
879
|
}
|
|
880
|
+
var BDT_EPOCH_MS = Date.UTC(2006, 0, 1);
|
|
881
|
+
function buildBdsCnavEphemeris(message, prn, date, epochVals, d) {
|
|
882
|
+
const num = (r, c) => d[r]?.[c] ?? 0;
|
|
883
|
+
const opt = (r, c) => d[r]?.[c] ?? null;
|
|
884
|
+
const cnv3 = message === "CNV3";
|
|
885
|
+
const t = (date.getTime() - BDT_EPOCH_MS) / 1e3;
|
|
886
|
+
const weekToc = Math.floor(t / SEC_PER_WEEK);
|
|
887
|
+
const toc = t - weekToc * SEC_PER_WEEK;
|
|
888
|
+
const toe = num(2, 0);
|
|
889
|
+
const week = toe - toc > SEC_PER_WEEK / 2 ? weekToc - 1 : toc - toe > SEC_PER_WEEK / 2 ? weekToc + 1 : weekToc;
|
|
890
|
+
const sqrtA = num(1, 3);
|
|
891
|
+
const a = sqrtA * sqrtA;
|
|
892
|
+
const satType = num(4, 2);
|
|
893
|
+
return {
|
|
894
|
+
system: "C",
|
|
895
|
+
prn,
|
|
896
|
+
message,
|
|
897
|
+
week,
|
|
898
|
+
toe,
|
|
899
|
+
toeDate: new Date(BDT_EPOCH_MS + (week * SEC_PER_WEEK + toe) * 1e3),
|
|
900
|
+
toc,
|
|
901
|
+
tocDate: date,
|
|
902
|
+
satType,
|
|
903
|
+
a,
|
|
904
|
+
deltaA: a - bdsCnavAref(satType),
|
|
905
|
+
aDot: num(0, 0),
|
|
906
|
+
deltaN0: num(0, 2),
|
|
907
|
+
deltaN0Dot: num(4, 1),
|
|
908
|
+
m0: num(0, 3),
|
|
909
|
+
e: num(1, 1),
|
|
910
|
+
omega: num(3, 2),
|
|
911
|
+
omega0: num(2, 2),
|
|
912
|
+
i0: num(3, 0),
|
|
913
|
+
omegaDot: num(3, 3),
|
|
914
|
+
i0Dot: num(4, 0),
|
|
915
|
+
cis: num(2, 3),
|
|
916
|
+
cic: num(2, 1),
|
|
917
|
+
crs: num(0, 1),
|
|
918
|
+
crc: num(3, 1),
|
|
919
|
+
cus: num(1, 2),
|
|
920
|
+
cuc: num(1, 0),
|
|
921
|
+
af0: epochVals[0] ?? 0,
|
|
922
|
+
af1: epochVals[1] ?? 0,
|
|
923
|
+
af2: epochVals[2] ?? 0,
|
|
924
|
+
iode: cnv3 ? null : opt(8, 3),
|
|
925
|
+
iodc: cnv3 ? null : opt(7, 3),
|
|
926
|
+
tgdB1Cp: cnv3 ? null : opt(6, 2),
|
|
927
|
+
tgdB2ap: cnv3 ? null : opt(6, 3),
|
|
928
|
+
iscB1Cd: cnv3 ? null : opt(6, 0),
|
|
929
|
+
iscB2ad: cnv3 ? null : opt(6, 1),
|
|
930
|
+
tgdB2bI: cnv3 ? opt(6, 3) : null,
|
|
931
|
+
top: opt(4, 3),
|
|
932
|
+
sisaiOe: opt(5, 0),
|
|
933
|
+
sisaiOcb: opt(5, 1),
|
|
934
|
+
sisaiOc1: opt(5, 2),
|
|
935
|
+
sisaiOc2: opt(5, 3),
|
|
936
|
+
sismai: cnv3 ? opt(6, 0) : opt(7, 0),
|
|
937
|
+
health: cnv3 ? opt(6, 1) : opt(7, 1),
|
|
938
|
+
integrityFlags: cnv3 ? opt(6, 2) : opt(7, 2),
|
|
939
|
+
tow: cnv3 ? num(7, 0) : num(8, 0)
|
|
940
|
+
};
|
|
941
|
+
}
|
|
876
942
|
function parseNavFile(text) {
|
|
877
943
|
const lines = text.split("\n");
|
|
878
944
|
const header = {
|
|
@@ -883,6 +949,7 @@ function parseNavFile(text) {
|
|
|
883
949
|
};
|
|
884
950
|
const ephemerides = [];
|
|
885
951
|
const cnav = [];
|
|
952
|
+
const bdsCnav = [];
|
|
886
953
|
let inHeader = true;
|
|
887
954
|
let i = 0;
|
|
888
955
|
while (i < lines.length) {
|
|
@@ -951,7 +1018,8 @@ function parseNavFile(text) {
|
|
|
951
1018
|
continue;
|
|
952
1019
|
}
|
|
953
1020
|
const isCnav = msgType === "CNAV" && (svSys === "G" || svSys === "J");
|
|
954
|
-
|
|
1021
|
+
const isBdsCnav = svSys === "C" && (msgType === "CNV1" || msgType === "CNV2" || msgType === "CNV3");
|
|
1022
|
+
if (!SUPPORTED_EPH_MSGS.has(msgType) && !isCnav && !isBdsCnav) {
|
|
955
1023
|
const totalLines = R4_MSG_LINES[msgType] ?? 2;
|
|
956
1024
|
i += totalLines + 1;
|
|
957
1025
|
continue;
|
|
@@ -963,17 +1031,34 @@ function parseNavFile(text) {
|
|
|
963
1031
|
const sys2 = epochLine.charAt(0);
|
|
964
1032
|
const parsed = parseNavEpochV3(epochLine);
|
|
965
1033
|
const prn2 = `${sys2}${parsed.prn.substring(1)}`;
|
|
966
|
-
if (isCnav) {
|
|
1034
|
+
if (isCnav || isBdsCnav) {
|
|
967
1035
|
const slotLines = [];
|
|
968
1036
|
for (let j = 0; j < numDataLines2; j++) {
|
|
969
1037
|
i++;
|
|
970
1038
|
if (i >= lines.length) break;
|
|
971
1039
|
slotLines.push(parseDataLineSlots(lines[i]));
|
|
972
1040
|
}
|
|
973
|
-
if (slotLines.length === numDataLines2
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1041
|
+
if (slotLines.length === numDataLines2) {
|
|
1042
|
+
if (isBdsCnav && sys2 === "C")
|
|
1043
|
+
bdsCnav.push(
|
|
1044
|
+
buildBdsCnavEphemeris(
|
|
1045
|
+
msgType,
|
|
1046
|
+
prn2,
|
|
1047
|
+
parsed.date,
|
|
1048
|
+
parsed.values,
|
|
1049
|
+
slotLines
|
|
1050
|
+
)
|
|
1051
|
+
);
|
|
1052
|
+
else if (sys2 === "G" || sys2 === "J")
|
|
1053
|
+
cnav.push(
|
|
1054
|
+
buildCnavEphemeris(
|
|
1055
|
+
sys2,
|
|
1056
|
+
prn2,
|
|
1057
|
+
parsed.date,
|
|
1058
|
+
parsed.values,
|
|
1059
|
+
slotLines
|
|
1060
|
+
)
|
|
1061
|
+
);
|
|
977
1062
|
}
|
|
978
1063
|
i++;
|
|
979
1064
|
continue;
|
|
@@ -1051,7 +1136,12 @@ function parseNavFile(text) {
|
|
|
1051
1136
|
}
|
|
1052
1137
|
i++;
|
|
1053
1138
|
}
|
|
1054
|
-
return
|
|
1139
|
+
return {
|
|
1140
|
+
header,
|
|
1141
|
+
ephemerides,
|
|
1142
|
+
...cnav.length > 0 && { cnav },
|
|
1143
|
+
...bdsCnav.length > 0 && { bdsCnav }
|
|
1144
|
+
};
|
|
1055
1145
|
}
|
|
1056
1146
|
|
|
1057
1147
|
// src/rinex/nav-writer.ts
|
|
@@ -1247,6 +1337,30 @@ function cnavRecord(eph) {
|
|
|
1247
1337
|
orbitLine4([eph.tow, resolveWnOp(eph.week, eph.wnOp)])
|
|
1248
1338
|
].join("\n");
|
|
1249
1339
|
}
|
|
1340
|
+
function bdsCnavRecord(eph) {
|
|
1341
|
+
const lines = [
|
|
1342
|
+
epochLine4(eph.prn, eph.tocDate, [eph.af0, eph.af1, eph.af2]),
|
|
1343
|
+
orbitLine4([eph.aDot, eph.crs, eph.deltaN0, eph.m0]),
|
|
1344
|
+
orbitLine4([eph.cuc, eph.e, eph.cus, Math.sqrt(eph.a)]),
|
|
1345
|
+
orbitLine4([eph.toe, eph.cic, eph.omega0, eph.cis]),
|
|
1346
|
+
orbitLine4([eph.i0, eph.crc, eph.omega, eph.omegaDot]),
|
|
1347
|
+
orbitLine4([eph.i0Dot, eph.deltaN0Dot, eph.satType, eph.top]),
|
|
1348
|
+
orbitLine4([eph.sisaiOe, eph.sisaiOcb, eph.sisaiOc1, eph.sisaiOc2])
|
|
1349
|
+
];
|
|
1350
|
+
if (eph.message === "CNV3") {
|
|
1351
|
+
lines.push(
|
|
1352
|
+
orbitLine4([eph.sismai, eph.health, eph.integrityFlags, eph.tgdB2bI]),
|
|
1353
|
+
orbitLine4([eph.tow])
|
|
1354
|
+
);
|
|
1355
|
+
} else {
|
|
1356
|
+
lines.push(
|
|
1357
|
+
orbitLine4([eph.iscB1Cd, eph.iscB2ad, eph.tgdB1Cp, eph.tgdB2ap]),
|
|
1358
|
+
orbitLine4([eph.sismai, eph.health, eph.integrityFlags, eph.iodc]),
|
|
1359
|
+
orbitLine4([eph.tow, null, null, eph.iode])
|
|
1360
|
+
);
|
|
1361
|
+
}
|
|
1362
|
+
return lines.join("\n");
|
|
1363
|
+
}
|
|
1250
1364
|
var KLOBUCHAR_SOURCES = [
|
|
1251
1365
|
["GPSA", "GPSB", "G", "LNAV"],
|
|
1252
1366
|
["QZSA", "QZSB", "J", "LNAV"],
|
|
@@ -1324,6 +1438,15 @@ function writeRinexNav4(nav) {
|
|
|
1324
1438
|
` + cnavRecord(eph)
|
|
1325
1439
|
});
|
|
1326
1440
|
}
|
|
1441
|
+
for (const eph of nav.bdsCnav ?? []) {
|
|
1442
|
+
records.push({
|
|
1443
|
+
prn: eph.prn,
|
|
1444
|
+
time: eph.tocDate.getTime(),
|
|
1445
|
+
label: eph.message,
|
|
1446
|
+
body: `> EPH ${padL(eph.prn, 3)} ${eph.message}
|
|
1447
|
+
` + bdsCnavRecord(eph)
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1327
1450
|
records.sort(
|
|
1328
1451
|
(a, b) => a.prn.localeCompare(b.prn) || a.time - b.time || a.label.localeCompare(b.label)
|
|
1329
1452
|
);
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import {
|
|
2
|
+
crc24q,
|
|
3
|
+
getBitS33,
|
|
4
|
+
getBitU33
|
|
5
|
+
} from "./chunk-HUXQABJI.js";
|
|
6
|
+
import {
|
|
7
|
+
GPS_PI,
|
|
8
|
+
getBitS,
|
|
9
|
+
getBitU
|
|
10
|
+
} from "./chunk-V2D5KUKH.js";
|
|
11
|
+
|
|
12
|
+
// src/navbits/bds-cnav.ts
|
|
13
|
+
var BDT_EPOCH_MS = Date.UTC(2006, 0, 1);
|
|
14
|
+
var SEC_PER_WEEK = 7 * 86400;
|
|
15
|
+
var HALF_WEEK = 302400;
|
|
16
|
+
var BDS_CNAV_A_REF_MEO = 27906100;
|
|
17
|
+
var BDS_CNAV_A_REF_IGSO_GEO = 42162200;
|
|
18
|
+
function bdsCnavAref(satType) {
|
|
19
|
+
return satType === 3 ? BDS_CNAV_A_REF_MEO : BDS_CNAV_A_REF_IGSO_GEO;
|
|
20
|
+
}
|
|
21
|
+
function ephI(b, p) {
|
|
22
|
+
return {
|
|
23
|
+
toe: getBitU(b, p, 11) * 300,
|
|
24
|
+
satType: getBitU(b, p + 11, 2),
|
|
25
|
+
deltaA: getBitS(b, p + 13, 26) * 2 ** -9,
|
|
26
|
+
aDot: getBitS(b, p + 39, 25) * 2 ** -21,
|
|
27
|
+
deltaN0: getBitS(b, p + 64, 17) * 2 ** -44 * GPS_PI,
|
|
28
|
+
deltaN0Dot: getBitS(b, p + 81, 23) * 2 ** -57 * GPS_PI,
|
|
29
|
+
m0: getBitS33(b, p + 104) * 2 ** -32 * GPS_PI,
|
|
30
|
+
e: getBitU33(b, p + 137) * 2 ** -34,
|
|
31
|
+
omega: getBitS33(b, p + 170) * 2 ** -32 * GPS_PI
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function ephII(b, p) {
|
|
35
|
+
return {
|
|
36
|
+
omega0: getBitS33(b, p) * 2 ** -32 * GPS_PI,
|
|
37
|
+
i0: getBitS33(b, p + 33) * 2 ** -32 * GPS_PI,
|
|
38
|
+
omegaDot: getBitS(b, p + 66, 19) * 2 ** -44 * GPS_PI,
|
|
39
|
+
i0Dot: getBitS(b, p + 85, 15) * 2 ** -44 * GPS_PI,
|
|
40
|
+
cis: getBitS(b, p + 100, 16) * 2 ** -30,
|
|
41
|
+
cic: getBitS(b, p + 116, 16) * 2 ** -30,
|
|
42
|
+
crs: getBitS(b, p + 132, 24) * 2 ** -8,
|
|
43
|
+
crc: getBitS(b, p + 156, 24) * 2 ** -8,
|
|
44
|
+
cus: getBitS(b, p + 180, 21) * 2 ** -30,
|
|
45
|
+
cuc: getBitS(b, p + 201, 21) * 2 ** -30
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function clock(b, p) {
|
|
49
|
+
return {
|
|
50
|
+
toc: getBitU(b, p, 11) * 300,
|
|
51
|
+
af0: getBitS(b, p + 11, 25) * 2 ** -34,
|
|
52
|
+
af1: getBitS(b, p + 36, 22) * 2 ** -50,
|
|
53
|
+
af2: getBitS(b, p + 58, 11) * 2 ** -66
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function sisaiOc(b, p) {
|
|
57
|
+
return {
|
|
58
|
+
top: getBitU(b, p, 11) * 300,
|
|
59
|
+
ocb: getBitS(b, p + 11, 5),
|
|
60
|
+
oc1: getBitS(b, p + 16, 3),
|
|
61
|
+
oc2: getBitS(b, p + 19, 3)
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
var delay = (b, p) => getBitS(b, p, 12) * 2 ** -34;
|
|
65
|
+
function crcOk(msg, dataBits) {
|
|
66
|
+
const need = Math.ceil((dataBits + 24) / 8);
|
|
67
|
+
return msg.length >= need && crc24q(msg, dataBits) === getBitU(msg, dataBits, 24);
|
|
68
|
+
}
|
|
69
|
+
var bdsCnav1Sf2CrcOk = (sf2) => crcOk(sf2, 576);
|
|
70
|
+
var bdsCnav1Sf3CrcOk = (sf3) => crcOk(sf3, 240);
|
|
71
|
+
var bdsCnav2CrcOk = (msg) => crcOk(msg, 264);
|
|
72
|
+
var bdsCnav3CrcOk = (msg) => crcOk(msg, 462);
|
|
73
|
+
function resolveWeek(week, towSec, sec) {
|
|
74
|
+
if (sec < towSec - HALF_WEEK) return week + 1;
|
|
75
|
+
if (sec > towSec + HALF_WEEK) return week - 1;
|
|
76
|
+
return week;
|
|
77
|
+
}
|
|
78
|
+
function bdtDate(week, sec) {
|
|
79
|
+
return new Date(BDT_EPOCH_MS + (week * SEC_PER_WEEK + sec) * 1e3);
|
|
80
|
+
}
|
|
81
|
+
var emptyStatus = () => ({
|
|
82
|
+
top: null,
|
|
83
|
+
sisaiOe: null,
|
|
84
|
+
sisaiOcb: null,
|
|
85
|
+
sisaiOc1: null,
|
|
86
|
+
sisaiOc2: null,
|
|
87
|
+
sismai: null,
|
|
88
|
+
health: null,
|
|
89
|
+
integrityFlags: null
|
|
90
|
+
});
|
|
91
|
+
function applyOc(s, oc) {
|
|
92
|
+
s.top = oc.top;
|
|
93
|
+
s.sisaiOcb = oc.ocb;
|
|
94
|
+
s.sisaiOc1 = oc.oc1;
|
|
95
|
+
s.sisaiOc2 = oc.oc2;
|
|
96
|
+
}
|
|
97
|
+
function build(message, prn, wn, tTm, e1, e2, c, d, s) {
|
|
98
|
+
const week = resolveWeek(wn, tTm, e1.toe);
|
|
99
|
+
const weekToc = resolveWeek(wn, tTm, c.toc);
|
|
100
|
+
return {
|
|
101
|
+
system: "C",
|
|
102
|
+
prn,
|
|
103
|
+
message,
|
|
104
|
+
week,
|
|
105
|
+
toe: e1.toe,
|
|
106
|
+
toeDate: bdtDate(week, e1.toe),
|
|
107
|
+
toc: c.toc,
|
|
108
|
+
tocDate: bdtDate(weekToc, c.toc),
|
|
109
|
+
satType: e1.satType,
|
|
110
|
+
a: bdsCnavAref(e1.satType) + e1.deltaA,
|
|
111
|
+
deltaA: e1.deltaA,
|
|
112
|
+
aDot: e1.aDot,
|
|
113
|
+
deltaN0: e1.deltaN0,
|
|
114
|
+
deltaN0Dot: e1.deltaN0Dot,
|
|
115
|
+
m0: e1.m0,
|
|
116
|
+
e: e1.e,
|
|
117
|
+
omega: e1.omega,
|
|
118
|
+
...e2,
|
|
119
|
+
af0: c.af0,
|
|
120
|
+
af1: c.af1,
|
|
121
|
+
af2: c.af2,
|
|
122
|
+
...d,
|
|
123
|
+
...s,
|
|
124
|
+
tow: tTm
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
var prnLabel = (prn) => `C${String(prn).padStart(2, "0")}`;
|
|
128
|
+
var BdsCnav1Assembler = class {
|
|
129
|
+
status = /* @__PURE__ */ new Map();
|
|
130
|
+
lastKey = /* @__PURE__ */ new Map();
|
|
131
|
+
/**
|
|
132
|
+
* Push one frame's CRC-valid subframes (bit-0 aligned; pass null for
|
|
133
|
+
* a subframe that failed its CRC) for satellite `prn` (1-63). `tTm`
|
|
134
|
+
* is the frame's transmit time, s of the BDT week. Returns the newly
|
|
135
|
+
* seen ephemeris, or null.
|
|
136
|
+
*/
|
|
137
|
+
push(prn, sf2, sf3, tTm) {
|
|
138
|
+
let s = this.status.get(prn);
|
|
139
|
+
if (!s) this.status.set(prn, s = emptyStatus());
|
|
140
|
+
if (sf3) {
|
|
141
|
+
const page = getBitU(sf3, 0, 6);
|
|
142
|
+
if (page >= 1 && page <= 4) {
|
|
143
|
+
s.health = getBitU(sf3, 6, 2);
|
|
144
|
+
s.integrityFlags = getBitU(sf3, 8, 3);
|
|
145
|
+
s.sismai = getBitU(sf3, 11, 4);
|
|
146
|
+
if (page === 1) {
|
|
147
|
+
s.sisaiOe = getBitU(sf3, 15, 5);
|
|
148
|
+
applyOc(s, sisaiOc(sf3, 20));
|
|
149
|
+
} else if (page === 3) s.sisaiOe = getBitU(sf3, 15, 5);
|
|
150
|
+
else applyOc(s, sisaiOc(sf3, 15));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (!sf2) return null;
|
|
154
|
+
const wn = getBitU(sf2, 0, 13);
|
|
155
|
+
const iodc = getBitU(sf2, 21, 10);
|
|
156
|
+
const iode = getBitU(sf2, 31, 8);
|
|
157
|
+
const e1 = ephI(sf2, 39);
|
|
158
|
+
const c = clock(sf2, 464);
|
|
159
|
+
const key = `${wn}:${iodc}:${iode}:${e1.toe}:${c.toc}`;
|
|
160
|
+
if (this.lastKey.get(prn) === key) return null;
|
|
161
|
+
this.lastKey.set(prn, key);
|
|
162
|
+
return build(
|
|
163
|
+
"CNV1",
|
|
164
|
+
prnLabel(prn),
|
|
165
|
+
wn,
|
|
166
|
+
tTm,
|
|
167
|
+
e1,
|
|
168
|
+
ephII(sf2, 242),
|
|
169
|
+
c,
|
|
170
|
+
{
|
|
171
|
+
iode,
|
|
172
|
+
iodc,
|
|
173
|
+
tgdB1Cp: delay(sf2, 557),
|
|
174
|
+
tgdB2ap: delay(sf2, 533),
|
|
175
|
+
iscB1Cd: delay(sf2, 545),
|
|
176
|
+
iscB2ad: null,
|
|
177
|
+
tgdB2bI: null
|
|
178
|
+
},
|
|
179
|
+
{ ...s }
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
var BdsCnav2Assembler = class {
|
|
184
|
+
sats = /* @__PURE__ */ new Map();
|
|
185
|
+
/**
|
|
186
|
+
* Push one CRC-valid 288-bit message (bit 0 = first PRN bit, the
|
|
187
|
+
* preamble stripped). Returns the newly completed ephemeris, or null.
|
|
188
|
+
*/
|
|
189
|
+
push(msg) {
|
|
190
|
+
const prn = getBitU(msg, 0, 6);
|
|
191
|
+
const type = getBitU(msg, 6, 6);
|
|
192
|
+
const sow = getBitU(msg, 12, 18) * 3;
|
|
193
|
+
if (prn < 1) return null;
|
|
194
|
+
let sat = this.sats.get(prn);
|
|
195
|
+
if (!sat) this.sats.set(prn, sat = { status: emptyStatus() });
|
|
196
|
+
const s = sat.status;
|
|
197
|
+
if (type === 10) {
|
|
198
|
+
sat.t10 = {
|
|
199
|
+
wn: getBitU(msg, 30, 13),
|
|
200
|
+
iode: getBitU(msg, 53, 8),
|
|
201
|
+
e1: ephI(msg, 61),
|
|
202
|
+
sow
|
|
203
|
+
};
|
|
204
|
+
s.integrityFlags = getBitU(msg, 43, 3) << 3 | getBitU(msg, 50, 3);
|
|
205
|
+
s.sismai = getBitU(msg, 46, 4);
|
|
206
|
+
if (sat.t11 && sat.t11.sow < sow) sat.t11 = void 0;
|
|
207
|
+
} else if (type === 11 || type >= 30 && type <= 34 || type === 40) {
|
|
208
|
+
s.health = getBitU(msg, 30, 2);
|
|
209
|
+
s.integrityFlags = getBitU(msg, 32, 3) << 3 | getBitU(msg, 39, 3);
|
|
210
|
+
s.sismai = getBitU(msg, 35, 4);
|
|
211
|
+
if (type === 11) {
|
|
212
|
+
if (!sat.t10 || sow <= sat.t10.sow) return null;
|
|
213
|
+
sat.t11 = { e2: ephII(msg, 42), sow };
|
|
214
|
+
} else if (type === 34) {
|
|
215
|
+
applyOc(s, sisaiOc(msg, 42));
|
|
216
|
+
sat.clock = { c: clock(msg, 64), iodc: getBitU(msg, 133, 10) };
|
|
217
|
+
} else if (type === 40) {
|
|
218
|
+
s.sisaiOe = getBitU(msg, 42, 5);
|
|
219
|
+
applyOc(s, sisaiOc(msg, 47));
|
|
220
|
+
return null;
|
|
221
|
+
} else {
|
|
222
|
+
sat.clock = { c: clock(msg, 42), iodc: getBitU(msg, 111, 10) };
|
|
223
|
+
if (type === 30)
|
|
224
|
+
sat.delays = {
|
|
225
|
+
tgdB2ap: delay(msg, 121),
|
|
226
|
+
iscB2ad: delay(msg, 133),
|
|
227
|
+
tgdB1Cp: delay(msg, 219)
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
} else return null;
|
|
231
|
+
const { t10, t11, clock: ck } = sat;
|
|
232
|
+
if (!t10 || !t11 || !ck || (ck.iodc & 255) !== t10.iode) return null;
|
|
233
|
+
const key = `${t10.wn}:${ck.iodc}:${t10.iode}:${t10.e1.toe}:${ck.c.toc}`;
|
|
234
|
+
if (sat.lastKey === key) return null;
|
|
235
|
+
sat.lastKey = key;
|
|
236
|
+
return build(
|
|
237
|
+
"CNV2",
|
|
238
|
+
prnLabel(prn),
|
|
239
|
+
t10.wn,
|
|
240
|
+
t10.sow,
|
|
241
|
+
t10.e1,
|
|
242
|
+
t11.e2,
|
|
243
|
+
ck.c,
|
|
244
|
+
{
|
|
245
|
+
iode: t10.iode,
|
|
246
|
+
iodc: ck.iodc,
|
|
247
|
+
tgdB1Cp: sat.delays?.tgdB1Cp ?? null,
|
|
248
|
+
tgdB2ap: sat.delays?.tgdB2ap ?? null,
|
|
249
|
+
iscB1Cd: null,
|
|
250
|
+
iscB2ad: sat.delays?.iscB2ad ?? null,
|
|
251
|
+
tgdB2bI: null
|
|
252
|
+
},
|
|
253
|
+
{ ...s }
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
var BdsCnav3Assembler = class {
|
|
258
|
+
sats = /* @__PURE__ */ new Map();
|
|
259
|
+
/**
|
|
260
|
+
* Push one CRC-valid 486-bit message (bit 0 = first MesType bit) from
|
|
261
|
+
* satellite `prn`. Returns the newly completed ephemeris, or null.
|
|
262
|
+
*/
|
|
263
|
+
push(prn, msg) {
|
|
264
|
+
const type = getBitU(msg, 0, 6);
|
|
265
|
+
const sow = getBitU(msg, 6, 20);
|
|
266
|
+
let sat = this.sats.get(prn);
|
|
267
|
+
if (!sat) this.sats.set(prn, sat = { status: emptyStatus() });
|
|
268
|
+
const s = sat.status;
|
|
269
|
+
if (type === 10) {
|
|
270
|
+
sat.t10 = { e1: ephI(msg, 30), e2: ephII(msg, 233), sow };
|
|
271
|
+
s.integrityFlags = getBitU(msg, 455, 3);
|
|
272
|
+
s.sismai = getBitU(msg, 458, 4);
|
|
273
|
+
} else if (type === 30) {
|
|
274
|
+
sat.t30 = {
|
|
275
|
+
wn: getBitU(msg, 26, 13),
|
|
276
|
+
c: clock(msg, 43),
|
|
277
|
+
tgd: delay(msg, 112)
|
|
278
|
+
};
|
|
279
|
+
applyOc(s, sisaiOc(msg, 433));
|
|
280
|
+
s.sisaiOe = getBitU(msg, 455, 5);
|
|
281
|
+
s.health = getBitU(msg, 460, 2);
|
|
282
|
+
} else return null;
|
|
283
|
+
const { t10, t30 } = sat;
|
|
284
|
+
if (!t10 || !t30 || t10.e1.toe !== t30.c.toc) return null;
|
|
285
|
+
const key = `${t30.wn}:${t10.e1.toe}:${t30.c.af0}:${t10.e1.m0}`;
|
|
286
|
+
if (sat.lastKey === key) return null;
|
|
287
|
+
sat.lastKey = key;
|
|
288
|
+
return build(
|
|
289
|
+
"CNV3",
|
|
290
|
+
prnLabel(prn),
|
|
291
|
+
t30.wn,
|
|
292
|
+
t10.sow,
|
|
293
|
+
t10.e1,
|
|
294
|
+
t10.e2,
|
|
295
|
+
t30.c,
|
|
296
|
+
{
|
|
297
|
+
iode: null,
|
|
298
|
+
iodc: null,
|
|
299
|
+
tgdB1Cp: null,
|
|
300
|
+
tgdB2ap: null,
|
|
301
|
+
iscB1Cd: null,
|
|
302
|
+
iscB2ad: null,
|
|
303
|
+
tgdB2bI: t30.tgd
|
|
304
|
+
},
|
|
305
|
+
{ ...s }
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
export {
|
|
311
|
+
bdsCnavAref,
|
|
312
|
+
bdsCnav1Sf2CrcOk,
|
|
313
|
+
bdsCnav1Sf3CrcOk,
|
|
314
|
+
bdsCnav2CrcOk,
|
|
315
|
+
bdsCnav3CrcOk,
|
|
316
|
+
BdsCnav1Assembler,
|
|
317
|
+
BdsCnav2Assembler,
|
|
318
|
+
BdsCnav3Assembler
|
|
319
|
+
};
|