gnss-js 1.62.0 → 1.64.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.
@@ -563,6 +563,302 @@ function decodeEphemeris(frame) {
563
563
  }
564
564
  }
565
565
 
566
+ // src/rtcm3/igs-ssr.ts
567
+ var UPDATE_INTERVAL_S = [
568
+ 1,
569
+ 2,
570
+ 5,
571
+ 10,
572
+ 15,
573
+ 30,
574
+ 60,
575
+ 120,
576
+ 240,
577
+ 300,
578
+ 600,
579
+ 900,
580
+ 1800,
581
+ 3600,
582
+ 7200,
583
+ 10800
584
+ ];
585
+ var SYSTEM_BY_BASE = {
586
+ 20: "G",
587
+ 40: "R",
588
+ 60: "E",
589
+ 80: "J",
590
+ 100: "C",
591
+ 120: "S"
592
+ };
593
+ var KIND_BY_OFFSET = {
594
+ 1: "orbit",
595
+ 2: "clock",
596
+ 3: "combined",
597
+ 4: "highRateClock",
598
+ 5: "codeBias",
599
+ 6: "phaseBias",
600
+ 7: "ura"
601
+ };
602
+ var two = (n) => n.toString().padStart(2, "0");
603
+ function prnFor(system, id) {
604
+ if (system === "J") return `J${two(id)}`;
605
+ if (system === "S") return `S${two(19 + id)}`;
606
+ return `${system}${two(id)}`;
607
+ }
608
+ function ssrUraMm(v) {
609
+ if (v === 0) return null;
610
+ const cls = v >> 3 & 7;
611
+ const val = v & 7;
612
+ return 3 ** cls * (1 + val / 4) - 1;
613
+ }
614
+ function decodeIgsSsr(frame) {
615
+ if (frame.messageType !== 4076) return null;
616
+ const r = new BitReader(frame.payload);
617
+ r.readU(12);
618
+ const version = r.readU(3);
619
+ const im = r.readU(8);
620
+ if (im === 201) return decodeIono(r, version, im);
621
+ const base = Math.floor(im / 20) * 20;
622
+ const system = SYSTEM_BY_BASE[base];
623
+ const kind = KIND_BY_OFFSET[im - base];
624
+ if (!system || !kind) return null;
625
+ const epochS = r.readU(20);
626
+ const updateIntervalS = UPDATE_INTERVAL_S[r.readU(4)];
627
+ const multipleMessage = r.readU(1) === 1;
628
+ const iodSsr = r.readU(4);
629
+ const providerId = r.readU(16);
630
+ const solutionId = r.readU(4);
631
+ const hasDatum = kind === "orbit" || kind === "combined";
632
+ const referenceDatum = hasDatum ? r.readU(1) : void 0;
633
+ let dispersiveConsistency;
634
+ let mwConsistency;
635
+ if (kind === "phaseBias") {
636
+ dispersiveConsistency = r.readU(1) === 1;
637
+ mwConsistency = r.readU(1) === 1;
638
+ }
639
+ const nsat = r.readU(6);
640
+ const readOrbit = (s) => {
641
+ s.iode = r.readU(8);
642
+ s.deltaRadial = r.readS(22) * 1e-4;
643
+ s.deltaAlongTrack = r.readS(20) * 4e-4;
644
+ s.deltaCrossTrack = r.readS(20) * 4e-4;
645
+ s.dotRadial = r.readS(21) * 1e-6;
646
+ s.dotAlongTrack = r.readS(19) * 4e-6;
647
+ s.dotCrossTrack = r.readS(19) * 4e-6;
648
+ };
649
+ const readClock = (s) => {
650
+ s.c0 = r.readS(22) * 1e-4;
651
+ s.c1 = r.readS(21) * 1e-6;
652
+ s.c2 = r.readS(27) * 2e-8;
653
+ };
654
+ const satellites = [];
655
+ for (let i = 0; i < nsat; i++) {
656
+ const id = r.readU(6);
657
+ const sat = { prn: prnFor(system, id) };
658
+ if (kind === "orbit" || kind === "combined") readOrbit(sat);
659
+ if (kind === "clock" || kind === "combined") readClock(sat);
660
+ else if (kind === "ura")
661
+ sat.uraMm = ssrUraMm(r.readU(6));
662
+ else if (kind === "highRateClock")
663
+ sat.highRateClock = r.readS(22) * 1e-4;
664
+ else if (kind === "codeBias") {
665
+ const n = r.readU(5);
666
+ const biases = [];
667
+ for (let b = 0; b < n; b++) {
668
+ const signal = r.readU(5);
669
+ biases.push({
670
+ signal,
671
+ signalName: `#${signal}`,
672
+ biasM: r.readS(14) * 0.01
673
+ // IDF025 0.01 m
674
+ });
675
+ }
676
+ sat.codeBiases = biases;
677
+ } else if (kind === "phaseBias") {
678
+ const n = r.readU(5);
679
+ r.readU(9);
680
+ r.readS(8);
681
+ const biases = [];
682
+ for (let b = 0; b < n; b++) {
683
+ const signal = r.readU(5);
684
+ const integer = r.readU(1) === 1;
685
+ const wideLaneGroup = r.readU(2);
686
+ const discontinuity = r.readU(4);
687
+ const biasM = r.readS(20) * 1e-4;
688
+ biases.push({ signal, integer, wideLaneGroup, discontinuity, biasM });
689
+ }
690
+ sat.phaseBiases = biases;
691
+ }
692
+ satellites.push(sat);
693
+ }
694
+ return {
695
+ messageType: 4076,
696
+ version,
697
+ igsMessageNumber: im,
698
+ system,
699
+ kind,
700
+ epochS,
701
+ updateIntervalS,
702
+ multipleMessage,
703
+ referenceDatum,
704
+ iodSsr,
705
+ providerId,
706
+ solutionId,
707
+ dispersiveConsistency,
708
+ mwConsistency,
709
+ satellites
710
+ };
711
+ }
712
+ function decodeIono(r, version, im) {
713
+ const epochS = r.readU(20);
714
+ const updateIntervalS = UPDATE_INTERVAL_S[r.readU(4)];
715
+ const multipleMessage = r.readU(1) === 1;
716
+ const iodSsr = r.readU(4);
717
+ const providerId = r.readU(16);
718
+ const solutionId = r.readU(4);
719
+ const qualityTecu = r.readU(9) * 0.05;
720
+ const nLayers = r.readU(2) + 1;
721
+ const layers = [];
722
+ for (let l = 0; l < nLayers; l++) {
723
+ const heightKm = r.readU(8) * 10;
724
+ const degree = r.readU(4) + 1;
725
+ const order = r.readU(4) + 1;
726
+ const N = degree;
727
+ const M = order;
728
+ const nCoef = (N + 1) * (N + 1) - (N - M) * (N - M + 1);
729
+ const nCos = nCoef;
730
+ let nSin = 0;
731
+ for (let m = 1; m <= M; m++) nSin += N - m + 1;
732
+ for (let i = 0; i < nCos + nSin; i++) r.readS(16);
733
+ layers.push({ heightKm, degree, order, coefficientCount: nCos + nSin });
734
+ }
735
+ return {
736
+ messageType: 4076,
737
+ version,
738
+ igsMessageNumber: im,
739
+ system: "I",
740
+ kind: "ionosphere",
741
+ epochS,
742
+ updateIntervalS,
743
+ multipleMessage,
744
+ iodSsr,
745
+ providerId,
746
+ solutionId,
747
+ satellites: [],
748
+ iono: { qualityTecu, layers }
749
+ };
750
+ }
751
+
752
+ // src/rtcm3/legacy-obs.ts
753
+ var PRUNIT_GPS = 299792.458;
754
+ var PRUNIT_GLO = 599584.916;
755
+ var LAM_GPS_L1 = C_LIGHT / 157542e4;
756
+ var LAM_GPS_L2 = C_LIGHT / 12276e5;
757
+ var PPR_INVALID = -(2 ** 19);
758
+ var PR21_INVALID = -(2 ** 13);
759
+ function legacyLockSec(i) {
760
+ if (i < 24) return i;
761
+ if (i < 48) return 2 * i - 24;
762
+ if (i < 72) return 4 * i - 120;
763
+ if (i < 96) return 8 * i - 408;
764
+ if (i < 120) return 16 * i - 1176;
765
+ if (i < 127) return 32 * i - 3096;
766
+ return 937;
767
+ }
768
+ var two2 = (n) => n.toString().padStart(2, "0");
769
+ function decodeLegacyObs(frame) {
770
+ const type = frame.messageType;
771
+ const gps = type >= 1001 && type <= 1004;
772
+ const glo = type >= 1009 && type <= 1012;
773
+ if (!gps && !glo) return null;
774
+ const ext = type === 1002 || type === 1004 || type === 1010 || type === 1012;
775
+ const dual = type === 1003 || type === 1004 || type === 1011 || type === 1012;
776
+ const system = gps ? "G" : "R";
777
+ const r = new BitReader(frame.payload);
778
+ r.readU(12);
779
+ r.readU(12);
780
+ let epochMs;
781
+ let nsat;
782
+ if (gps) {
783
+ epochMs = r.readU(30);
784
+ r.readU(1);
785
+ nsat = r.readU(5);
786
+ r.readU(1);
787
+ r.readU(3);
788
+ } else {
789
+ const tk = r.readU(27);
790
+ r.readU(1);
791
+ nsat = r.readU(5);
792
+ r.readU(1);
793
+ r.readU(3);
794
+ const gloDow = new Date(Date.now() + 3 * 36e5).getUTCDay();
795
+ epochMs = (gloDow << 27 | tk) >>> 0;
796
+ }
797
+ const observations = [];
798
+ for (let s = 0; s < nsat; s++) {
799
+ const satId = r.readU(6);
800
+ const code1 = r.readU(1);
801
+ const freqCh = glo ? r.readU(5) : 0;
802
+ const pr1raw = r.readU(gps ? 24 : 25);
803
+ const ppr1 = r.readS(20);
804
+ const lock1 = r.readU(7);
805
+ let amb = 0;
806
+ let cnr1 = 0;
807
+ if (ext) {
808
+ amb = r.readU(gps ? 8 : 7);
809
+ cnr1 = r.readU(8);
810
+ }
811
+ let code2 = 0;
812
+ let pr21 = 0;
813
+ let ppr2 = 0;
814
+ let lock2 = 0;
815
+ let cnr2 = 0;
816
+ if (dual) {
817
+ code2 = r.readU(2);
818
+ pr21 = r.readS(14);
819
+ ppr2 = r.readS(20);
820
+ lock2 = r.readU(7);
821
+ if (ext) cnr2 = r.readU(8);
822
+ }
823
+ if (gps && (satId < 1 || satId > 32)) continue;
824
+ if (glo && (satId < 1 || satId > 24)) continue;
825
+ const prunit = gps ? PRUNIT_GPS : PRUNIT_GLO;
826
+ const pr1 = pr1raw * 0.02 + amb * prunit;
827
+ const k = freqCh - 7;
828
+ const lamL1 = gps ? LAM_GPS_L1 : C_LIGHT / (GLO_F1_BASE + k * GLO_F1_STEP);
829
+ const lamL2 = gps ? LAM_GPS_L2 : C_LIGHT / (GLO_F2_BASE + k * GLO_F2_STEP);
830
+ const signals = [];
831
+ {
832
+ const sig = {
833
+ rinexCode: gps ? code1 ? "1W" : "1C" : code1 ? "1P" : "1C",
834
+ pseudorange: pr1,
835
+ wavelength: lamL1,
836
+ lockTime: legacyLockSec(lock1)
837
+ };
838
+ if (ppr1 !== PPR_INVALID) sig.phase = (pr1 + ppr1 * 5e-4) / lamL1;
839
+ if (ext && cnr1 > 0) sig.cn0 = cnr1 * 0.25;
840
+ signals.push(sig);
841
+ }
842
+ if (dual) {
843
+ const sig = {
844
+ rinexCode: gps ? code2 === 0 ? "2X" : "2W" : code2 === 0 ? "2C" : "2P",
845
+ wavelength: lamL2,
846
+ lockTime: legacyLockSec(lock2)
847
+ };
848
+ if (pr21 !== PR21_INVALID) sig.pseudorange = pr1 + pr21 * 0.02;
849
+ if (ppr2 !== PPR_INVALID) sig.phase = (pr1 + ppr2 * 5e-4) / lamL2;
850
+ if (ext && cnr2 > 0) sig.cn0 = cnr2 * 0.25;
851
+ signals.push(sig);
852
+ }
853
+ observations.push({
854
+ prn: `${system}${two2(satId)}`,
855
+ system,
856
+ signals
857
+ });
858
+ }
859
+ return { messageType: type, epochMs, system, observations };
860
+ }
861
+
566
862
  // src/rtcm3/msm.ts
