gnss-js 1.18.0 → 1.20.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-2IM5VXNI.js → chunk-7RKLWE6R.js} +23 -2
- package/dist/{chunk-QXZZNXE3.js → chunk-B5LU4746.js} +1 -1
- package/dist/{chunk-FEGLXNWA.js → chunk-DLXTTHRK.js} +2 -4
- package/dist/{chunk-OMVL3X7V.js → chunk-JNFV5BYB.js} +186 -8
- package/dist/{chunk-HXF7XVW7.js → chunk-NOQAAUGY.js} +297 -11
- package/dist/{chunk-CG7SF45F.js → chunk-VJEPOC76.js} +908 -14
- package/dist/{chunk-Y5IWUPJQ.js → chunk-WZDFZ76K.js} +151 -8
- package/dist/index.cjs +3283 -1908
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +25 -8
- package/dist/nav-BYmYoh9A.d.cts +137 -0
- package/dist/nav-CN8rxL4h.d.ts +137 -0
- package/dist/nav-DImXUdbp.d.cts +223 -0
- package/dist/nav-DImXUdbp.d.ts +223 -0
- package/dist/novatel.cjs +230 -15
- package/dist/novatel.d.cts +8 -1
- package/dist/novatel.d.ts +8 -1
- package/dist/novatel.js +2 -2
- package/dist/orbit.cjs +190 -8
- package/dist/orbit.d.cts +91 -2
- package/dist/orbit.d.ts +91 -2
- package/dist/orbit.js +9 -1
- package/dist/positioning.d.cts +2 -1
- package/dist/positioning.d.ts +2 -1
- package/dist/positioning.js +2 -2
- package/dist/rinex.cjs +304 -11
- package/dist/rinex.d.cts +45 -3
- package/dist/rinex.d.ts +45 -3
- package/dist/rinex.js +6 -1
- package/dist/sbf.cjs +908 -11
- package/dist/sbf.d.cts +114 -137
- package/dist/sbf.d.ts +114 -137
- package/dist/sbf.js +8 -3
- package/dist/ubx.d.cts +1 -2
- package/dist/ubx.d.ts +1 -2
- package/dist/ubx.js +2 -3
- package/package.json +1 -1
- package/dist/chunk-IQ5OIMQD.js +0 -148
- package/dist/cnav-CRns0ECn.d.cts +0 -96
- package/dist/cnav-CRns0ECn.d.ts +0 -96
- package/dist/nav-BAI1a9vK.d.cts +0 -108
- package/dist/nav-BAI1a9vK.d.ts +0 -108
package/dist/rinex.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(rinex_exports, {
|
|
|
26
26
|
createGzipLineSink: () => createGzipLineSink,
|
|
27
27
|
crxDecompress: () => crxDecompress,
|
|
28
28
|
crxRepair: () => crxRepair,
|
|
29
|
+
fmtD: () => fmtD,
|
|
29
30
|
fmtF: () => fmtF,
|
|
30
31
|
hdrLine: () => hdrLine,
|
|
31
32
|
padL: () => padL,
|
|
@@ -43,6 +44,7 @@ __export(rinex_exports, {
|
|
|
43
44
|
writeRinex2ObsBlob: () => writeRinex2ObsBlob,
|
|
44
45
|
writeRinex4ObsBlob: () => writeRinex4ObsBlob,
|
|
45
46
|
writeRinexNav: () => writeRinexNav,
|
|
47
|
+
writeRinexNav4: () => writeRinexNav4,
|
|
46
48
|
writeRinexObsBlob: () => writeRinexObsBlob
|
|
47
49
|
});
|
|
48
50
|
module.exports = __toCommonJS(rinex_exports);
|
|
@@ -1038,6 +1040,17 @@ var WarningAccumulator = class {
|
|
|
1038
1040
|
}
|
|
1039
1041
|
};
|
|
1040
1042
|
|
|
1043
|
+
// src/navbits/index.ts
|
|
1044
|
+
var GPS_PI = 3.1415926535898;
|
|
1045
|
+
var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
|
|
1046
|
+
var SEC_PER_WEEK = 7 * 86400;
|
|
1047
|
+
|
|
1048
|
+
// src/navbits/cnav.ts
|
|
1049
|
+
var GPS_EPOCH_MS2 = Date.UTC(1980, 0, 6);
|
|
1050
|
+
var SEC_PER_WEEK2 = 7 * 86400;
|
|
1051
|
+
var CNAV_A_REF = 26559710;
|
|
1052
|
+
var CNAV_OMEGA_DOT_REF = -26e-10;
|
|
1053
|
+
|
|
1041
1054
|
// src/rinex/nav.ts
|
|
1042
1055
|
var DATA_LINES = {
|
|
1043
1056
|
G: 7,
|
|
@@ -1061,19 +1074,19 @@ var R4_MSG_LINES = {
|
|
|
1061
1074
|
SBAS: 4,
|
|
1062
1075
|
FDMA: 5,
|
|
1063
1076
|
// RINEX 4 adds orbit-4 (status flags) vs 3 in RINEX 3
|
|
1064
|
-
// EPH
|
|
1077
|
+
// EPH type parsed into RinexCnavEphemeris for G/J (skipped otherwise)
|
|
1065
1078
|
CNAV: 9,
|
|
1079
|
+
// EPH types we skip (different field layout)
|
|
1066
1080
|
CNV1: 10,
|
|
1067
1081
|
CNV2: 10,
|
|
1068
1082
|
CNV3: 9,
|
|
1069
1083
|
L1NV: 8,
|
|
1070
1084
|
L1OC: 9,
|
|
1071
|
-
L3OC: 9
|
|
1072
|
-
// Non-EPH records
|
|
1073
|
-
STO: 2,
|
|
1074
|
-
EOP: 3,
|
|
1075
|
-
ION: 3
|
|
1085
|
+
L3OC: 9
|
|
1076
1086
|
};
|
|
1087
|
+
var GPS_EPOCH_MS3 = Date.UTC(1980, 0, 6);
|
|
1088
|
+
var SEC_PER_WEEK3 = 7 * 86400;
|
|
1089
|
+
var QZSS_CNAV_A_REF = 42164200;
|
|
1077
1090
|
var SUPPORTED_EPH_MSGS = /* @__PURE__ */ new Set([
|
|
1078
1091
|
"LNAV",
|
|
1079
1092
|
"INAV",
|
|
@@ -1137,6 +1150,20 @@ function parseDataLine(line, colOffset = 4) {
|
|
|
1137
1150
|
}
|
|
1138
1151
|
return values;
|
|
1139
1152
|
}
|
|
1153
|
+
function parseDataLineSlots(line) {
|
|
1154
|
+
const values = [];
|
|
1155
|
+
for (let i = 0; i < 4; i++) {
|
|
1156
|
+
const start = 4 + i * 19;
|
|
1157
|
+
const s = start < line.length ? line.substring(start, start + 19).trim() : "";
|
|
1158
|
+
if (s.length === 0) {
|
|
1159
|
+
values.push(null);
|
|
1160
|
+
continue;
|
|
1161
|
+
}
|
|
1162
|
+
const v = parseFloat19(s);
|
|
1163
|
+
values.push(Number.isFinite(v) ? v : null);
|
|
1164
|
+
}
|
|
1165
|
+
return values;
|
|
1166
|
+
}
|
|
1140
1167
|
function buildKeplerEphemeris(sys, prn, date, epochVals, data) {
|
|
1141
1168
|
const d = [];
|
|
1142
1169
|
for (const line of data) {
|
|
@@ -1199,6 +1226,68 @@ function buildStateVectorEphemeris(sys, prn, date, epochVals, data) {
|
|
|
1199
1226
|
zAcc: d[10] ?? 0
|
|
1200
1227
|
};
|
|
1201
1228
|
}
|
|
1229
|
+
function buildCnavEphemeris(sys, prn, date, epochVals, d) {
|
|
1230
|
+
const num = (r, c) => d[r]?.[c] ?? 0;
|
|
1231
|
+
const opt = (r, c) => d[r]?.[c] ?? null;
|
|
1232
|
+
const t = (date.getTime() - GPS_EPOCH_MS3) / 1e3;
|
|
1233
|
+
const week = Math.floor(t / SEC_PER_WEEK3);
|
|
1234
|
+
const toc = t - week * SEC_PER_WEEK3;
|
|
1235
|
+
const sqrtA = num(1, 3);
|
|
1236
|
+
const a = sqrtA * sqrtA;
|
|
1237
|
+
const aRef = sys === "J" ? QZSS_CNAV_A_REF : CNAV_A_REF;
|
|
1238
|
+
const omegaDot = num(3, 3);
|
|
1239
|
+
const wnOp = d[7]?.[1];
|
|
1240
|
+
return {
|
|
1241
|
+
system: sys,
|
|
1242
|
+
prn,
|
|
1243
|
+
week,
|
|
1244
|
+
health: num(5, 1),
|
|
1245
|
+
uraEd: num(5, 0),
|
|
1246
|
+
uraNed0: num(4, 2),
|
|
1247
|
+
uraNed1: num(4, 3),
|
|
1248
|
+
uraNed2: num(5, 3),
|
|
1249
|
+
top: num(2, 0),
|
|
1250
|
+
toe: toc,
|
|
1251
|
+
toeDate: date,
|
|
1252
|
+
a,
|
|
1253
|
+
deltaA: a - aRef,
|
|
1254
|
+
aDot: num(0, 0),
|
|
1255
|
+
deltaN0: num(0, 2),
|
|
1256
|
+
deltaN0Dot: num(4, 1),
|
|
1257
|
+
m0: num(0, 3),
|
|
1258
|
+
e: num(1, 1),
|
|
1259
|
+
omega: num(3, 2),
|
|
1260
|
+
omega0: num(2, 2),
|
|
1261
|
+
i0: num(3, 0),
|
|
1262
|
+
omegaDot,
|
|
1263
|
+
deltaOmegaDot: omegaDot - CNAV_OMEGA_DOT_REF * GPS_PI,
|
|
1264
|
+
i0Dot: num(4, 0),
|
|
1265
|
+
cis: num(2, 3),
|
|
1266
|
+
cic: num(2, 1),
|
|
1267
|
+
crs: num(0, 1),
|
|
1268
|
+
crc: num(3, 1),
|
|
1269
|
+
cus: num(1, 2),
|
|
1270
|
+
cuc: num(1, 0),
|
|
1271
|
+
toc,
|
|
1272
|
+
tocDate: date,
|
|
1273
|
+
af0: epochVals[0] ?? 0,
|
|
1274
|
+
af1: epochVals[1] ?? 0,
|
|
1275
|
+
af2: epochVals[2] ?? 0,
|
|
1276
|
+
clockMsgType: 0,
|
|
1277
|
+
// not recorded in RINEX
|
|
1278
|
+
tgd: opt(5, 2),
|
|
1279
|
+
iscL1ca: opt(6, 0),
|
|
1280
|
+
iscL2c: opt(6, 1),
|
|
1281
|
+
iscL5i5: opt(6, 2),
|
|
1282
|
+
iscL5q5: opt(6, 3),
|
|
1283
|
+
...wnOp != null && { wnOp },
|
|
1284
|
+
integrityFlag: false,
|
|
1285
|
+
// not recorded in RINEX
|
|
1286
|
+
l2cPhasing: false,
|
|
1287
|
+
// not recorded in RINEX
|
|
1288
|
+
tow: num(7, 0)
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1202
1291
|
function parseNavFile(text) {
|
|
1203
1292
|
const lines = text.split("\n");
|
|
1204
1293
|
const header = {
|
|
@@ -1208,6 +1297,7 @@ function parseNavFile(text) {
|
|
|
1208
1297
|
ionoCorrections: {}
|
|
1209
1298
|
};
|
|
1210
1299
|
const ephemerides = [];
|
|
1300
|
+
const cnav = [];
|
|
1211
1301
|
let inHeader = true;
|
|
1212
1302
|
let i = 0;
|
|
1213
1303
|
while (i < lines.length) {
|
|
@@ -1268,8 +1358,15 @@ function parseNavFile(text) {
|
|
|
1268
1358
|
if (isV4 && line.charAt(0) === ">") {
|
|
1269
1359
|
const parts = line.substring(2).trim().split(/\s+/);
|
|
1270
1360
|
const recType = parts[0] ?? "";
|
|
1361
|
+
const svSys = (parts[1] ?? "").charAt(0);
|
|
1271
1362
|
const msgType = parts[2] ?? recType;
|
|
1272
|
-
if (recType !== "EPH"
|
|
1363
|
+
if (recType !== "EPH") {
|
|
1364
|
+
const totalLines = recType === "STO" ? 2 : recType === "EOP" ? 3 : recType === "ION" ? svSys === "E" ? 2 : 3 : 2;
|
|
1365
|
+
i += totalLines + 1;
|
|
1366
|
+
continue;
|
|
1367
|
+
}
|
|
1368
|
+
const isCnav = msgType === "CNAV" && (svSys === "G" || svSys === "J");
|
|
1369
|
+
if (!SUPPORTED_EPH_MSGS.has(msgType) && !isCnav) {
|
|
1273
1370
|
const totalLines = R4_MSG_LINES[msgType] ?? 2;
|
|
1274
1371
|
i += totalLines + 1;
|
|
1275
1372
|
continue;
|
|
@@ -1281,6 +1378,21 @@ function parseNavFile(text) {
|
|
|
1281
1378
|
const sys2 = epochLine.charAt(0);
|
|
1282
1379
|
const parsed = parseNavEpochV3(epochLine);
|
|
1283
1380
|
const prn2 = `${sys2}${parsed.prn.substring(1)}`;
|
|
1381
|
+
if (isCnav) {
|
|
1382
|
+
const slotLines = [];
|
|
1383
|
+
for (let j = 0; j < numDataLines2; j++) {
|
|
1384
|
+
i++;
|
|
1385
|
+
if (i >= lines.length) break;
|
|
1386
|
+
slotLines.push(parseDataLineSlots(lines[i]));
|
|
1387
|
+
}
|
|
1388
|
+
if (slotLines.length === numDataLines2 && (sys2 === "G" || sys2 === "J")) {
|
|
1389
|
+
cnav.push(
|
|
1390
|
+
buildCnavEphemeris(sys2, prn2, parsed.date, parsed.values, slotLines)
|
|
1391
|
+
);
|
|
1392
|
+
}
|
|
1393
|
+
i++;
|
|
1394
|
+
continue;
|
|
1395
|
+
}
|
|
1284
1396
|
const dataLines2 = [];
|
|
1285
1397
|
for (let j = 0; j < numDataLines2; j++) {
|
|
1286
1398
|
i++;
|
|
@@ -1354,7 +1466,7 @@ function parseNavFile(text) {
|
|
|
1354
1466
|
}
|
|
1355
1467
|
i++;
|
|
1356
1468
|
}
|
|
1357
|
-
return { header, ephemerides };
|
|
1469
|
+
return cnav.length > 0 ? { header, ephemerides, cnav } : { header, ephemerides };
|
|
1358
1470
|
}
|
|
1359
1471
|
|
|
1360
1472
|
// src/rinex/nav-writer.ts
|
|
@@ -1362,9 +1474,13 @@ function fmtD(val) {
|
|
|
1362
1474
|
if (val === 0) return " 0.000000000000E+00";
|
|
1363
1475
|
const sign = val < 0 ? "-" : " ";
|
|
1364
1476
|
const abs = Math.abs(val);
|
|
1365
|
-
|
|
1477
|
+
let exp = Math.floor(Math.log10(abs));
|
|
1366
1478
|
const mantissa = abs / 10 ** exp;
|
|
1367
|
-
|
|
1479
|
+
let mStr = mantissa.toFixed(12);
|
|
1480
|
+
if (mStr.length > 14) {
|
|
1481
|
+
exp += 1;
|
|
1482
|
+
mStr = (mantissa / 10).toFixed(12);
|
|
1483
|
+
}
|
|
1368
1484
|
const expSign = exp >= 0 ? "+" : "-";
|
|
1369
1485
|
const expStr = String(Math.abs(exp)).padStart(2, "0");
|
|
1370
1486
|
return `${sign}${mStr}E${expSign}${expStr}`;
|
|
@@ -1439,7 +1555,7 @@ function writeKeplerRecord(eph) {
|
|
|
1439
1555
|
function writeGlonassRecord(eph) {
|
|
1440
1556
|
const lines = [];
|
|
1441
1557
|
lines.push(
|
|
1442
|
-
`${padL(eph.prn, 3)} ${fmtEpoch(eph.tocDate)}${fmtD(
|
|
1558
|
+
`${padL(eph.prn, 3)} ${fmtEpoch(eph.tocDate)}${fmtD(eph.tauN)}${fmtD(eph.gammaN)}${fmtD(eph.messageFrameTime)}`
|
|
1443
1559
|
);
|
|
1444
1560
|
lines.push(orbitLine([eph.x, eph.xDot, eph.xAcc, eph.health]));
|
|
1445
1561
|
lines.push(orbitLine([eph.y, eph.yDot, eph.yAcc, eph.freqNum]));
|
|
@@ -1459,6 +1575,181 @@ function writeRinexNav(nav) {
|
|
|
1459
1575
|
return header + records.join("\n") + "\n";
|
|
1460
1576
|
}
|
|
1461
1577
|
|
|
1578
|
+
// src/rinex/nav-writer-v4.ts
|
|
1579
|
+
var BLANK19 = " ".repeat(19);
|
|
1580
|
+
function fmtEpoch4(d) {
|
|
1581
|
+
const p2 = (v) => String(v).padStart(2, "0");
|
|
1582
|
+
return `${d.getUTCFullYear()} ${p2(d.getUTCMonth() + 1)} ${p2(d.getUTCDate())} ${p2(d.getUTCHours())} ${p2(d.getUTCMinutes())} ${p2(d.getUTCSeconds())}`;
|
|
1583
|
+
}
|
|
1584
|
+
function orbitLine4(values) {
|
|
1585
|
+
const line = " " + values.map((v) => v == null ? BLANK19 : fmtD(v)).join("");
|
|
1586
|
+
return line.replace(/ +$/, "");
|
|
1587
|
+
}
|
|
1588
|
+
function epochLine4(prn, date, vals) {
|
|
1589
|
+
return `${padL(prn, 3)} ${fmtEpoch4(date)}${vals.map(fmtD).join("")}`;
|
|
1590
|
+
}
|
|
1591
|
+
var BDS_GEO = /* @__PURE__ */ new Set([
|
|
1592
|
+
"C01",
|
|
1593
|
+
"C02",
|
|
1594
|
+
"C03",
|
|
1595
|
+
"C04",
|
|
1596
|
+
"C05",
|
|
1597
|
+
"C59",
|
|
1598
|
+
"C60",
|
|
1599
|
+
"C61",
|
|
1600
|
+
"C62",
|
|
1601
|
+
"C63"
|
|
1602
|
+
]);
|
|
1603
|
+
function msgLabel(eph) {
|
|
1604
|
+
switch (eph.system) {
|
|
1605
|
+
case "E":
|
|
1606
|
+
return "INAV";
|
|
1607
|
+
case "C":
|
|
1608
|
+
return BDS_GEO.has(eph.prn) ? "D2" : "D1";
|
|
1609
|
+
case "R":
|
|
1610
|
+
return "FDMA";
|
|
1611
|
+
case "S":
|
|
1612
|
+
return "SBAS";
|
|
1613
|
+
default:
|
|
1614
|
+
return "LNAV";
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
function isKepler2(eph) {
|
|
1618
|
+
return "af0" in eph;
|
|
1619
|
+
}
|
|
1620
|
+
function keplerRecord(eph) {
|
|
1621
|
+
return [
|
|
1622
|
+
epochLine4(eph.prn, eph.tocDate, [eph.af0, eph.af1, eph.af2]),
|
|
1623
|
+
orbitLine4([eph.iode, eph.crs, eph.deltaN, eph.m0]),
|
|
1624
|
+
orbitLine4([eph.cuc, eph.e, eph.cus, eph.sqrtA]),
|
|
1625
|
+
orbitLine4([eph.toe, eph.cic, eph.omega0, eph.cis]),
|
|
1626
|
+
orbitLine4([eph.i0, eph.crc, eph.omega, eph.omegaDot]),
|
|
1627
|
+
orbitLine4([eph.idot, 0, eph.week, 0]),
|
|
1628
|
+
orbitLine4([0, eph.svHealth, eph.tgd, 0]),
|
|
1629
|
+
orbitLine4([eph.toe, 0, 0, 0])
|
|
1630
|
+
].join("\n");
|
|
1631
|
+
}
|
|
1632
|
+
function stateVectorRecord(eph) {
|
|
1633
|
+
const lines = [
|
|
1634
|
+
epochLine4(eph.prn, eph.tocDate, [
|
|
1635
|
+
eph.tauN,
|
|
1636
|
+
eph.gammaN,
|
|
1637
|
+
eph.messageFrameTime
|
|
1638
|
+
]),
|
|
1639
|
+
orbitLine4([eph.x, eph.xDot, eph.xAcc, eph.health]),
|
|
1640
|
+
orbitLine4([eph.y, eph.yDot, eph.yAcc, eph.freqNum]),
|
|
1641
|
+
orbitLine4([eph.z, eph.zDot, eph.zAcc, 0])
|
|
1642
|
+
];
|
|
1643
|
+
if (eph.system === "R") {
|
|
1644
|
+
lines.push(orbitLine4([null, 999999999999e-3, 15, null]));
|
|
1645
|
+
}
|
|
1646
|
+
return lines.join("\n");
|
|
1647
|
+
}
|
|
1648
|
+
function resolveWnOp(week, wnOp) {
|
|
1649
|
+
if (wnOp == null) return week;
|
|
1650
|
+
return week - ((week - wnOp) % 256 + 256) % 256;
|
|
1651
|
+
}
|
|
1652
|
+
function cnavRecord(eph) {
|
|
1653
|
+
return [
|
|
1654
|
+
epochLine4(eph.prn, eph.tocDate, [eph.af0, eph.af1, eph.af2]),
|
|
1655
|
+
orbitLine4([eph.aDot, eph.crs, eph.deltaN0, eph.m0]),
|
|
1656
|
+
orbitLine4([eph.cuc, eph.e, eph.cus, Math.sqrt(eph.a)]),
|
|
1657
|
+
orbitLine4([eph.top, eph.cic, eph.omega0, eph.cis]),
|
|
1658
|
+
orbitLine4([eph.i0, eph.crc, eph.omega, eph.omegaDot]),
|
|
1659
|
+
orbitLine4([eph.i0Dot, eph.deltaN0Dot, eph.uraNed0, eph.uraNed1]),
|
|
1660
|
+
orbitLine4([eph.uraEd, eph.health, eph.tgd, eph.uraNed2]),
|
|
1661
|
+
orbitLine4([eph.iscL1ca, eph.iscL2c, eph.iscL5i5, eph.iscL5q5]),
|
|
1662
|
+
orbitLine4([eph.tow, resolveWnOp(eph.week, eph.wnOp)])
|
|
1663
|
+
].join("\n");
|
|
1664
|
+
}
|
|
1665
|
+
var KLOBUCHAR_SOURCES = [
|
|
1666
|
+
["GPSA", "GPSB", "G", "LNAV"],
|
|
1667
|
+
["QZSA", "QZSB", "J", "LNAV"],
|
|
1668
|
+
["BDSA", "BDSB", "C", "D1D2"],
|
|
1669
|
+
["IRNA", "IRNB", "I", "LNAV"]
|
|
1670
|
+
];
|
|
1671
|
+
function ionRecords(header, epoch) {
|
|
1672
|
+
const records = [];
|
|
1673
|
+
const iono = header.ionoCorrections;
|
|
1674
|
+
for (const [alphaKey, betaKey, sys, msg] of KLOBUCHAR_SOURCES) {
|
|
1675
|
+
const alpha = iono[alphaKey];
|
|
1676
|
+
if (!alpha) continue;
|
|
1677
|
+
const beta = iono[betaKey] ?? [0, 0, 0, 0];
|
|
1678
|
+
records.push(
|
|
1679
|
+
[
|
|
1680
|
+
`> ION ${sys} ${msg}`,
|
|
1681
|
+
` ${fmtEpoch4(epoch)}${[alpha[0] ?? 0, alpha[1] ?? 0, alpha[2] ?? 0].map(fmtD).join("")}`,
|
|
1682
|
+
orbitLine4([alpha[3] ?? 0, beta[0] ?? 0, beta[1] ?? 0, beta[2] ?? 0]),
|
|
1683
|
+
orbitLine4([beta[3] ?? 0, null])
|
|
1684
|
+
].join("\n")
|
|
1685
|
+
);
|
|
1686
|
+
}
|
|
1687
|
+
const gal = iono["GAL"];
|
|
1688
|
+
if (gal) {
|
|
1689
|
+
records.push(
|
|
1690
|
+
[
|
|
1691
|
+
"> ION E IFNV",
|
|
1692
|
+
` ${fmtEpoch4(epoch)}${[gal[0] ?? 0, gal[1] ?? 0, gal[2] ?? 0].map(fmtD).join("")}`,
|
|
1693
|
+
orbitLine4([gal[3] ?? 0])
|
|
1694
|
+
].join("\n")
|
|
1695
|
+
);
|
|
1696
|
+
}
|
|
1697
|
+
return records;
|
|
1698
|
+
}
|
|
1699
|
+
function writeHeader4(header) {
|
|
1700
|
+
const lines = [];
|
|
1701
|
+
lines.push(
|
|
1702
|
+
hdrLine(
|
|
1703
|
+
padL(" 4.01", 9) + " " + padL("NAVIGATION DATA", 20) + padL("M", 20),
|
|
1704
|
+
"RINEX VERSION / TYPE"
|
|
1705
|
+
)
|
|
1706
|
+
);
|
|
1707
|
+
const now = /* @__PURE__ */ new Date();
|
|
1708
|
+
const dateStr = now.getUTCFullYear().toString() + String(now.getUTCMonth() + 1).padStart(2, "0") + String(now.getUTCDate()).padStart(2, "0") + " " + String(now.getUTCHours()).padStart(2, "0") + String(now.getUTCMinutes()).padStart(2, "0") + String(now.getUTCSeconds()).padStart(2, "0") + " UTC";
|
|
1709
|
+
lines.push(
|
|
1710
|
+
hdrLine(
|
|
1711
|
+
padL("GNSSCalc", 20) + padL("", 20) + padL(dateStr, 20),
|
|
1712
|
+
"PGM / RUN BY / DATE"
|
|
1713
|
+
)
|
|
1714
|
+
);
|
|
1715
|
+
if (header.leapSeconds != null) {
|
|
1716
|
+
lines.push(hdrLine(padR(String(header.leapSeconds), 6), "LEAP SECONDS"));
|
|
1717
|
+
}
|
|
1718
|
+
lines.push(hdrLine("", "END OF HEADER"));
|
|
1719
|
+
return lines.join("\n") + "\n";
|
|
1720
|
+
}
|
|
1721
|
+
function writeRinexNav4(nav) {
|
|
1722
|
+
const records = [];
|
|
1723
|
+
for (const eph of nav.ephemerides) {
|
|
1724
|
+
const label = msgLabel(eph);
|
|
1725
|
+
records.push({
|
|
1726
|
+
prn: eph.prn,
|
|
1727
|
+
time: eph.tocDate.getTime(),
|
|
1728
|
+
label,
|
|
1729
|
+
body: `> EPH ${padL(eph.prn, 3)} ${label}
|
|
1730
|
+
` + (isKepler2(eph) ? keplerRecord(eph) : stateVectorRecord(eph))
|
|
1731
|
+
});
|
|
1732
|
+
}
|
|
1733
|
+
for (const eph of nav.cnav ?? []) {
|
|
1734
|
+
records.push({
|
|
1735
|
+
prn: eph.prn,
|
|
1736
|
+
time: eph.tocDate.getTime(),
|
|
1737
|
+
label: "CNAV",
|
|
1738
|
+
body: `> EPH ${padL(eph.prn, 3)} CNAV
|
|
1739
|
+
` + cnavRecord(eph)
|
|
1740
|
+
});
|
|
1741
|
+
}
|
|
1742
|
+
records.sort(
|
|
1743
|
+
(a, b) => a.prn.localeCompare(b.prn) || a.time - b.time || a.label.localeCompare(b.label)
|
|
1744
|
+
);
|
|
1745
|
+
const bodies = records.map((r) => r.body);
|
|
1746
|
+
if (records.length > 0) {
|
|
1747
|
+
const earliest = new Date(Math.min(...records.map((r) => r.time)));
|
|
1748
|
+
bodies.push(...ionRecords(nav.header, earliest));
|
|
1749
|
+
}
|
|
1750
|
+
return writeHeader4(nav.header) + (bodies.length > 0 ? bodies.join("\n") + "\n" : "");
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1462
1753
|
// src/rinex/ionex.ts
|
|
1463
1754
|
function gridRange(l1, l2, dl) {
|
|
1464
1755
|
const out = [];
|
|
@@ -2041,6 +2332,7 @@ function writeRinex4ObsBlob(header, epochs, obsTypes) {
|
|
|
2041
2332
|
createGzipLineSink,
|
|
2042
2333
|
crxDecompress,
|
|
2043
2334
|
crxRepair,
|
|
2335
|
+
fmtD,
|
|
2044
2336
|
fmtF,
|
|
2045
2337
|
hdrLine,
|
|
2046
2338
|
padL,
|
|
@@ -2058,5 +2350,6 @@ function writeRinex4ObsBlob(header, epochs, obsTypes) {
|
|
|
2058
2350
|
writeRinex2ObsBlob,
|
|
2059
2351
|
writeRinex4ObsBlob,
|
|
2060
2352
|
writeRinexNav,
|
|
2353
|
+
writeRinexNav4,
|
|
2061
2354
|
writeRinexObsBlob
|
|
2062
2355
|
});
|
package/dist/rinex.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { R as RinexHeader } from './parser-JPjjFgeP.cjs';
|
|
2
2
|
export { E as EpochSummary, P as ParseOptions, a as RinexResult, b as RinexStats, S as SYSTEM_ORDER, c as SatObsCallback, p as parseRinexStream, s as systemCmp, d as systemName } from './parser-JPjjFgeP.cjs';
|
|
3
|
-
import { a as NavResult } from './nav-
|
|
4
|
-
export {
|
|
3
|
+
import { a as NavResult, N as NavHeader, E as Ephemeris, R as RinexCnavEphemeris } from './nav-DImXUdbp.cjs';
|
|
4
|
+
export { G as GlonassEphemeris, K as KeplerEphemeris, p as parseNavFile } from './nav-DImXUdbp.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Compact RINEX (Hatanaka / CRX) decompression utilities.
|
|
@@ -106,6 +106,16 @@ declare class WarningAccumulator {
|
|
|
106
106
|
* Produces a standards-compliant RINEX 3.04 nav file from parsed NavResult data.
|
|
107
107
|
*/
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Format a number in RINEX "D19.12" scientific notation.
|
|
111
|
+
*
|
|
112
|
+
* 19 characters wide, 12 decimal digits, explicit exponent sign.
|
|
113
|
+
* Examples:
|
|
114
|
+
* 0.0 → " 0.000000000000E+00"
|
|
115
|
+
* -1.5e-8 → "-1.500000000000E-08"
|
|
116
|
+
* 5153.71875→ " 5.153718750000E+03"
|
|
117
|
+
*/
|
|
118
|
+
declare function fmtD(val: number): string;
|
|
109
119
|
/**
|
|
110
120
|
* Write a RINEX 3.04 mixed navigation file from parsed navigation data.
|
|
111
121
|
*
|
|
@@ -113,6 +123,38 @@ declare class WarningAccumulator {
|
|
|
113
123
|
*/
|
|
114
124
|
declare function writeRinexNav(nav: NavResult): string;
|
|
115
125
|
|
|
126
|
+
/**
|
|
127
|
+
* RINEX 4.01 mixed navigation file writer.
|
|
128
|
+
*
|
|
129
|
+
* Produces `> EPH` data records for the classic ephemeris types
|
|
130
|
+
* (GPS/QZSS/NavIC LNAV, Galileo INAV, BeiDou D1/D2, GLONASS FDMA,
|
|
131
|
+
* SBAS), `> EPH ... CNAV` records for GPS/QZSS CNAV ephemerides, and
|
|
132
|
+
* `> ION` records for the header's Klobuchar/NeQuick-G coefficients,
|
|
133
|
+
* per the RINEX 4.01 record tables (A9-A18, A21, A26, A32, A33).
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
/** Input for {@link writeRinexNav4}: a NavResult, optionally with CNAV. */
|
|
137
|
+
interface Nav4Input {
|
|
138
|
+
header: NavHeader;
|
|
139
|
+
ephemerides: Ephemeris[];
|
|
140
|
+
cnav?: RinexCnavEphemeris[];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Write a RINEX 4.01 mixed navigation file.
|
|
144
|
+
*
|
|
145
|
+
* Emits `> EPH` records for every classic ephemeris (message labels
|
|
146
|
+
* per constellation: LNAV, INAV, D1/D2, FDMA, SBAS) and every CNAV
|
|
147
|
+
* ephemeris (`CNAV`), sorted by PRN, epoch, then label; followed by
|
|
148
|
+
* `> ION` records when the header carries Klobuchar (GPSA/GPSB,
|
|
149
|
+
* QZSA/QZSB, BDSA/BDSB, IRNA/IRNB) or NeQuick-G (GAL) coefficients.
|
|
150
|
+
* ION records need a transmit-time epoch, which RINEX 3-style headers
|
|
151
|
+
* do not store — the earliest record epoch is used, so a file with no
|
|
152
|
+
* ephemerides gets no ION records. There is no source for system
|
|
153
|
+
* time offsets in NavHeader, so no `> STO` records are produced; leap
|
|
154
|
+
* seconds go in the LEAP SECONDS header line.
|
|
155
|
+
*/
|
|
156
|
+
declare function writeRinexNav4(nav: Nav4Input): string;
|
|
157
|
+
|
|
116
158
|
/**
|
|
117
159
|
* IONEX 1.0 parser — global ionosphere maps (GIMs) as published by
|
|
118
160
|
* the IGS analysis centres (e.g. ESA0OPSRAP_*_GIM.INX).
|
|
@@ -263,4 +305,4 @@ declare function createGzipLineSink(): {
|
|
|
263
305
|
*/
|
|
264
306
|
declare function stationHeaderLines(header: RinexHeader): string[];
|
|
265
307
|
|
|
266
|
-
export { type CompactEpoch, type CrxField, type DiffState, EMPTY_WARNINGS, type IonexGrid, NavResult, RinexHeader, type RinexWarning, type RinexWarnings, type Sp3File, type Sp3Sample, WarningAccumulator, type WarningSeverity, createGzipLineSink, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, parseSp3, sp3Position, stationHeaderLines, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexObsBlob };
|
|
308
|
+
export { type CompactEpoch, type CrxField, type DiffState, EMPTY_WARNINGS, Ephemeris, type IonexGrid, type Nav4Input, NavHeader, NavResult, RinexCnavEphemeris, RinexHeader, type RinexWarning, type RinexWarnings, type Sp3File, type Sp3Sample, WarningAccumulator, type WarningSeverity, createGzipLineSink, crxDecompress, crxRepair, fmtD, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, parseSp3, sp3Position, stationHeaderLines, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob };
|
package/dist/rinex.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { R as RinexHeader } from './parser-JPjjFgeP.js';
|
|
2
2
|
export { E as EpochSummary, P as ParseOptions, a as RinexResult, b as RinexStats, S as SYSTEM_ORDER, c as SatObsCallback, p as parseRinexStream, s as systemCmp, d as systemName } from './parser-JPjjFgeP.js';
|
|
3
|
-
import { a as NavResult } from './nav-
|
|
4
|
-
export {
|
|
3
|
+
import { a as NavResult, N as NavHeader, E as Ephemeris, R as RinexCnavEphemeris } from './nav-DImXUdbp.js';
|
|
4
|
+
export { G as GlonassEphemeris, K as KeplerEphemeris, p as parseNavFile } from './nav-DImXUdbp.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Compact RINEX (Hatanaka / CRX) decompression utilities.
|
|
@@ -106,6 +106,16 @@ declare class WarningAccumulator {
|
|
|
106
106
|
* Produces a standards-compliant RINEX 3.04 nav file from parsed NavResult data.
|
|
107
107
|
*/
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Format a number in RINEX "D19.12" scientific notation.
|
|
111
|
+
*
|
|
112
|
+
* 19 characters wide, 12 decimal digits, explicit exponent sign.
|
|
113
|
+
* Examples:
|
|
114
|
+
* 0.0 → " 0.000000000000E+00"
|
|
115
|
+
* -1.5e-8 → "-1.500000000000E-08"
|
|
116
|
+
* 5153.71875→ " 5.153718750000E+03"
|
|
117
|
+
*/
|
|
118
|
+
declare function fmtD(val: number): string;
|
|
109
119
|
/**
|
|
110
120
|
* Write a RINEX 3.04 mixed navigation file from parsed navigation data.
|
|
111
121
|
*
|
|
@@ -113,6 +123,38 @@ declare class WarningAccumulator {
|
|
|
113
123
|
*/
|
|
114
124
|
declare function writeRinexNav(nav: NavResult): string;
|
|
115
125
|
|
|
126
|
+
/**
|
|
127
|
+
* RINEX 4.01 mixed navigation file writer.
|
|
128
|
+
*
|
|
129
|
+
* Produces `> EPH` data records for the classic ephemeris types
|
|
130
|
+
* (GPS/QZSS/NavIC LNAV, Galileo INAV, BeiDou D1/D2, GLONASS FDMA,
|
|
131
|
+
* SBAS), `> EPH ... CNAV` records for GPS/QZSS CNAV ephemerides, and
|
|
132
|
+
* `> ION` records for the header's Klobuchar/NeQuick-G coefficients,
|
|
133
|
+
* per the RINEX 4.01 record tables (A9-A18, A21, A26, A32, A33).
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
/** Input for {@link writeRinexNav4}: a NavResult, optionally with CNAV. */
|
|
137
|
+
interface Nav4Input {
|
|
138
|
+
header: NavHeader;
|
|
139
|
+
ephemerides: Ephemeris[];
|
|
140
|
+
cnav?: RinexCnavEphemeris[];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Write a RINEX 4.01 mixed navigation file.
|
|
144
|
+
*
|
|
145
|
+
* Emits `> EPH` records for every classic ephemeris (message labels
|
|
146
|
+
* per constellation: LNAV, INAV, D1/D2, FDMA, SBAS) and every CNAV
|
|
147
|
+
* ephemeris (`CNAV`), sorted by PRN, epoch, then label; followed by
|
|
148
|
+
* `> ION` records when the header carries Klobuchar (GPSA/GPSB,
|
|
149
|
+
* QZSA/QZSB, BDSA/BDSB, IRNA/IRNB) or NeQuick-G (GAL) coefficients.
|
|
150
|
+
* ION records need a transmit-time epoch, which RINEX 3-style headers
|
|
151
|
+
* do not store — the earliest record epoch is used, so a file with no
|
|
152
|
+
* ephemerides gets no ION records. There is no source for system
|
|
153
|
+
* time offsets in NavHeader, so no `> STO` records are produced; leap
|
|
154
|
+
* seconds go in the LEAP SECONDS header line.
|
|
155
|
+
*/
|
|
156
|
+
declare function writeRinexNav4(nav: Nav4Input): string;
|
|
157
|
+
|
|
116
158
|
/**
|
|
117
159
|
* IONEX 1.0 parser — global ionosphere maps (GIMs) as published by
|
|
118
160
|
* the IGS analysis centres (e.g. ESA0OPSRAP_*_GIM.INX).
|
|
@@ -263,4 +305,4 @@ declare function createGzipLineSink(): {
|
|
|
263
305
|
*/
|
|
264
306
|
declare function stationHeaderLines(header: RinexHeader): string[];
|
|
265
307
|
|
|
266
|
-
export { type CompactEpoch, type CrxField, type DiffState, EMPTY_WARNINGS, type IonexGrid, NavResult, RinexHeader, type RinexWarning, type RinexWarnings, type Sp3File, type Sp3Sample, WarningAccumulator, type WarningSeverity, createGzipLineSink, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, parseSp3, sp3Position, stationHeaderLines, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexObsBlob };
|
|
308
|
+
export { type CompactEpoch, type CrxField, type DiffState, EMPTY_WARNINGS, Ephemeris, type IonexGrid, type Nav4Input, NavHeader, NavResult, RinexCnavEphemeris, RinexHeader, type RinexWarning, type RinexWarnings, type Sp3File, type Sp3Sample, WarningAccumulator, type WarningSeverity, createGzipLineSink, crxDecompress, crxRepair, fmtD, fmtF, hdrLine, padL, padR, parseCrxDataLine, parseIonex, parseSp3, sp3Position, stationHeaderLines, writeModernObsBlob, writeRinex2ObsBlob, writeRinex4ObsBlob, writeRinexNav, writeRinexNav4, writeRinexObsBlob };
|
package/dist/rinex.js
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
EMPTY_WARNINGS,
|
|
3
3
|
WarningAccumulator,
|
|
4
4
|
createGzipLineSink,
|
|
5
|
+
fmtD,
|
|
5
6
|
fmtF,
|
|
6
7
|
hdrLine,
|
|
7
8
|
padL,
|
|
@@ -15,8 +16,10 @@ import {
|
|
|
15
16
|
writeRinex2ObsBlob,
|
|
16
17
|
writeRinex4ObsBlob,
|
|
17
18
|
writeRinexNav,
|
|
19
|
+
writeRinexNav4,
|
|
18
20
|
writeRinexObsBlob
|
|
19
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-NOQAAUGY.js";
|
|
22
|
+
import "./chunk-WZDFZ76K.js";
|
|
20
23
|
import {
|
|
21
24
|
SYSTEM_ORDER,
|
|
22
25
|
crxDecompress,
|
|
@@ -34,6 +37,7 @@ export {
|
|
|
34
37
|
createGzipLineSink,
|
|
35
38
|
crxDecompress,
|
|
36
39
|
crxRepair,
|
|
40
|
+
fmtD,
|
|
37
41
|
fmtF,
|
|
38
42
|
hdrLine,
|
|
39
43
|
padL,
|
|
@@ -51,5 +55,6 @@ export {
|
|
|
51
55
|
writeRinex2ObsBlob,
|
|
52
56
|
writeRinex4ObsBlob,
|
|
53
57
|
writeRinexNav,
|
|
58
|
+
writeRinexNav4,
|
|
54
59
|
writeRinexObsBlob
|
|
55
60
|
};
|