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
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CNAV_A_REF,
|
|
3
|
+
CNAV_OMEGA_DOT_REF,
|
|
4
|
+
GPS_PI
|
|
5
|
+
} from "./chunk-WZDFZ76K.js";
|
|
6
|
+
|
|
1
7
|
// src/rinex/format.ts
|
|
2
8
|
function padL(s, w) {
|
|
3
9
|
return s.length >= w ? s.slice(0, w) : s + " ".repeat(w - s.length);
|
|
@@ -212,19 +218,19 @@ var R4_MSG_LINES = {
|
|
|
212
218
|
SBAS: 4,
|
|
213
219
|
FDMA: 5,
|
|
214
220
|
// RINEX 4 adds orbit-4 (status flags) vs 3 in RINEX 3
|
|
215
|
-
// EPH
|
|
221
|
+
// EPH type parsed into RinexCnavEphemeris for G/J (skipped otherwise)
|
|
216
222
|
CNAV: 9,
|
|
223
|
+
// EPH types we skip (different field layout)
|
|
217
224
|
CNV1: 10,
|
|
218
225
|
CNV2: 10,
|
|
219
226
|
CNV3: 9,
|
|
220
227
|
L1NV: 8,
|
|
221
228
|
L1OC: 9,
|
|
222
|
-
L3OC: 9
|
|
223
|
-
// Non-EPH records
|
|
224
|
-
STO: 2,
|
|
225
|
-
EOP: 3,
|
|
226
|
-
ION: 3
|
|
229
|
+
L3OC: 9
|
|
227
230
|
};
|
|
231
|
+
var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
|
|
232
|
+
var SEC_PER_WEEK = 7 * 86400;
|
|
233
|
+
var QZSS_CNAV_A_REF = 42164200;
|
|
228
234
|
var SUPPORTED_EPH_MSGS = /* @__PURE__ */ new Set([
|
|
229
235
|
"LNAV",
|
|
230
236
|
"INAV",
|
|
@@ -288,6 +294,20 @@ function parseDataLine(line, colOffset = 4) {
|
|
|
288
294
|
}
|
|
289
295
|
return values;
|
|
290
296
|
}
|
|
297
|
+
function parseDataLineSlots(line) {
|
|
298
|
+
const values = [];
|
|
299
|
+
for (let i = 0; i < 4; i++) {
|
|
300
|
+
const start = 4 + i * 19;
|
|
301
|
+
const s = start < line.length ? line.substring(start, start + 19).trim() : "";
|
|
302
|
+
if (s.length === 0) {
|
|
303
|
+
values.push(null);
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
const v = parseFloat19(s);
|
|
307
|
+
values.push(Number.isFinite(v) ? v : null);
|
|
308
|
+
}
|
|
309
|
+
return values;
|
|
310
|
+
}
|
|
291
311
|
function buildKeplerEphemeris(sys, prn, date, epochVals, data) {
|
|
292
312
|
const d = [];
|
|
293
313
|
for (const line of data) {
|
|
@@ -350,6 +370,68 @@ function buildStateVectorEphemeris(sys, prn, date, epochVals, data) {
|
|
|
350
370
|
zAcc: d[10] ?? 0
|
|
351
371
|
};
|
|
352
372
|
}
|
|
373
|
+
function buildCnavEphemeris(sys, prn, date, epochVals, d) {
|
|
374
|
+
const num = (r, c) => d[r]?.[c] ?? 0;
|
|
375
|
+
const opt = (r, c) => d[r]?.[c] ?? null;
|
|
376
|
+
const t = (date.getTime() - GPS_EPOCH_MS) / 1e3;
|
|
377
|
+
const week = Math.floor(t / SEC_PER_WEEK);
|
|
378
|
+
const toc = t - week * SEC_PER_WEEK;
|
|
379
|
+
const sqrtA = num(1, 3);
|
|
380
|
+
const a = sqrtA * sqrtA;
|
|
381
|
+
const aRef = sys === "J" ? QZSS_CNAV_A_REF : CNAV_A_REF;
|
|
382
|
+
const omegaDot = num(3, 3);
|
|
383
|
+
const wnOp = d[7]?.[1];
|
|
384
|
+
return {
|
|
385
|
+
system: sys,
|
|
386
|
+
prn,
|
|
387
|
+
week,
|
|
388
|
+
health: num(5, 1),
|
|
389
|
+
uraEd: num(5, 0),
|
|
390
|
+
uraNed0: num(4, 2),
|
|
391
|
+
uraNed1: num(4, 3),
|
|
392
|
+
uraNed2: num(5, 3),
|
|
393
|
+
top: num(2, 0),
|
|
394
|
+
toe: toc,
|
|
395
|
+
toeDate: date,
|
|
396
|
+
a,
|
|
397
|
+
deltaA: a - aRef,
|
|
398
|
+
aDot: num(0, 0),
|
|
399
|
+
deltaN0: num(0, 2),
|
|
400
|
+
deltaN0Dot: num(4, 1),
|
|
401
|
+
m0: num(0, 3),
|
|
402
|
+
e: num(1, 1),
|
|
403
|
+
omega: num(3, 2),
|
|
404
|
+
omega0: num(2, 2),
|
|
405
|
+
i0: num(3, 0),
|
|
406
|
+
omegaDot,
|
|
407
|
+
deltaOmegaDot: omegaDot - CNAV_OMEGA_DOT_REF * GPS_PI,
|
|
408
|
+
i0Dot: num(4, 0),
|
|
409
|
+
cis: num(2, 3),
|
|
410
|
+
cic: num(2, 1),
|
|
411
|
+
crs: num(0, 1),
|
|
412
|
+
crc: num(3, 1),
|
|
413
|
+
cus: num(1, 2),
|
|
414
|
+
cuc: num(1, 0),
|
|
415
|
+
toc,
|
|
416
|
+
tocDate: date,
|
|
417
|
+
af0: epochVals[0] ?? 0,
|
|
418
|
+
af1: epochVals[1] ?? 0,
|
|
419
|
+
af2: epochVals[2] ?? 0,
|
|
420
|
+
clockMsgType: 0,
|
|
421
|
+
// not recorded in RINEX
|
|
422
|
+
tgd: opt(5, 2),
|
|
423
|
+
iscL1ca: opt(6, 0),
|
|
424
|
+
iscL2c: opt(6, 1),
|
|
425
|
+
iscL5i5: opt(6, 2),
|
|
426
|
+
iscL5q5: opt(6, 3),
|
|
427
|
+
...wnOp != null && { wnOp },
|
|
428
|
+
integrityFlag: false,
|
|
429
|
+
// not recorded in RINEX
|
|
430
|
+
l2cPhasing: false,
|
|
431
|
+
// not recorded in RINEX
|
|
432
|
+
tow: num(7, 0)
|
|
433
|
+
};
|
|
434
|
+
}
|
|
353
435
|
function parseNavFile(text) {
|
|
354
436
|
const lines = text.split("\n");
|
|
355
437
|
const header = {
|
|
@@ -359,6 +441,7 @@ function parseNavFile(text) {
|
|
|
359
441
|
ionoCorrections: {}
|
|
360
442
|
};
|
|
361
443
|
const ephemerides = [];
|
|
444
|
+
const cnav = [];
|
|
362
445
|
let inHeader = true;
|
|
363
446
|
let i = 0;
|
|
364
447
|
while (i < lines.length) {
|
|
@@ -419,8 +502,15 @@ function parseNavFile(text) {
|
|
|
419
502
|
if (isV4 && line.charAt(0) === ">") {
|
|
420
503
|
const parts = line.substring(2).trim().split(/\s+/);
|
|
421
504
|
const recType = parts[0] ?? "";
|
|
505
|
+
const svSys = (parts[1] ?? "").charAt(0);
|
|
422
506
|
const msgType = parts[2] ?? recType;
|
|
423
|
-
if (recType !== "EPH"
|
|
507
|
+
if (recType !== "EPH") {
|
|
508
|
+
const totalLines = recType === "STO" ? 2 : recType === "EOP" ? 3 : recType === "ION" ? svSys === "E" ? 2 : 3 : 2;
|
|
509
|
+
i += totalLines + 1;
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
const isCnav = msgType === "CNAV" && (svSys === "G" || svSys === "J");
|
|
513
|
+
if (!SUPPORTED_EPH_MSGS.has(msgType) && !isCnav) {
|
|
424
514
|
const totalLines = R4_MSG_LINES[msgType] ?? 2;
|
|
425
515
|
i += totalLines + 1;
|
|
426
516
|
continue;
|
|
@@ -432,6 +522,21 @@ function parseNavFile(text) {
|
|
|
432
522
|
const sys2 = epochLine.charAt(0);
|
|
433
523
|
const parsed = parseNavEpochV3(epochLine);
|
|
434
524
|
const prn2 = `${sys2}${parsed.prn.substring(1)}`;
|
|
525
|
+
if (isCnav) {
|
|
526
|
+
const slotLines = [];
|
|
527
|
+
for (let j = 0; j < numDataLines2; j++) {
|
|
528
|
+
i++;
|
|
529
|
+
if (i >= lines.length) break;
|
|
530
|
+
slotLines.push(parseDataLineSlots(lines[i]));
|
|
531
|
+
}
|
|
532
|
+
if (slotLines.length === numDataLines2 && (sys2 === "G" || sys2 === "J")) {
|
|
533
|
+
cnav.push(
|
|
534
|
+
buildCnavEphemeris(sys2, prn2, parsed.date, parsed.values, slotLines)
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
i++;
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
435
540
|
const dataLines2 = [];
|
|
436
541
|
for (let j = 0; j < numDataLines2; j++) {
|
|
437
542
|
i++;
|
|
@@ -505,7 +610,7 @@ function parseNavFile(text) {
|
|
|
505
610
|
}
|
|
506
611
|
i++;
|
|
507
612
|
}
|
|
508
|
-
return { header, ephemerides };
|
|
613
|
+
return cnav.length > 0 ? { header, ephemerides, cnav } : { header, ephemerides };
|
|
509
614
|
}
|
|
510
615
|
|
|
511
616
|
// src/rinex/nav-writer.ts
|
|
@@ -513,9 +618,13 @@ function fmtD(val) {
|
|
|
513
618
|
if (val === 0) return " 0.000000000000E+00";
|
|
514
619
|
const sign = val < 0 ? "-" : " ";
|
|
515
620
|
const abs = Math.abs(val);
|
|
516
|
-
|
|
621
|
+
let exp = Math.floor(Math.log10(abs));
|
|
517
622
|
const mantissa = abs / 10 ** exp;
|
|
518
|
-
|
|
623
|
+
let mStr = mantissa.toFixed(12);
|
|
624
|
+
if (mStr.length > 14) {
|
|
625
|
+
exp += 1;
|
|
626
|
+
mStr = (mantissa / 10).toFixed(12);
|
|
627
|
+
}
|
|
519
628
|
const expSign = exp >= 0 ? "+" : "-";
|
|
520
629
|
const expStr = String(Math.abs(exp)).padStart(2, "0");
|
|
521
630
|
return `${sign}${mStr}E${expSign}${expStr}`;
|
|
@@ -590,7 +699,7 @@ function writeKeplerRecord(eph) {
|
|
|
590
699
|
function writeGlonassRecord(eph) {
|
|
591
700
|
const lines = [];
|
|
592
701
|
lines.push(
|
|
593
|
-
`${padL(eph.prn, 3)} ${fmtEpoch(eph.tocDate)}${fmtD(
|
|
702
|
+
`${padL(eph.prn, 3)} ${fmtEpoch(eph.tocDate)}${fmtD(eph.tauN)}${fmtD(eph.gammaN)}${fmtD(eph.messageFrameTime)}`
|
|
594
703
|
);
|
|
595
704
|
lines.push(orbitLine([eph.x, eph.xDot, eph.xAcc, eph.health]));
|
|
596
705
|
lines.push(orbitLine([eph.y, eph.yDot, eph.yAcc, eph.freqNum]));
|
|
@@ -610,6 +719,181 @@ function writeRinexNav(nav) {
|
|
|
610
719
|
return header + records.join("\n") + "\n";
|
|
611
720
|
}
|
|
612
721
|
|
|
722
|
+
// src/rinex/nav-writer-v4.ts
|
|
723
|
+
var BLANK19 = " ".repeat(19);
|
|
724
|
+
function fmtEpoch4(d) {
|
|
725
|
+
const p2 = (v) => String(v).padStart(2, "0");
|
|
726
|
+
return `${d.getUTCFullYear()} ${p2(d.getUTCMonth() + 1)} ${p2(d.getUTCDate())} ${p2(d.getUTCHours())} ${p2(d.getUTCMinutes())} ${p2(d.getUTCSeconds())}`;
|
|
727
|
+
}
|
|
728
|
+
function orbitLine4(values) {
|
|
729
|
+
const line = " " + values.map((v) => v == null ? BLANK19 : fmtD(v)).join("");
|
|
730
|
+
return line.replace(/ +$/, "");
|
|
731
|
+
}
|
|
732
|
+
function epochLine4(prn, date, vals) {
|
|
733
|
+
return `${padL(prn, 3)} ${fmtEpoch4(date)}${vals.map(fmtD).join("")}`;
|
|
734
|
+
}
|
|
735
|
+
var BDS_GEO = /* @__PURE__ */ new Set([
|
|
736
|
+
"C01",
|
|
737
|
+
"C02",
|
|
738
|
+
"C03",
|
|
739
|
+
"C04",
|
|
740
|
+
"C05",
|
|
741
|
+
"C59",
|
|
742
|
+
"C60",
|
|
743
|
+
"C61",
|
|
744
|
+
"C62",
|
|
745
|
+
"C63"
|
|
746
|
+
]);
|
|
747
|
+
function msgLabel(eph) {
|
|
748
|
+
switch (eph.system) {
|
|
749
|
+
case "E":
|
|
750
|
+
return "INAV";
|
|
751
|
+
case "C":
|
|
752
|
+
return BDS_GEO.has(eph.prn) ? "D2" : "D1";
|
|
753
|
+
case "R":
|
|
754
|
+
return "FDMA";
|
|
755
|
+
case "S":
|
|
756
|
+
return "SBAS";
|
|
757
|
+
default:
|
|
758
|
+
return "LNAV";
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
function isKepler2(eph) {
|
|
762
|
+
return "af0" in eph;
|
|
763
|
+
}
|
|
764
|
+
function keplerRecord(eph) {
|
|
765
|
+
return [
|
|
766
|
+
epochLine4(eph.prn, eph.tocDate, [eph.af0, eph.af1, eph.af2]),
|
|
767
|
+
orbitLine4([eph.iode, eph.crs, eph.deltaN, eph.m0]),
|
|
768
|
+
orbitLine4([eph.cuc, eph.e, eph.cus, eph.sqrtA]),
|
|
769
|
+
orbitLine4([eph.toe, eph.cic, eph.omega0, eph.cis]),
|
|
770
|
+
orbitLine4([eph.i0, eph.crc, eph.omega, eph.omegaDot]),
|
|
771
|
+
orbitLine4([eph.idot, 0, eph.week, 0]),
|
|
772
|
+
orbitLine4([0, eph.svHealth, eph.tgd, 0]),
|
|
773
|
+
orbitLine4([eph.toe, 0, 0, 0])
|
|
774
|
+
].join("\n");
|
|
775
|
+
}
|
|
776
|
+
function stateVectorRecord(eph) {
|
|
777
|
+
const lines = [
|
|
778
|
+
epochLine4(eph.prn, eph.tocDate, [
|
|
779
|
+
eph.tauN,
|
|
780
|
+
eph.gammaN,
|
|
781
|
+
eph.messageFrameTime
|
|
782
|
+
]),
|
|
783
|
+
orbitLine4([eph.x, eph.xDot, eph.xAcc, eph.health]),
|
|
784
|
+
orbitLine4([eph.y, eph.yDot, eph.yAcc, eph.freqNum]),
|
|
785
|
+
orbitLine4([eph.z, eph.zDot, eph.zAcc, 0])
|
|
786
|
+
];
|
|
787
|
+
if (eph.system === "R") {
|
|
788
|
+
lines.push(orbitLine4([null, 999999999999e-3, 15, null]));
|
|
789
|
+
}
|
|
790
|
+
return lines.join("\n");
|
|
791
|
+
}
|
|
792
|
+
function resolveWnOp(week, wnOp) {
|
|
793
|
+
if (wnOp == null) return week;
|
|
794
|
+
return week - ((week - wnOp) % 256 + 256) % 256;
|
|
795
|
+
}
|
|
796
|
+
function cnavRecord(eph) {
|
|
797
|
+
return [
|
|
798
|
+
epochLine4(eph.prn, eph.tocDate, [eph.af0, eph.af1, eph.af2]),
|
|
799
|
+
orbitLine4([eph.aDot, eph.crs, eph.deltaN0, eph.m0]),
|
|
800
|
+
orbitLine4([eph.cuc, eph.e, eph.cus, Math.sqrt(eph.a)]),
|
|
801
|
+
orbitLine4([eph.top, eph.cic, eph.omega0, eph.cis]),
|
|
802
|
+
orbitLine4([eph.i0, eph.crc, eph.omega, eph.omegaDot]),
|
|
803
|
+
orbitLine4([eph.i0Dot, eph.deltaN0Dot, eph.uraNed0, eph.uraNed1]),
|
|
804
|
+
orbitLine4([eph.uraEd, eph.health, eph.tgd, eph.uraNed2]),
|
|
805
|
+
orbitLine4([eph.iscL1ca, eph.iscL2c, eph.iscL5i5, eph.iscL5q5]),
|
|
806
|
+
orbitLine4([eph.tow, resolveWnOp(eph.week, eph.wnOp)])
|
|
807
|
+
].join("\n");
|
|
808
|
+
}
|
|
809
|
+
var KLOBUCHAR_SOURCES = [
|
|
810
|
+
["GPSA", "GPSB", "G", "LNAV"],
|
|
811
|
+
["QZSA", "QZSB", "J", "LNAV"],
|
|
812
|
+
["BDSA", "BDSB", "C", "D1D2"],
|
|
813
|
+
["IRNA", "IRNB", "I", "LNAV"]
|
|
814
|
+
];
|
|
815
|
+
function ionRecords(header, epoch) {
|
|
816
|
+
const records = [];
|
|
817
|
+
const iono = header.ionoCorrections;
|
|
818
|
+
for (const [alphaKey, betaKey, sys, msg] of KLOBUCHAR_SOURCES) {
|
|
819
|
+
const alpha = iono[alphaKey];
|
|
820
|
+
if (!alpha) continue;
|
|
821
|
+
const beta = iono[betaKey] ?? [0, 0, 0, 0];
|
|
822
|
+
records.push(
|
|
823
|
+
[
|
|
824
|
+
`> ION ${sys} ${msg}`,
|
|
825
|
+
` ${fmtEpoch4(epoch)}${[alpha[0] ?? 0, alpha[1] ?? 0, alpha[2] ?? 0].map(fmtD).join("")}`,
|
|
826
|
+
orbitLine4([alpha[3] ?? 0, beta[0] ?? 0, beta[1] ?? 0, beta[2] ?? 0]),
|
|
827
|
+
orbitLine4([beta[3] ?? 0, null])
|
|
828
|
+
].join("\n")
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
|
+
const gal = iono["GAL"];
|
|
832
|
+
if (gal) {
|
|
833
|
+
records.push(
|
|
834
|
+
[
|
|
835
|
+
"> ION E IFNV",
|
|
836
|
+
` ${fmtEpoch4(epoch)}${[gal[0] ?? 0, gal[1] ?? 0, gal[2] ?? 0].map(fmtD).join("")}`,
|
|
837
|
+
orbitLine4([gal[3] ?? 0])
|
|
838
|
+
].join("\n")
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
return records;
|
|
842
|
+
}
|
|
843
|
+
function writeHeader4(header) {
|
|
844
|
+
const lines = [];
|
|
845
|
+
lines.push(
|
|
846
|
+
hdrLine(
|
|
847
|
+
padL(" 4.01", 9) + " " + padL("NAVIGATION DATA", 20) + padL("M", 20),
|
|
848
|
+
"RINEX VERSION / TYPE"
|
|
849
|
+
)
|
|
850
|
+
);
|
|
851
|
+
const now = /* @__PURE__ */ new Date();
|
|
852
|
+
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";
|
|
853
|
+
lines.push(
|
|
854
|
+
hdrLine(
|
|
855
|
+
padL("GNSSCalc", 20) + padL("", 20) + padL(dateStr, 20),
|
|
856
|
+
"PGM / RUN BY / DATE"
|
|
857
|
+
)
|
|
858
|
+
);
|
|
859
|
+
if (header.leapSeconds != null) {
|
|
860
|
+
lines.push(hdrLine(padR(String(header.leapSeconds), 6), "LEAP SECONDS"));
|
|
861
|
+
}
|
|
862
|
+
lines.push(hdrLine("", "END OF HEADER"));
|
|
863
|
+
return lines.join("\n") + "\n";
|
|
864
|
+
}
|
|
865
|
+
function writeRinexNav4(nav) {
|
|
866
|
+
const records = [];
|
|
867
|
+
for (const eph of nav.ephemerides) {
|
|
868
|
+
const label = msgLabel(eph);
|
|
869
|
+
records.push({
|
|
870
|
+
prn: eph.prn,
|
|
871
|
+
time: eph.tocDate.getTime(),
|
|
872
|
+
label,
|
|
873
|
+
body: `> EPH ${padL(eph.prn, 3)} ${label}
|
|
874
|
+
` + (isKepler2(eph) ? keplerRecord(eph) : stateVectorRecord(eph))
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
for (const eph of nav.cnav ?? []) {
|
|
878
|
+
records.push({
|
|
879
|
+
prn: eph.prn,
|
|
880
|
+
time: eph.tocDate.getTime(),
|
|
881
|
+
label: "CNAV",
|
|
882
|
+
body: `> EPH ${padL(eph.prn, 3)} CNAV
|
|
883
|
+
` + cnavRecord(eph)
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
records.sort(
|
|
887
|
+
(a, b) => a.prn.localeCompare(b.prn) || a.time - b.time || a.label.localeCompare(b.label)
|
|
888
|
+
);
|
|
889
|
+
const bodies = records.map((r) => r.body);
|
|
890
|
+
if (records.length > 0) {
|
|
891
|
+
const earliest = new Date(Math.min(...records.map((r) => r.time)));
|
|
892
|
+
bodies.push(...ionRecords(nav.header, earliest));
|
|
893
|
+
}
|
|
894
|
+
return writeHeader4(nav.header) + (bodies.length > 0 ? bodies.join("\n") + "\n" : "");
|
|
895
|
+
}
|
|
896
|
+
|
|
613
897
|
// src/rinex/ionex.ts
|
|
614
898
|
function gridRange(l1, l2, dl) {
|
|
615
899
|
const out = [];
|
|
@@ -1193,7 +1477,9 @@ export {
|
|
|
1193
1477
|
EMPTY_WARNINGS,
|
|
1194
1478
|
WarningAccumulator,
|
|
1195
1479
|
parseNavFile,
|
|
1480
|
+
fmtD,
|
|
1196
1481
|
writeRinexNav,
|
|
1482
|
+
writeRinexNav4,
|
|
1197
1483
|
parseIonex,
|
|
1198
1484
|
parseSp3,
|
|
1199
1485
|
sp3Position,
|