567
863
  var GPS_L1 = FREQ.G["1"];
568
864
  var GPS_L2 = FREQ.G["2"];
@@ -1097,6 +1393,144 @@ function resetGloFreqCache() {
1097
1393
  gloFreqNum.fill(-128);
1098
1394
  }
1099
1395
 
1396
+ // src/rtcm3/ssr.ts
1397
+ var UPDATE_INTERVAL_S2 = [
1398
+ 1,
1399
+ 2,
1400
+ 5,
1401
+ 10,
1402
+ 15,
1403
+ 30,
1404
+ 60,
1405
+ 120,
1406
+ 240,
1407
+ 300,
1408
+ 600,
1409
+ 900,
1410
+ 1800,
1411
+ 3600,
1412
+ 7200,
1413
+ 10800
1414
+ ];
1415
+ var GPS_SIGNAL = {
1416
+ 0: "L1 C/A",
1417
+ 1: "L1 P",
1418
+ 2: "L1 Z-tracking",
1419
+ 5: "L2 C/A",
1420
+ 6: "L2 semi-codeless",
1421
+ 7: "L2C(M)",
1422
+ 8: "L2C(L)",
1423
+ 9: "L2C(M+L)",
1424
+ 10: "L2 P",
1425
+ 11: "L2 Z-tracking",
1426
+ 14: "L5 I",
1427
+ 15: "L5 Q"
1428
+ };
1429
+ var GLO_SIGNAL = {
1430
+ 0: "G1 C/A",
1431
+ 1: "G1 P",
1432
+ 2: "G2 C/A",
1433
+ 3: "G2 P"
1434
+ };
1435
+ var SSR_KIND = {
1436
+ 1057: { system: "G", kind: "orbit" },
1437
+ 1058: { system: "G", kind: "clock" },
1438
+ 1059: { system: "G", kind: "codeBias" },
1439
+ 1060: { system: "G", kind: "combined" },
1440
+ 1061: { system: "G", kind: "ura" },
1441
+ 1062: { system: "G", kind: "highRateClock" },
1442
+ 1063: { system: "R", kind: "orbit" },
1443
+ 1064: { system: "R", kind: "clock" },
1444
+ 1065: { system: "R", kind: "codeBias" },
1445
+ 1066: { system: "R", kind: "combined" },
1446
+ 1067: { system: "R", kind: "ura" },
1447
+ 1068: { system: "R", kind: "highRateClock" }
1448
+ };
1449
+ function ssrUraMm2(v) {
1450
+ if (v === 0) return null;
1451
+ const cls = v >> 3 & 7;
1452
+ const val = v & 7;
1453
+ return 3 ** cls * (1 + val / 4) - 1;
1454
+ }
1455
+ var two3 = (n) => n.toString().padStart(2, "0");
1456
+ function decodeSsr(frame) {
1457
+ const spec = SSR_KIND[frame.messageType];
1458
+ if (!spec) return null;
1459
+ const { system, kind } = spec;
1460
+ const gps = system === "G";
1461
+ const r = new BitReader(frame.payload);
1462
+ r.readU(12);
1463
+ const epochS = r.readU(gps ? 20 : 17);
1464
+ const updateIntervalS = UPDATE_INTERVAL_S2[r.readU(4)];
1465
+ const multipleMessage = r.readU(1) === 1;
1466
+ const hasDatum = kind === "orbit" || kind === "combined";
1467
+ const referenceDatum = hasDatum ? r.readU(1) : void 0;
1468
+ const iodSsr = r.readU(4);
1469
+ const providerId = r.readU(16);
1470
+ const solutionId = r.readU(4);
1471
+ const nsat = r.readU(6);
1472
+ const sigName = gps ? GPS_SIGNAL : GLO_SIGNAL;
1473
+ const satellites = [];
1474
+ const readOrbit = (sat) => {
1475
+ sat.deltaRadial = r.readS(22) * 1e-4;
1476
+ sat.deltaAlongTrack = r.readS(20) * 4e-4;
1477
+ sat.deltaCrossTrack = r.readS(20) * 4e-4;
1478
+ sat.dotRadial = r.readS(21) * 1e-6;
1479
+ sat.dotAlongTrack = r.readS(19) * 4e-6;
1480
+ sat.dotCrossTrack = r.readS(19) * 4e-6;
1481
+ };
1482
+ const readClock = (sat) => {
1483
+ sat.c0 = r.readS(22) * 1e-4;
1484
+ sat.c1 = r.readS(21) * 1e-6;
1485
+ sat.c2 = r.readS(27) * 2e-8;
1486
+ };
1487
+ for (let i = 0; i < nsat; i++) {
1488
+ const satId = gps ? r.readU(6) : r.readU(5);
1489
+ const sat = { prn: `${system}${two3(satId)}` };
1490
+ if (kind === "orbit" || kind === "combined") {
1491
+ sat.iode = r.readU(8);
1492
+ readOrbit(sat);
1493
+ }
1494
+ if (kind === "combined") readClock(sat);
1495
+ else if (kind === "clock") readClock(sat);
1496
+ else if (kind === "ura")
1497
+ sat.uraMm = ssrUraMm2(r.readU(6));
1498
+ else if (kind === "highRateClock")
1499
+ sat.highRateClock = r.readS(22) * 1e-4;
1500
+ else if (kind === "codeBias") {
1501
+ const ncb = r.readU(5);
1502
+ const biases = [];
1503
+ for (let c = 0; c < ncb; c++) {
1504
+ const signal = r.readU(5);
1505
+ const biasM = r.readS(14) * 0.01;
1506
+ biases.push({
1507
+ signal,
1508
+ signalName: sigName[signal] ?? `#${signal}`,
1509
+ biasM
1510
+ });
1511
+ }
1512
+ sat.codeBiases = biases;
1513
+ }
1514
+ satellites.push(sat);
1515
+ }
1516
+ return {
1517
+ messageType: frame.messageType,
1518
+ system,
1519
+ kind,
1520
+ epochS,
1521
+ updateIntervalS,
1522
+ multipleMessage,
1523
+ referenceDatum,
1524
+ iodSsr,
1525
+ providerId,
1526
+ solutionId,
1527
+ satellites
1528
+ };
1529
+ }
1530
+ function isSsrMessage(messageType) {
1531
+ return messageType in SSR_KIND;
1532
+ }
1533
+
1100
1534
  // src/rtcm3/station.ts
1101
1535
  function createStationMeta() {
1102
1536
  return {
@@ -1447,10 +1881,14 @@ export {
1447
1881
  Rtcm3Decoder,
1448
1882
  readString,
1449
1883
  decodeEphemeris,
1884
+ decodeIgsSsr,
1885
+ decodeLegacyObs,
1450
1886
  decodeMsmFull,
1451
1887
  msmEpochToDate,
1452
1888
  setGloFreqNumber,
1453
1889
  resetGloFreqCache,
1890
+ decodeSsr,
1891
+ isSsrMessage,
1454
1892
  createStationMeta,
1455
1893
  updateStationMeta,
1456
1894
  RTCM3_MESSAGE_NAMES,