gnss-js 1.38.0 → 1.40.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-CKRNXZHT.js → chunk-J2E2IKJR.js} +94 -56
- package/dist/index.cjs +98 -60
- package/dist/index.js +1 -1
- package/dist/trimble.cjs +94 -56
- package/dist/trimble.d.cts +12 -10
- package/dist/trimble.d.ts +12 -10
- package/dist/trimble.js +1 -1
- package/package.json +1 -1
|
@@ -40,68 +40,106 @@ function* trimbleFrames(data, stats) {
|
|
|
40
40
|
|
|
41
41
|
// src/trimble/nav.ts
|
|
42
42
|
var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
|
|
43
|
+
var BDT_EPOCH_MS = Date.UTC(2006, 0, 1);
|
|
43
44
|
var SEC_PER_WEEK = 7 * 86400;
|
|
44
45
|
var MS_PER_WEEK = SEC_PER_WEEK * 1e3;
|
|
45
46
|
var GPS_PI = 3.1415926535898;
|
|
47
|
+
var BDS_WEEK_OFFSET = 1356;
|
|
48
|
+
var BDS_LEAP_SEC = 14;
|
|
46
49
|
var gpsMs = (week, sec) => GPS_EPOCH_MS + week * MS_PER_WEEK + sec * 1e3;
|
|
47
50
|
var sowOf = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK;
|
|
48
51
|
var SUB_GPS_EPHEMERIS = 1;
|
|
49
52
|
var SUB_ION_UTC = 3;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
53
|
+
var SUB_BDS_EPHEMERIS = 21;
|
|
54
|
+
function readKepler(view, base) {
|
|
55
|
+
return {
|
|
56
|
+
svid: view.getUint8(base + 5),
|
|
57
|
+
week: view.getUint16(base + 6, false),
|
|
58
|
+
iode: view.getUint8(base + 11),
|
|
59
|
+
tocSec: view.getInt32(base + 16, false),
|
|
60
|
+
toeSec: view.getUint32(base + 20, false),
|
|
61
|
+
tgd: view.getFloat64(base + 24, false),
|
|
62
|
+
af2: view.getFloat64(base + 32, false),
|
|
63
|
+
af1: view.getFloat64(base + 40, false),
|
|
64
|
+
af0: view.getFloat64(base + 48, false),
|
|
65
|
+
crs: view.getFloat64(base + 56, false),
|
|
66
|
+
deltaN: view.getFloat64(base + 64, false) * GPS_PI,
|
|
67
|
+
m0: view.getFloat64(base + 72, false) * GPS_PI,
|
|
68
|
+
cuc: view.getFloat64(base + 80, false) * GPS_PI,
|
|
69
|
+
e: view.getFloat64(base + 88, false),
|
|
70
|
+
cus: view.getFloat64(base + 96, false) * GPS_PI,
|
|
71
|
+
sqrtA: view.getFloat64(base + 104, false),
|
|
72
|
+
cic: view.getFloat64(base + 112, false) * GPS_PI,
|
|
73
|
+
omega0: view.getFloat64(base + 120, false) * GPS_PI,
|
|
74
|
+
cis: view.getFloat64(base + 128, false) * GPS_PI,
|
|
75
|
+
i0: view.getFloat64(base + 136, false) * GPS_PI,
|
|
76
|
+
crc: view.getFloat64(base + 144, false),
|
|
77
|
+
omega: view.getFloat64(base + 152, false) * GPS_PI,
|
|
78
|
+
omegaDot: view.getFloat64(base + 160, false) * GPS_PI,
|
|
79
|
+
idot: view.getFloat64(base + 168, false) * GPS_PI,
|
|
80
|
+
flags: view.getUint32(base + 176, false)
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function keplerCommon(r) {
|
|
84
|
+
return {
|
|
85
|
+
af0: r.af0,
|
|
86
|
+
af1: r.af1,
|
|
87
|
+
af2: r.af2,
|
|
88
|
+
iode: r.iode,
|
|
89
|
+
crs: r.crs,
|
|
90
|
+
deltaN: r.deltaN,
|
|
91
|
+
m0: r.m0,
|
|
92
|
+
cuc: r.cuc,
|
|
93
|
+
e: r.e,
|
|
94
|
+
cus: r.cus,
|
|
95
|
+
sqrtA: r.sqrtA,
|
|
96
|
+
cic: r.cic,
|
|
97
|
+
omega0: r.omega0,
|
|
98
|
+
cis: r.cis,
|
|
99
|
+
i0: r.i0,
|
|
100
|
+
crc: r.crc,
|
|
101
|
+
omega: r.omega,
|
|
102
|
+
omegaDot: r.omegaDot,
|
|
103
|
+
idot: r.idot,
|
|
104
|
+
tgd: r.tgd
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function decodeGpsEphemeris(view, base) {
|
|
108
|
+
const r = readKepler(view, base);
|
|
109
|
+
if (r.svid < 1 || r.svid > 32) return null;
|
|
110
|
+
const tocMs = gpsMs(r.week, r.tocSec);
|
|
77
111
|
return {
|
|
78
112
|
system: "G",
|
|
79
|
-
prn: `G${String(
|
|
80
|
-
toc: sowOf(
|
|
81
|
-
tocDate: new Date(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
113
|
+
prn: `G${String(r.svid).padStart(2, "0")}`,
|
|
114
|
+
toc: sowOf(tocMs),
|
|
115
|
+
tocDate: new Date(tocMs),
|
|
116
|
+
toe: r.toeSec,
|
|
117
|
+
week: r.week,
|
|
118
|
+
svHealth: r.flags >>> 4 & 127,
|
|
119
|
+
...keplerCommon(r)
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function decodeBdsEphemeris(view, base) {
|
|
123
|
+
const r = readKepler(view, base);
|
|
124
|
+
if (r.svid < 1 || r.svid > 63) return null;
|
|
125
|
+
const bdsWeek = r.week - BDS_WEEK_OFFSET;
|
|
126
|
+
const tocSec = r.tocSec - BDS_LEAP_SEC;
|
|
127
|
+
const toeSec = r.toeSec - BDS_LEAP_SEC;
|
|
128
|
+
const tocDate = new Date(
|
|
129
|
+
BDT_EPOCH_MS + bdsWeek * MS_PER_WEEK + tocSec * 1e3
|
|
130
|
+
);
|
|
131
|
+
return {
|
|
132
|
+
system: "C",
|
|
133
|
+
prn: `C${String(r.svid).padStart(2, "0")}`,
|
|
134
|
+
toc: sowOf(tocDate.getTime()),
|
|
135
|
+
tocDate,
|
|
136
|
+
toe: toeSec,
|
|
137
|
+
week: bdsWeek,
|
|
138
|
+
// Health from the same flags nibble as GPS (0 = healthy for the observed
|
|
139
|
+
// operational BeiDou sats); flags bit 0 is a set-on-all format marker,
|
|
140
|
+
// not SatH1, so it must not be used here.
|
|
141
|
+
svHealth: r.flags >>> 4 & 127,
|
|
142
|
+
...keplerCommon(r)
|
|
105
143
|
};
|
|
106
144
|
}
|
|
107
145
|
function parseTrimbleNav(data) {
|
|
@@ -116,13 +154,13 @@ function parseTrimbleNav(data) {
|
|
|
116
154
|
if (f.type !== RETSVDATA) continue;
|
|
117
155
|
const sub = data[f.payload];
|
|
118
156
|
retsvCounts[sub] = (retsvCounts[sub] ?? 0) + 1;
|
|
119
|
-
if (sub === SUB_GPS_EPHEMERIS && f.len >=
|
|
120
|
-
const eph = decodeGpsEphemeris(
|
|
157
|
+
if ((sub === SUB_GPS_EPHEMERIS || sub === SUB_BDS_EPHEMERIS) && f.len >= 176) {
|
|
158
|
+
const eph = sub === SUB_GPS_EPHEMERIS ? decodeGpsEphemeris(view, f.start) : decodeBdsEphemeris(view, f.start);
|
|
121
159
|
if (!eph) continue;
|
|
122
160
|
if (lastIode.get(eph.prn) === eph.iode) continue;
|
|
123
161
|
lastIode.set(eph.prn, eph.iode);
|
|
124
162
|
ephemerides.push(eph);
|
|
125
|
-
} else if (sub === SUB_ION_UTC && f.len >=
|
|
163
|
+
} else if (sub === SUB_ION_UTC && f.len >= 102) {
|
|
126
164
|
const p = f.start;
|
|
127
165
|
const alpha = [];
|
|
128
166
|
const beta = [];
|
package/dist/index.cjs
CHANGED
|
@@ -9590,68 +9590,106 @@ function* trimbleFrames(data, stats) {
|
|
|
9590
9590
|
|
|
9591
9591
|
// src/trimble/nav.ts
|
|
9592
9592
|
var GPS_EPOCH_MS14 = Date.UTC(1980, 0, 6);
|
|
9593
|
+
var BDT_EPOCH_MS4 = Date.UTC(2006, 0, 1);
|
|
9593
9594
|
var SEC_PER_WEEK10 = 7 * 86400;
|
|
9594
9595
|
var MS_PER_WEEK9 = SEC_PER_WEEK10 * 1e3;
|
|
9595
9596
|
var GPS_PI2 = 3.1415926535898;
|
|
9597
|
+
var BDS_WEEK_OFFSET = 1356;
|
|
9598
|
+
var BDS_LEAP_SEC = 14;
|
|
9596
9599
|
var gpsMs3 = (week, sec) => GPS_EPOCH_MS14 + week * MS_PER_WEEK9 + sec * 1e3;
|
|
9597
9600
|
var sowOf4 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK10;
|
|
9598
9601
|
var SUB_GPS_EPHEMERIS = 1;
|
|
9599
9602
|
var SUB_ION_UTC = 3;
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
|
|
9614
|
-
|
|
9615
|
-
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
|
|
9625
|
-
|
|
9626
|
-
|
|
9603
|
+
var SUB_BDS_EPHEMERIS = 21;
|
|
9604
|
+
function readKepler(view, base) {
|
|
9605
|
+
return {
|
|
9606
|
+
svid: view.getUint8(base + 5),
|
|
9607
|
+
week: view.getUint16(base + 6, false),
|
|
9608
|
+
iode: view.getUint8(base + 11),
|
|
9609
|
+
tocSec: view.getInt32(base + 16, false),
|
|
9610
|
+
toeSec: view.getUint32(base + 20, false),
|
|
9611
|
+
tgd: view.getFloat64(base + 24, false),
|
|
9612
|
+
af2: view.getFloat64(base + 32, false),
|
|
9613
|
+
af1: view.getFloat64(base + 40, false),
|
|
9614
|
+
af0: view.getFloat64(base + 48, false),
|
|
9615
|
+
crs: view.getFloat64(base + 56, false),
|
|
9616
|
+
deltaN: view.getFloat64(base + 64, false) * GPS_PI2,
|
|
9617
|
+
m0: view.getFloat64(base + 72, false) * GPS_PI2,
|
|
9618
|
+
cuc: view.getFloat64(base + 80, false) * GPS_PI2,
|
|
9619
|
+
e: view.getFloat64(base + 88, false),
|
|
9620
|
+
cus: view.getFloat64(base + 96, false) * GPS_PI2,
|
|
9621
|
+
sqrtA: view.getFloat64(base + 104, false),
|
|
9622
|
+
cic: view.getFloat64(base + 112, false) * GPS_PI2,
|
|
9623
|
+
omega0: view.getFloat64(base + 120, false) * GPS_PI2,
|
|
9624
|
+
cis: view.getFloat64(base + 128, false) * GPS_PI2,
|
|
9625
|
+
i0: view.getFloat64(base + 136, false) * GPS_PI2,
|
|
9626
|
+
crc: view.getFloat64(base + 144, false),
|
|
9627
|
+
omega: view.getFloat64(base + 152, false) * GPS_PI2,
|
|
9628
|
+
omegaDot: view.getFloat64(base + 160, false) * GPS_PI2,
|
|
9629
|
+
idot: view.getFloat64(base + 168, false) * GPS_PI2,
|
|
9630
|
+
flags: view.getUint32(base + 176, false)
|
|
9631
|
+
};
|
|
9632
|
+
}
|
|
9633
|
+
function keplerCommon(r) {
|
|
9634
|
+
return {
|
|
9635
|
+
af0: r.af0,
|
|
9636
|
+
af1: r.af1,
|
|
9637
|
+
af2: r.af2,
|
|
9638
|
+
iode: r.iode,
|
|
9639
|
+
crs: r.crs,
|
|
9640
|
+
deltaN: r.deltaN,
|
|
9641
|
+
m0: r.m0,
|
|
9642
|
+
cuc: r.cuc,
|
|
9643
|
+
e: r.e,
|
|
9644
|
+
cus: r.cus,
|
|
9645
|
+
sqrtA: r.sqrtA,
|
|
9646
|
+
cic: r.cic,
|
|
9647
|
+
omega0: r.omega0,
|
|
9648
|
+
cis: r.cis,
|
|
9649
|
+
i0: r.i0,
|
|
9650
|
+
crc: r.crc,
|
|
9651
|
+
omega: r.omega,
|
|
9652
|
+
omegaDot: r.omegaDot,
|
|
9653
|
+
idot: r.idot,
|
|
9654
|
+
tgd: r.tgd
|
|
9655
|
+
};
|
|
9656
|
+
}
|
|
9657
|
+
function decodeGpsEphemeris2(view, base) {
|
|
9658
|
+
const r = readKepler(view, base);
|
|
9659
|
+
if (r.svid < 1 || r.svid > 32) return null;
|
|
9660
|
+
const tocMs = gpsMs3(r.week, r.tocSec);
|
|
9627
9661
|
return {
|
|
9628
9662
|
system: "G",
|
|
9629
|
-
prn: `G${String(
|
|
9630
|
-
toc: sowOf4(
|
|
9631
|
-
tocDate: new Date(
|
|
9632
|
-
|
|
9633
|
-
|
|
9634
|
-
|
|
9635
|
-
|
|
9636
|
-
|
|
9637
|
-
|
|
9638
|
-
|
|
9639
|
-
|
|
9640
|
-
|
|
9641
|
-
|
|
9642
|
-
|
|
9643
|
-
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
|
|
9649
|
-
|
|
9650
|
-
|
|
9651
|
-
|
|
9652
|
-
|
|
9653
|
-
|
|
9654
|
-
|
|
9663
|
+
prn: `G${String(r.svid).padStart(2, "0")}`,
|
|
9664
|
+
toc: sowOf4(tocMs),
|
|
9665
|
+
tocDate: new Date(tocMs),
|
|
9666
|
+
toe: r.toeSec,
|
|
9667
|
+
week: r.week,
|
|
9668
|
+
svHealth: r.flags >>> 4 & 127,
|
|
9669
|
+
...keplerCommon(r)
|
|
9670
|
+
};
|
|
9671
|
+
}
|
|
9672
|
+
function decodeBdsEphemeris3(view, base) {
|
|
9673
|
+
const r = readKepler(view, base);
|
|
9674
|
+
if (r.svid < 1 || r.svid > 63) return null;
|
|
9675
|
+
const bdsWeek = r.week - BDS_WEEK_OFFSET;
|
|
9676
|
+
const tocSec = r.tocSec - BDS_LEAP_SEC;
|
|
9677
|
+
const toeSec = r.toeSec - BDS_LEAP_SEC;
|
|
9678
|
+
const tocDate = new Date(
|
|
9679
|
+
BDT_EPOCH_MS4 + bdsWeek * MS_PER_WEEK9 + tocSec * 1e3
|
|
9680
|
+
);
|
|
9681
|
+
return {
|
|
9682
|
+
system: "C",
|
|
9683
|
+
prn: `C${String(r.svid).padStart(2, "0")}`,
|
|
9684
|
+
toc: sowOf4(tocDate.getTime()),
|
|
9685
|
+
tocDate,
|
|
9686
|
+
toe: toeSec,
|
|
9687
|
+
week: bdsWeek,
|
|
9688
|
+
// Health from the same flags nibble as GPS (0 = healthy for the observed
|
|
9689
|
+
// operational BeiDou sats); flags bit 0 is a set-on-all format marker,
|
|
9690
|
+
// not SatH1, so it must not be used here.
|
|
9691
|
+
svHealth: r.flags >>> 4 & 127,
|
|
9692
|
+
...keplerCommon(r)
|
|
9655
9693
|
};
|
|
9656
9694
|
}
|
|
9657
9695
|
function parseTrimbleNav(data) {
|
|
@@ -9666,13 +9704,13 @@ function parseTrimbleNav(data) {
|
|
|
9666
9704
|
if (f.type !== RETSVDATA) continue;
|
|
9667
9705
|
const sub = data[f.payload];
|
|
9668
9706
|
retsvCounts[sub] = (retsvCounts[sub] ?? 0) + 1;
|
|
9669
|
-
if (sub === SUB_GPS_EPHEMERIS && f.len >=
|
|
9670
|
-
const eph = decodeGpsEphemeris2(
|
|
9707
|
+
if ((sub === SUB_GPS_EPHEMERIS || sub === SUB_BDS_EPHEMERIS) && f.len >= 176) {
|
|
9708
|
+
const eph = sub === SUB_GPS_EPHEMERIS ? decodeGpsEphemeris2(view, f.start) : decodeBdsEphemeris3(view, f.start);
|
|
9671
9709
|
if (!eph) continue;
|
|
9672
9710
|
if (lastIode.get(eph.prn) === eph.iode) continue;
|
|
9673
9711
|
lastIode.set(eph.prn, eph.iode);
|
|
9674
9712
|
ephemerides.push(eph);
|
|
9675
|
-
} else if (sub === SUB_ION_UTC && f.len >=
|
|
9713
|
+
} else if (sub === SUB_ION_UTC && f.len >= 102) {
|
|
9676
9714
|
const p = f.start;
|
|
9677
9715
|
const alpha = [];
|
|
9678
9716
|
const beta = [];
|
|
@@ -10076,7 +10114,7 @@ function* binexRecords(data, view, stats) {
|
|
|
10076
10114
|
// src/binex/nav.ts
|
|
10077
10115
|
var GPS_EPOCH_MS16 = Date.UTC(1980, 0, 6);
|
|
10078
10116
|
var GLO_DAY0_MS = Date.UTC(1980, 0, 1);
|
|
10079
|
-
var
|
|
10117
|
+
var BDT_EPOCH_MS5 = Date.UTC(2006, 0, 1);
|
|
10080
10118
|
var SEC_PER_WEEK11 = 7 * 86400;
|
|
10081
10119
|
var MS_PER_WEEK11 = SEC_PER_WEEK11 * 1e3;
|
|
10082
10120
|
var SC2RAD = GPS_PI;
|
|
@@ -10245,7 +10283,7 @@ function decodeBeidou(view, p, le) {
|
|
|
10245
10283
|
const iode = flag1 >> 6 & 31;
|
|
10246
10284
|
const svHealth = flag1 & 1;
|
|
10247
10285
|
const tgd = bdsTgd(flag2 >> 4);
|
|
10248
|
-
const tocDate = new Date(
|
|
10286
|
+
const tocDate = new Date(BDT_EPOCH_MS5 + week * MS_PER_WEEK11 + toes * 1e3);
|
|
10249
10287
|
return {
|
|
10250
10288
|
system: "C",
|
|
10251
10289
|
prn: `C${two5(prn)}`,
|
|
@@ -10713,13 +10751,13 @@ var GM_GPS = 3986005e8;
|
|
|
10713
10751
|
var GM_GAL = 3986004418e5;
|
|
10714
10752
|
var GM_BDS = 3986004418e5;
|
|
10715
10753
|
var GPS_EPOCH_MS18 = Date.UTC(1980, 0, 6);
|
|
10716
|
-
var
|
|
10754
|
+
var BDT_EPOCH_MS6 = Date.UTC(2006, 0, 1);
|
|
10717
10755
|
var WEEK_MS = 6048e5;
|
|
10718
10756
|
var BDT_MINUS_GPST_MS = 14e3;
|
|
10719
10757
|
var BDS_GEO_PRNS = /* @__PURE__ */ new Set([1, 2, 3, 4, 5, 59, 60, 61, 62, 63]);
|
|
10720
10758
|
function almanacEpochMs(alm) {
|
|
10721
10759
|
if (alm.system === "C") {
|
|
10722
|
-
return
|
|
10760
|
+
return BDT_EPOCH_MS6 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3 + BDT_MINUS_GPST_MS;
|
|
10723
10761
|
}
|
|
10724
10762
|
return GPS_EPOCH_MS18 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3;
|
|
10725
10763
|
}
|
package/dist/index.js
CHANGED
package/dist/trimble.cjs
CHANGED
|
@@ -68,68 +68,106 @@ function* trimbleFrames(data, stats) {
|
|
|
68
68
|
|
|
69
69
|
// src/trimble/nav.ts
|
|
70
70
|
var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
|
|
71
|
+
var BDT_EPOCH_MS = Date.UTC(2006, 0, 1);
|
|
71
72
|
var SEC_PER_WEEK = 7 * 86400;
|
|
72
73
|
var MS_PER_WEEK = SEC_PER_WEEK * 1e3;
|
|
73
74
|
var GPS_PI = 3.1415926535898;
|
|
75
|
+
var BDS_WEEK_OFFSET = 1356;
|
|
76
|
+
var BDS_LEAP_SEC = 14;
|
|
74
77
|
var gpsMs = (week, sec) => GPS_EPOCH_MS + week * MS_PER_WEEK + sec * 1e3;
|
|
75
78
|
var sowOf = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK;
|
|
76
79
|
var SUB_GPS_EPHEMERIS = 1;
|
|
77
80
|
var SUB_ION_UTC = 3;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
81
|
+
var SUB_BDS_EPHEMERIS = 21;
|
|
82
|
+
function readKepler(view, base) {
|
|
83
|
+
return {
|
|
84
|
+
svid: view.getUint8(base + 5),
|
|
85
|
+
week: view.getUint16(base + 6, false),
|
|
86
|
+
iode: view.getUint8(base + 11),
|
|
87
|
+
tocSec: view.getInt32(base + 16, false),
|
|
88
|
+
toeSec: view.getUint32(base + 20, false),
|
|
89
|
+
tgd: view.getFloat64(base + 24, false),
|
|
90
|
+
af2: view.getFloat64(base + 32, false),
|
|
91
|
+
af1: view.getFloat64(base + 40, false),
|
|
92
|
+
af0: view.getFloat64(base + 48, false),
|
|
93
|
+
crs: view.getFloat64(base + 56, false),
|
|
94
|
+
deltaN: view.getFloat64(base + 64, false) * GPS_PI,
|
|
95
|
+
m0: view.getFloat64(base + 72, false) * GPS_PI,
|
|
96
|
+
cuc: view.getFloat64(base + 80, false) * GPS_PI,
|
|
97
|
+
e: view.getFloat64(base + 88, false),
|
|
98
|
+
cus: view.getFloat64(base + 96, false) * GPS_PI,
|
|
99
|
+
sqrtA: view.getFloat64(base + 104, false),
|
|
100
|
+
cic: view.getFloat64(base + 112, false) * GPS_PI,
|
|
101
|
+
omega0: view.getFloat64(base + 120, false) * GPS_PI,
|
|
102
|
+
cis: view.getFloat64(base + 128, false) * GPS_PI,
|
|
103
|
+
i0: view.getFloat64(base + 136, false) * GPS_PI,
|
|
104
|
+
crc: view.getFloat64(base + 144, false),
|
|
105
|
+
omega: view.getFloat64(base + 152, false) * GPS_PI,
|
|
106
|
+
omegaDot: view.getFloat64(base + 160, false) * GPS_PI,
|
|
107
|
+
idot: view.getFloat64(base + 168, false) * GPS_PI,
|
|
108
|
+
flags: view.getUint32(base + 176, false)
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function keplerCommon(r) {
|
|
112
|
+
return {
|
|
113
|
+
af0: r.af0,
|
|
114
|
+
af1: r.af1,
|
|
115
|
+
af2: r.af2,
|
|
116
|
+
iode: r.iode,
|
|
117
|
+
crs: r.crs,
|
|
118
|
+
deltaN: r.deltaN,
|
|
119
|
+
m0: r.m0,
|
|
120
|
+
cuc: r.cuc,
|
|
121
|
+
e: r.e,
|
|
122
|
+
cus: r.cus,
|
|
123
|
+
sqrtA: r.sqrtA,
|
|
124
|
+
cic: r.cic,
|
|
125
|
+
omega0: r.omega0,
|
|
126
|
+
cis: r.cis,
|
|
127
|
+
i0: r.i0,
|
|
128
|
+
crc: r.crc,
|
|
129
|
+
omega: r.omega,
|
|
130
|
+
omegaDot: r.omegaDot,
|
|
131
|
+
idot: r.idot,
|
|
132
|
+
tgd: r.tgd
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function decodeGpsEphemeris(view, base) {
|
|
136
|
+
const r = readKepler(view, base);
|
|
137
|
+
if (r.svid < 1 || r.svid > 32) return null;
|
|
138
|
+
const tocMs = gpsMs(r.week, r.tocSec);
|
|
105
139
|
return {
|
|
106
140
|
system: "G",
|
|
107
|
-
prn: `G${String(
|
|
108
|
-
toc: sowOf(
|
|
109
|
-
tocDate: new Date(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
141
|
+
prn: `G${String(r.svid).padStart(2, "0")}`,
|
|
142
|
+
toc: sowOf(tocMs),
|
|
143
|
+
tocDate: new Date(tocMs),
|
|
144
|
+
toe: r.toeSec,
|
|
145
|
+
week: r.week,
|
|
146
|
+
svHealth: r.flags >>> 4 & 127,
|
|
147
|
+
...keplerCommon(r)
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function decodeBdsEphemeris(view, base) {
|
|
151
|
+
const r = readKepler(view, base);
|
|
152
|
+
if (r.svid < 1 || r.svid > 63) return null;
|
|
153
|
+
const bdsWeek = r.week - BDS_WEEK_OFFSET;
|
|
154
|
+
const tocSec = r.tocSec - BDS_LEAP_SEC;
|
|
155
|
+
const toeSec = r.toeSec - BDS_LEAP_SEC;
|
|
156
|
+
const tocDate = new Date(
|
|
157
|
+
BDT_EPOCH_MS + bdsWeek * MS_PER_WEEK + tocSec * 1e3
|
|
158
|
+
);
|
|
159
|
+
return {
|
|
160
|
+
system: "C",
|
|
161
|
+
prn: `C${String(r.svid).padStart(2, "0")}`,
|
|
162
|
+
toc: sowOf(tocDate.getTime()),
|
|
163
|
+
tocDate,
|
|
164
|
+
toe: toeSec,
|
|
165
|
+
week: bdsWeek,
|
|
166
|
+
// Health from the same flags nibble as GPS (0 = healthy for the observed
|
|
167
|
+
// operational BeiDou sats); flags bit 0 is a set-on-all format marker,
|
|
168
|
+
// not SatH1, so it must not be used here.
|
|
169
|
+
svHealth: r.flags >>> 4 & 127,
|
|
170
|
+
...keplerCommon(r)
|
|
133
171
|
};
|
|
134
172
|
}
|
|
135
173
|
function parseTrimbleNav(data) {
|
|
@@ -144,13 +182,13 @@ function parseTrimbleNav(data) {
|
|
|
144
182
|
if (f.type !== RETSVDATA) continue;
|
|
145
183
|
const sub = data[f.payload];
|
|
146
184
|
retsvCounts[sub] = (retsvCounts[sub] ?? 0) + 1;
|
|
147
|
-
if (sub === SUB_GPS_EPHEMERIS && f.len >=
|
|
148
|
-
const eph = decodeGpsEphemeris(
|
|
185
|
+
if ((sub === SUB_GPS_EPHEMERIS || sub === SUB_BDS_EPHEMERIS) && f.len >= 176) {
|
|
186
|
+
const eph = sub === SUB_GPS_EPHEMERIS ? decodeGpsEphemeris(view, f.start) : decodeBdsEphemeris(view, f.start);
|
|
149
187
|
if (!eph) continue;
|
|
150
188
|
if (lastIode.get(eph.prn) === eph.iode) continue;
|
|
151
189
|
lastIode.set(eph.prn, eph.iode);
|
|
152
190
|
ephemerides.push(eph);
|
|
153
|
-
} else if (sub === SUB_ION_UTC && f.len >=
|
|
191
|
+
} else if (sub === SUB_ION_UTC && f.len >= 102) {
|
|
154
192
|
const p = f.start;
|
|
155
193
|
const alpha = [];
|
|
156
194
|
const beta = [];
|
package/dist/trimble.d.cts
CHANGED
|
@@ -25,23 +25,25 @@ declare function trimbleFrames(data: Uint8Array, stats: {
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Trimble RT17/RT27 navigation-message decoding: RETSVDATA (0x55)
|
|
28
|
-
* GPS ephemeris (subtype 1) and ION / UTC
|
|
28
|
+
* GPS ephemeris (subtype 1), BeiDou ephemeris (subtype 21) and ION / UTC
|
|
29
|
+
* data (subtype 3).
|
|
29
30
|
*
|
|
30
|
-
*
|
|
31
|
+
* The GPS path is ported field-for-field from RTKLIB's `src/rcv/rt17.c`
|
|
31
32
|
* (`decode_gps_ephemeris` / `decode_ion_utc_data`, tomojitakasu/RTKLIB,
|
|
32
33
|
* Copyright (C) 2014 D. A. Cook / T. Takasu, BSD-2-Clause). All scalar
|
|
33
34
|
* fields are big-endian; the semicircle angular/harmonic fields are
|
|
34
|
-
* scaled by π to radians, exactly as RTKLIB does.
|
|
35
|
+
* scaled by π to radians, exactly as RTKLIB does. BeiDou (subtype 21)
|
|
36
|
+
* reuses the identical 176-byte Keplerian struct — established from a
|
|
37
|
+
* real DLF100NLD1 capture (√a ≈ 5282.6 m^½ ⇒ BeiDou MEO, i₀ ≈ 55°) — with
|
|
38
|
+
* the GPS→BDT time-scale conversion (week − 1356, SOW − 14 s) applied so
|
|
39
|
+
* the record matches `parseSbfNav`'s BDSNav output.
|
|
35
40
|
*
|
|
36
41
|
* Output records mirror what `parseNavFile` produces for the equivalent
|
|
37
|
-
* RINEX 3
|
|
38
|
-
*
|
|
42
|
+
* RINEX 3 navigation record and match the NovAtel/SBF ephemeris paths
|
|
43
|
+
* (GPS: GPS-scale `tocDate`; BeiDou: naive-BDT `tocDate`; angles in rad).
|
|
39
44
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* here (see the module note in the package README / decoder report).
|
|
43
|
-
* This path is validated against synthetic records only: the DLF100
|
|
44
|
-
* ALLOY capture carried GLONASS/BeiDou subtypes but no GPS ephemeris.
|
|
45
|
+
* Still not decoded: the GLONASS/Galileo/QZSS ephemeris and almanac
|
|
46
|
+
* subtypes (RETSVDATA 9/11/13/23/27 on this stream).
|
|
45
47
|
*/
|
|
46
48
|
|
|
47
49
|
interface TrimbleNavResult {
|
package/dist/trimble.d.ts
CHANGED
|
@@ -25,23 +25,25 @@ declare function trimbleFrames(data: Uint8Array, stats: {
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Trimble RT17/RT27 navigation-message decoding: RETSVDATA (0x55)
|
|
28
|
-
* GPS ephemeris (subtype 1) and ION / UTC
|
|
28
|
+
* GPS ephemeris (subtype 1), BeiDou ephemeris (subtype 21) and ION / UTC
|
|
29
|
+
* data (subtype 3).
|
|
29
30
|
*
|
|
30
|
-
*
|
|
31
|
+
* The GPS path is ported field-for-field from RTKLIB's `src/rcv/rt17.c`
|
|
31
32
|
* (`decode_gps_ephemeris` / `decode_ion_utc_data`, tomojitakasu/RTKLIB,
|
|
32
33
|
* Copyright (C) 2014 D. A. Cook / T. Takasu, BSD-2-Clause). All scalar
|
|
33
34
|
* fields are big-endian; the semicircle angular/harmonic fields are
|
|
34
|
-
* scaled by π to radians, exactly as RTKLIB does.
|
|
35
|
+
* scaled by π to radians, exactly as RTKLIB does. BeiDou (subtype 21)
|
|
36
|
+
* reuses the identical 176-byte Keplerian struct — established from a
|
|
37
|
+
* real DLF100NLD1 capture (√a ≈ 5282.6 m^½ ⇒ BeiDou MEO, i₀ ≈ 55°) — with
|
|
38
|
+
* the GPS→BDT time-scale conversion (week − 1356, SOW − 14 s) applied so
|
|
39
|
+
* the record matches `parseSbfNav`'s BDSNav output.
|
|
35
40
|
*
|
|
36
41
|
* Output records mirror what `parseNavFile` produces for the equivalent
|
|
37
|
-
* RINEX 3
|
|
38
|
-
*
|
|
42
|
+
* RINEX 3 navigation record and match the NovAtel/SBF ephemeris paths
|
|
43
|
+
* (GPS: GPS-scale `tocDate`; BeiDou: naive-BDT `tocDate`; angles in rad).
|
|
39
44
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* here (see the module note in the package README / decoder report).
|
|
43
|
-
* This path is validated against synthetic records only: the DLF100
|
|
44
|
-
* ALLOY capture carried GLONASS/BeiDou subtypes but no GPS ephemeris.
|
|
45
|
+
* Still not decoded: the GLONASS/Galileo/QZSS ephemeris and almanac
|
|
46
|
+
* subtypes (RETSVDATA 9/11/13/23/27 on this stream).
|
|
45
47
|
*/
|
|
46
48
|
|
|
47
49
|
interface TrimbleNavResult {
|
package/dist/trimble.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gnss-js",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.40.0",
|
|
4
4
|
"description": "Comprehensive GNSS library for JavaScript — time scales, coordinates, RINEX parsing, RTCM3 decoding, orbit computation, and signal analysis",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|