gnss-js 1.14.1 → 1.15.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-YIHO74OS.js → chunk-BEQSEJMU.js} +390 -67
- package/dist/{chunk-SWKWJEGY.js → chunk-I4UV45NT.js} +269 -15
- package/dist/index.cjs +671 -96
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +15 -3
- package/dist/novatel.cjs +357 -14
- package/dist/novatel.d.cts +69 -1
- package/dist/novatel.d.ts +69 -1
- package/dist/novatel.js +11 -1
- package/dist/sbf.cjs +478 -68
- package/dist/sbf.d.cts +138 -1
- package/dist/sbf.d.ts +138 -1
- package/dist/sbf.js +9 -3
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -10,8 +10,8 @@ export { E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHe
|
|
|
10
10
|
export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.cjs';
|
|
11
11
|
export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.cjs';
|
|
12
12
|
export { UbxMeasurement, UbxParseResult, UbxRawxEpoch, parseUbxRawx } from './ubx.cjs';
|
|
13
|
-
export { SbfMeasEpoch, SbfMeasurement, SbfParseResult, parseSbfMeas } from './sbf.cjs';
|
|
14
|
-
export { NovatelEpoch, NovatelMeasurement, NovatelParseResult, parseNovatelRange } from './novatel.cjs';
|
|
13
|
+
export { SbfAlmanac, SbfAlmanacResult, SbfGlonassAlmanac, SbfKeplerAlmanac, SbfMeasEpoch, SbfMeasurement, SbfNavResult, SbfParseResult, parseSbfAlmanac, parseSbfMeas, parseSbfNav } from './sbf.cjs';
|
|
14
|
+
export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelRange } from './novatel.cjs';
|
|
15
15
|
export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.cjs';
|
|
16
16
|
export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.cjs';
|
|
17
17
|
export { KlobucharCoeffs, SppOptions, SppSolution, ionoFree, klobucharDelay, satClockCorrection, solveSpp } from './positioning.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ export { E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHe
|
|
|
10
10
|
export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.js';
|
|
11
11
|
export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.js';
|
|
12
12
|
export { UbxMeasurement, UbxParseResult, UbxRawxEpoch, parseUbxRawx } from './ubx.js';
|
|
13
|
-
export { SbfMeasEpoch, SbfMeasurement, SbfParseResult, parseSbfMeas } from './sbf.js';
|
|
14
|
-
export { NovatelEpoch, NovatelMeasurement, NovatelParseResult, parseNovatelRange } from './novatel.js';
|
|
13
|
+
export { SbfAlmanac, SbfAlmanacResult, SbfGlonassAlmanac, SbfKeplerAlmanac, SbfMeasEpoch, SbfMeasurement, SbfNavResult, SbfParseResult, parseSbfAlmanac, parseSbfMeas, parseSbfNav } from './sbf.js';
|
|
14
|
+
export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelRange } from './novatel.js';
|
|
15
15
|
export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.js';
|
|
16
16
|
export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.js';
|
|
17
17
|
export { KlobucharCoeffs, SppOptions, SppSolution, ionoFree, klobucharDelay, satClockCorrection, solveSpp } from './positioning.js';
|
package/dist/index.js
CHANGED
|
@@ -37,11 +37,17 @@ import {
|
|
|
37
37
|
parseUbxRawx
|
|
38
38
|
} from "./chunk-5IXK25MX.js";
|
|
39
39
|
import {
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
parseSbfAlmanac,
|
|
41
|
+
parseSbfMeas,
|
|
42
|
+
parseSbfNav
|
|
43
|
+
} from "./chunk-BEQSEJMU.js";
|
|
42
44
|
import {
|
|
45
|
+
OEM4_HLEN,
|
|
46
|
+
crc32,
|
|
47
|
+
oem4Frames,
|
|
48
|
+
parseNovatelNav,
|
|
43
49
|
parseNovatelRange
|
|
44
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-I4UV45NT.js";
|
|
45
51
|
import {
|
|
46
52
|
connectToMountpoint,
|
|
47
53
|
fetchSourcetable,
|
|
@@ -330,6 +336,7 @@ export {
|
|
|
330
336
|
MILLISECONDS_IN_WEEK,
|
|
331
337
|
MILLISECONDS_TT_TAI,
|
|
332
338
|
MultipathAccumulator,
|
|
339
|
+
OEM4_HLEN,
|
|
333
340
|
OMEGA_E,
|
|
334
341
|
REFERENCE_FRAMES,
|
|
335
342
|
RINEX_CODES,
|
|
@@ -373,6 +380,7 @@ export {
|
|
|
373
380
|
computeVisibility,
|
|
374
381
|
computeVisibilityFromPositions,
|
|
375
382
|
connectToMountpoint,
|
|
383
|
+
crc32,
|
|
376
384
|
createGzipLineSink,
|
|
377
385
|
createStationMeta,
|
|
378
386
|
createStreamStats,
|
|
@@ -462,6 +470,7 @@ export {
|
|
|
462
470
|
msmEpochToDate,
|
|
463
471
|
navTimesFromEph,
|
|
464
472
|
nmeaCoordToDecimal,
|
|
473
|
+
oem4Frames,
|
|
465
474
|
padL,
|
|
466
475
|
padR,
|
|
467
476
|
parseAntex,
|
|
@@ -469,9 +478,12 @@ export {
|
|
|
469
478
|
parseIonex,
|
|
470
479
|
parseNavFile,
|
|
471
480
|
parseNmeaFile,
|
|
481
|
+
parseNovatelNav,
|
|
472
482
|
parseNovatelRange,
|
|
473
483
|
parseRinexStream,
|
|
484
|
+
parseSbfAlmanac,
|
|
474
485
|
parseSbfMeas,
|
|
486
|
+
parseSbfNav,
|
|
475
487
|
parseSinexBiasDcb,
|
|
476
488
|
parseSourcetable,
|
|
477
489
|
parseSp3,
|
package/dist/novatel.cjs
CHANGED
|
@@ -20,15 +20,364 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/novatel/index.ts
|
|
21
21
|
var novatel_exports = {};
|
|
22
22
|
__export(novatel_exports, {
|
|
23
|
+
OEM4_HLEN: () => OEM4_HLEN,
|
|
24
|
+
crc32: () => crc32,
|
|
25
|
+
oem4Frames: () => oem4Frames,
|
|
26
|
+
parseNovatelNav: () => parseNovatelNav,
|
|
23
27
|
parseNovatelRange: () => parseNovatelRange
|
|
24
28
|
});
|
|
25
29
|
module.exports = __toCommonJS(novatel_exports);
|
|
30
|
+
|
|
31
|
+
// src/novatel/frame.ts
|
|
32
|
+
var OEM4_HLEN = 28;
|
|
33
|
+
function crc32(data, start, len) {
|
|
34
|
+
let crc = 0;
|
|
35
|
+
for (let i = start; i < start + len; i++) {
|
|
36
|
+
crc ^= data[i];
|
|
37
|
+
for (let j = 0; j < 8; j++) {
|
|
38
|
+
crc = crc & 1 ? crc >>> 1 ^ 3988292384 : crc >>> 1;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return crc >>> 0;
|
|
42
|
+
}
|
|
43
|
+
function* oem4Frames(data, view, stats) {
|
|
44
|
+
let i = 0;
|
|
45
|
+
while (i + OEM4_HLEN + 4 <= data.length) {
|
|
46
|
+
if (data[i] !== 170 || data[i + 1] !== 68 || data[i + 2] !== 18) {
|
|
47
|
+
i++;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const hlen = data[i + 3];
|
|
51
|
+
const msgLen = view.getUint16(i + 8, true);
|
|
52
|
+
const total = hlen + msgLen + 4;
|
|
53
|
+
if (hlen < OEM4_HLEN || i + total > data.length) {
|
|
54
|
+
i++;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (crc32(data, i, hlen + msgLen) !== view.getUint32(i + hlen + msgLen, true)) {
|
|
58
|
+
stats.badCrc++;
|
|
59
|
+
i++;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
yield {
|
|
63
|
+
id: view.getUint16(i + 4, true),
|
|
64
|
+
start: i,
|
|
65
|
+
payload: i + hlen,
|
|
66
|
+
msgLen,
|
|
67
|
+
binary: (data[i + 6] >> 4 & 3) === 0,
|
|
68
|
+
week: view.getUint16(i + 14, true),
|
|
69
|
+
towMs: view.getUint32(i + 16, true)
|
|
70
|
+
};
|
|
71
|
+
i += total;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/navbits/index.ts
|
|
76
|
+
var GPS_PI = 3.1415926535898;
|
|
26
77
|
var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
|
|
78
|
+
var SEC_PER_WEEK = 7 * 86400;
|
|
79
|
+
function getBitU(buff, pos, len) {
|
|
80
|
+
let bits = 0;
|
|
81
|
+
for (let i = pos; i < pos + len; i++) {
|
|
82
|
+
bits = bits * 2 + (buff[i >> 3] >> 7 - (i & 7) & 1);
|
|
83
|
+
}
|
|
84
|
+
return bits;
|
|
85
|
+
}
|
|
86
|
+
function getBitS(buff, pos, len) {
|
|
87
|
+
const bits = getBitU(buff, pos, len);
|
|
88
|
+
if (len <= 0 || bits < 2 ** (len - 1)) return bits;
|
|
89
|
+
return bits - 2 ** len;
|
|
90
|
+
}
|
|
91
|
+
function decodeGpsLnavFrame(subframes, opts = {}) {
|
|
92
|
+
if (subframes.length < 90) return null;
|
|
93
|
+
const b = subframes;
|
|
94
|
+
let i = 24;
|
|
95
|
+
const tow1 = getBitU(b, i, 17) * 6;
|
|
96
|
+
i += 17 + 2;
|
|
97
|
+
const id1 = getBitU(b, i, 3);
|
|
98
|
+
i += 3 + 2;
|
|
99
|
+
const week10 = getBitU(b, i, 10);
|
|
100
|
+
i += 10;
|
|
101
|
+
i += 2;
|
|
102
|
+
i += 4;
|
|
103
|
+
const svHealth = getBitU(b, i, 6);
|
|
104
|
+
i += 6;
|
|
105
|
+
const iodc0 = getBitU(b, i, 2);
|
|
106
|
+
i += 2;
|
|
107
|
+
i += 1 + 87;
|
|
108
|
+
const tgdRaw = getBitS(b, i, 8);
|
|
109
|
+
i += 8;
|
|
110
|
+
const iodc1 = getBitU(b, i, 8);
|
|
111
|
+
i += 8;
|
|
112
|
+
const tocSec = getBitU(b, i, 16) * 16;
|
|
113
|
+
i += 16;
|
|
114
|
+
const af2 = getBitS(b, i, 8) * 2 ** -55;
|
|
115
|
+
i += 8;
|
|
116
|
+
const af1 = getBitS(b, i, 16) * 2 ** -43;
|
|
117
|
+
i += 16;
|
|
118
|
+
const af0 = getBitS(b, i, 22) * 2 ** -31;
|
|
119
|
+
i = 240 + 24;
|
|
120
|
+
i += 17 + 2;
|
|
121
|
+
const id2 = getBitU(b, i, 3);
|
|
122
|
+
i += 3 + 2;
|
|
123
|
+
const iode = getBitU(b, i, 8);
|
|
124
|
+
i += 8;
|
|
125
|
+
const crs = getBitS(b, i, 16) * 2 ** -5;
|
|
126
|
+
i += 16;
|
|
127
|
+
const deltaN = getBitS(b, i, 16) * 2 ** -43 * GPS_PI;
|
|
128
|
+
i += 16;
|
|
129
|
+
const m0 = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
130
|
+
i += 32;
|
|
131
|
+
const cuc = getBitS(b, i, 16) * 2 ** -29;
|
|
132
|
+
i += 16;
|
|
133
|
+
const e = getBitU(b, i, 32) * 2 ** -33;
|
|
134
|
+
i += 32;
|
|
135
|
+
const cus = getBitS(b, i, 16) * 2 ** -29;
|
|
136
|
+
i += 16;
|
|
137
|
+
const sqrtA = getBitU(b, i, 32) * 2 ** -19;
|
|
138
|
+
i += 32;
|
|
139
|
+
const toes = getBitU(b, i, 16) * 16;
|
|
140
|
+
i = 480 + 24;
|
|
141
|
+
i += 17 + 2;
|
|
142
|
+
const id3 = getBitU(b, i, 3);
|
|
143
|
+
i += 3 + 2;
|
|
144
|
+
const cic = getBitS(b, i, 16) * 2 ** -29;
|
|
145
|
+
i += 16;
|
|
146
|
+
const omega0 = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
147
|
+
i += 32;
|
|
148
|
+
const cis = getBitS(b, i, 16) * 2 ** -29;
|
|
149
|
+
i += 16;
|
|
150
|
+
const i0 = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
151
|
+
i += 32;
|
|
152
|
+
const crc = getBitS(b, i, 16) * 2 ** -5;
|
|
153
|
+
i += 16;
|
|
154
|
+
const omega = getBitS(b, i, 32) * 2 ** -31 * GPS_PI;
|
|
155
|
+
i += 32;
|
|
156
|
+
const omegaDot = getBitS(b, i, 24) * 2 ** -43 * GPS_PI;
|
|
157
|
+
i += 24;
|
|
158
|
+
const iode3 = getBitU(b, i, 8);
|
|
159
|
+
i += 8;
|
|
160
|
+
const idot = getBitS(b, i, 14) * 2 ** -43 * GPS_PI;
|
|
161
|
+
const iodc = iodc0 * 256 + iodc1;
|
|
162
|
+
if (id1 !== 1 || id2 !== 2 || id3 !== 3) return null;
|
|
163
|
+
if (iode3 !== iode || iode !== (iodc & 255)) return null;
|
|
164
|
+
const ref = opts.refWeek ?? Math.floor((Date.now() - GPS_EPOCH_MS) / 1e3 / SEC_PER_WEEK);
|
|
165
|
+
let week = week10 + 1024 * Math.round((ref - week10) / 1024);
|
|
166
|
+
if (toes < tow1 - 302400) week++;
|
|
167
|
+
else if (toes > tow1 + 302400) week--;
|
|
168
|
+
const prn = opts.prn ?? "G00";
|
|
169
|
+
const tocDate = new Date(
|
|
170
|
+
GPS_EPOCH_MS + (week * SEC_PER_WEEK + tocSec) * 1e3
|
|
171
|
+
);
|
|
172
|
+
return {
|
|
173
|
+
system: prn[0] === "J" ? "J" : "G",
|
|
174
|
+
prn,
|
|
175
|
+
tocDate,
|
|
176
|
+
// Same seconds-of-week convention as parseNavFile (rinex/nav.ts).
|
|
177
|
+
toc: tocDate.getTime() / 1e3 % SEC_PER_WEEK,
|
|
178
|
+
af0,
|
|
179
|
+
af1,
|
|
180
|
+
af2,
|
|
181
|
+
iode,
|
|
182
|
+
crs,
|
|
183
|
+
deltaN,
|
|
184
|
+
m0,
|
|
185
|
+
cuc,
|
|
186
|
+
e,
|
|
187
|
+
cus,
|
|
188
|
+
sqrtA,
|
|
189
|
+
toe: toes,
|
|
190
|
+
cic,
|
|
191
|
+
omega0,
|
|
192
|
+
cis,
|
|
193
|
+
i0,
|
|
194
|
+
crc,
|
|
195
|
+
omega,
|
|
196
|
+
omegaDot,
|
|
197
|
+
idot,
|
|
198
|
+
week,
|
|
199
|
+
svHealth,
|
|
200
|
+
tgd: tgdRaw === -128 ? 0 : tgdRaw * 2 ** -31
|
|
201
|
+
// IS-GPS-200: -128 reserved
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// src/constants/time.ts
|
|
206
|
+
var MILLISECONDS_IN_SECOND = 1e3;
|
|
207
|
+
var MILLISECONDS_GPS_TAI = 19e3;
|
|
208
|
+
var START_NTP_TIME = /* @__PURE__ */ new Date("1900-01-01T00:00:00Z");
|
|
209
|
+
|
|
210
|
+
// src/time/gnss.ts
|
|
211
|
+
function getTaiDate(date) {
|
|
212
|
+
return new Date(date.getTime() + MILLISECONDS_GPS_TAI);
|
|
213
|
+
}
|
|
214
|
+
function getNtpTime(date) {
|
|
215
|
+
return getTaiDate(date).getTime() - START_NTP_TIME.getTime();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// src/time/utc.ts
|
|
219
|
+
var LEAP_SECONDS_TABLE = [
|
|
220
|
+
[3692217600, 37],
|
|
221
|
+
// 1 Jan 2017
|
|
222
|
+
[3644697600, 36],
|
|
223
|
+
// 1 Jul 2015
|
|
224
|
+
[3550089600, 35],
|
|
225
|
+
// 1 Jul 2012
|
|
226
|
+
[3439756800, 34],
|
|
227
|
+
// 1 Jan 2009
|
|
228
|
+
[3345062400, 33],
|
|
229
|
+
// 1 Jan 2006
|
|
230
|
+
[3124137600, 32],
|
|
231
|
+
// 1 Jan 1999
|
|
232
|
+
[3076704e3, 31],
|
|
233
|
+
// 1 Jul 1997
|
|
234
|
+
[3029443200, 30],
|
|
235
|
+
// 1 Jan 1996
|
|
236
|
+
[2982009600, 29],
|
|
237
|
+
// 1 Jul 1994
|
|
238
|
+
[2950473600, 28],
|
|
239
|
+
// 1 Jul 1993
|
|
240
|
+
[2918937600, 27],
|
|
241
|
+
// 1 Jul 1992
|
|
242
|
+
[2871676800, 26],
|
|
243
|
+
// 1 Jan 1991
|
|
244
|
+
[2840140800, 25],
|
|
245
|
+
// 1 Jan 1990
|
|
246
|
+
[2776982400, 24],
|
|
247
|
+
// 1 Jan 1988
|
|
248
|
+
[2698012800, 23],
|
|
249
|
+
// 1 Jul 1985
|
|
250
|
+
[2634854400, 22],
|
|
251
|
+
// 1 Jul 1983
|
|
252
|
+
[2603318400, 21],
|
|
253
|
+
// 1 Jul 1982
|
|
254
|
+
[2571782400, 20],
|
|
255
|
+
// 1 Jul 1981
|
|
256
|
+
[2524521600, 19],
|
|
257
|
+
// 1 Jan 1980
|
|
258
|
+
[2492985600, 18],
|
|
259
|
+
// 1 Jan 1979
|
|
260
|
+
[2461449600, 17],
|
|
261
|
+
// 1 Jan 1978
|
|
262
|
+
[2429913600, 16],
|
|
263
|
+
// 1 Jan 1977
|
|
264
|
+
[2398291200, 15],
|
|
265
|
+
// 1 Jan 1976
|
|
266
|
+
[2366755200, 14],
|
|
267
|
+
// 1 Jan 1975
|
|
268
|
+
[2335219200, 13],
|
|
269
|
+
// 1 Jan 1974
|
|
270
|
+
[2303683200, 12],
|
|
271
|
+
// 1 Jan 1973
|
|
272
|
+
[2287785600, 11],
|
|
273
|
+
// 1 Jul 1972
|
|
274
|
+
[2272060800, 10]
|
|
275
|
+
// 1 Jan 1972
|
|
276
|
+
];
|
|
277
|
+
function getLeap(date) {
|
|
278
|
+
const ntp_time = getNtpTime(date);
|
|
279
|
+
for (const [timestamp, leapSeconds] of LEAP_SECONDS_TABLE) {
|
|
280
|
+
if (ntp_time / MILLISECONDS_IN_SECOND - leapSeconds >= timestamp) {
|
|
281
|
+
return leapSeconds;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return 8;
|
|
285
|
+
}
|
|
286
|
+
function getUtcDate(date) {
|
|
287
|
+
const tai_date = getTaiDate(date);
|
|
288
|
+
const leap_seconds = getLeap(date);
|
|
289
|
+
return new Date(tai_date.getTime() - leap_seconds * MILLISECONDS_IN_SECOND);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// src/novatel/nav.ts
|
|
293
|
+
var ID_RAWEPHEM = 41;
|
|
294
|
+
var ID_GLOEPHEMERIS = 723;
|
|
295
|
+
var GPS_EPOCH_MS2 = Date.UTC(1980, 0, 6);
|
|
296
|
+
var SEC_PER_WEEK2 = 7 * 86400;
|
|
297
|
+
var SEC_PER_DAY = 86400;
|
|
298
|
+
function decodeRawEphem(data, view, p) {
|
|
299
|
+
const prn = view.getUint32(p, true);
|
|
300
|
+
if (prn < 1 || prn > 32) return null;
|
|
301
|
+
const refWeek = view.getUint32(p + 4, true);
|
|
302
|
+
return decodeGpsLnavFrame(data.subarray(p + 12, p + 102), {
|
|
303
|
+
prn: `G${String(prn).padStart(2, "0")}`,
|
|
304
|
+
refWeek
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
function decodeGloEphemeris(view, p) {
|
|
308
|
+
const slot = view.getUint16(p, true) - 37;
|
|
309
|
+
if (slot < 1 || slot > 27) return null;
|
|
310
|
+
const freqNum = view.getUint16(p + 2, true) - 7;
|
|
311
|
+
const week = view.getUint16(p + 6, true);
|
|
312
|
+
const tow = Math.floor(view.getUint32(p + 8, true) / 1e3 + 0.5);
|
|
313
|
+
const toff = view.getUint32(p + 12, true);
|
|
314
|
+
const health = view.getUint32(p + 24, true) < 4 ? 0 : 1;
|
|
315
|
+
let tof = view.getUint32(p + 124, true) - toff;
|
|
316
|
+
tof += Math.floor(tow / SEC_PER_DAY) * SEC_PER_DAY;
|
|
317
|
+
if (tof < tow - 43200) tof += SEC_PER_DAY;
|
|
318
|
+
else if (tof > tow + 43200) tof -= SEC_PER_DAY;
|
|
319
|
+
const toeGpsMs = GPS_EPOCH_MS2 + (week * SEC_PER_WEEK2 + tow) * 1e3;
|
|
320
|
+
const tofGpsMs = GPS_EPOCH_MS2 + (week * SEC_PER_WEEK2 + tof) * 1e3;
|
|
321
|
+
const tofUtcSec = (getUtcDate(new Date(tofGpsMs)).getTime() - GPS_EPOCH_MS2) / 1e3;
|
|
322
|
+
return {
|
|
323
|
+
system: "R",
|
|
324
|
+
prn: `R${String(slot).padStart(2, "0")}`,
|
|
325
|
+
tocDate: getUtcDate(new Date(toeGpsMs)),
|
|
326
|
+
tauN: -view.getFloat64(p + 100, true),
|
|
327
|
+
// RINEX stores −τ_n
|
|
328
|
+
gammaN: view.getFloat64(p + 116, true),
|
|
329
|
+
messageFrameTime: (tofUtcSec % SEC_PER_WEEK2 + SEC_PER_WEEK2) % SEC_PER_WEEK2,
|
|
330
|
+
x: view.getFloat64(p + 28, true) / 1e3,
|
|
331
|
+
y: view.getFloat64(p + 36, true) / 1e3,
|
|
332
|
+
z: view.getFloat64(p + 44, true) / 1e3,
|
|
333
|
+
xDot: view.getFloat64(p + 52, true) / 1e3,
|
|
334
|
+
yDot: view.getFloat64(p + 60, true) / 1e3,
|
|
335
|
+
zDot: view.getFloat64(p + 68, true) / 1e3,
|
|
336
|
+
xAcc: view.getFloat64(p + 76, true) / 1e3,
|
|
337
|
+
yAcc: view.getFloat64(p + 84, true) / 1e3,
|
|
338
|
+
zAcc: view.getFloat64(p + 92, true) / 1e3,
|
|
339
|
+
health,
|
|
340
|
+
freqNum
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
function parseNovatelNav(data) {
|
|
344
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
345
|
+
const stats = { badCrc: 0 };
|
|
346
|
+
const ephemerides = [];
|
|
347
|
+
const lastGps = /* @__PURE__ */ new Map();
|
|
348
|
+
const lastGlo = /* @__PURE__ */ new Map();
|
|
349
|
+
for (const frame of oem4Frames(data, view, stats)) {
|
|
350
|
+
if (!frame.binary) continue;
|
|
351
|
+
if (frame.id === ID_RAWEPHEM && frame.msgLen >= 102) {
|
|
352
|
+
const eph = decodeRawEphem(data, view, frame.payload);
|
|
353
|
+
if (!eph) continue;
|
|
354
|
+
const prev = lastGps.get(eph.prn);
|
|
355
|
+
if (prev && prev.iode === eph.iode && prev.tocDate.getTime() === eph.tocDate.getTime()) {
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
lastGps.set(eph.prn, eph);
|
|
359
|
+
ephemerides.push(eph);
|
|
360
|
+
} else if (frame.id === ID_GLOEPHEMERIS && frame.msgLen >= 144) {
|
|
361
|
+
const eph = decodeGloEphemeris(view, frame.payload);
|
|
362
|
+
if (!eph) continue;
|
|
363
|
+
const prev = lastGlo.get(eph.prn);
|
|
364
|
+
if (prev && Math.abs(prev.tocDate.getTime() - eph.tocDate.getTime()) < 1e3 && prev.health === eph.health) {
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
lastGlo.set(eph.prn, eph);
|
|
368
|
+
ephemerides.push(eph);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return { ephemerides, badCrc: stats.badCrc };
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// src/novatel/index.ts
|
|
375
|
+
var GPS_EPOCH_MS3 = Date.UTC(1980, 0, 6);
|
|
27
376
|
var MS_PER_WEEK = 7 * 864e5;
|
|
28
377
|
var HDR = 28;
|
|
29
378
|
var ID_RANGE = 43;
|
|
30
379
|
var ID_RANGECMP = 140;
|
|
31
|
-
var
|
|
380
|
+
var ID_GLOEPHEMERIS2 = 723;
|
|
32
381
|
var C_LIGHT = 299792458;
|
|
33
382
|
var ADR_ROLL = 8388608;
|
|
34
383
|
function carrierFreq(sys, code, gloK) {
|
|
@@ -56,16 +405,6 @@ function carrierFreq(sys, code, gloK) {
|
|
|
56
405
|
function exsign(v, bits) {
|
|
57
406
|
return v & 1 << bits - 1 ? v - 2 ** bits : v;
|
|
58
407
|
}
|
|
59
|
-
function crc32(data, start, len) {
|
|
60
|
-
let crc = 0;
|
|
61
|
-
for (let i = start; i < start + len; i++) {
|
|
62
|
-
crc ^= data[i];
|
|
63
|
-
for (let j = 0; j < 8; j++) {
|
|
64
|
-
crc = crc & 1 ? crc >>> 1 ^ 3988292384 : crc >>> 1;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return crc >>> 0;
|
|
68
|
-
}
|
|
69
408
|
var SIGNALS = {
|
|
70
409
|
0: {
|
|
71
410
|
0: ["G", "1C"],
|
|
@@ -119,7 +458,7 @@ function parseNovatelRange(data) {
|
|
|
119
458
|
const hl = data[j + 3];
|
|
120
459
|
const id = view.getUint16(j + 4, true);
|
|
121
460
|
const ln = view.getUint16(j + 8, true);
|
|
122
|
-
if (id !==
|
|
461
|
+
if (id !== ID_GLOEPHEMERIS2 || hl < HDR || j + hl + ln + 4 > data.length)
|
|
123
462
|
continue;
|
|
124
463
|
if (crc32(data, j, hl + ln) !== view.getUint32(j + hl + ln, true)) continue;
|
|
125
464
|
const slot = view.getUint16(j + hl, true) - 37;
|
|
@@ -203,7 +542,7 @@ function parseNovatelRange(data) {
|
|
|
203
542
|
if (!codes.includes(code)) codes.push(code);
|
|
204
543
|
}
|
|
205
544
|
epochs.push({
|
|
206
|
-
timeMs:
|
|
545
|
+
timeMs: GPS_EPOCH_MS3 + week * MS_PER_WEEK + towMs,
|
|
207
546
|
meas
|
|
208
547
|
});
|
|
209
548
|
}
|
|
@@ -255,7 +594,7 @@ function parseNovatelRange(data) {
|
|
|
255
594
|
if (!codes.includes(code)) codes.push(code);
|
|
256
595
|
}
|
|
257
596
|
epochs.push({
|
|
258
|
-
timeMs:
|
|
597
|
+
timeMs: GPS_EPOCH_MS3 + week * MS_PER_WEEK + towMs,
|
|
259
598
|
meas
|
|
260
599
|
});
|
|
261
600
|
}
|
|
@@ -266,5 +605,9 @@ function parseNovatelRange(data) {
|
|
|
266
605
|
}
|
|
267
606
|
// Annotate the CommonJS export names for ESM import in node:
|
|
268
607
|
0 && (module.exports = {
|
|
608
|
+
OEM4_HLEN,
|
|
609
|
+
crc32,
|
|
610
|
+
oem4Frames,
|
|
611
|
+
parseNovatelNav,
|
|
269
612
|
parseNovatelRange
|
|
270
613
|
});
|
package/dist/novatel.d.cts
CHANGED
|
@@ -1,3 +1,70 @@
|
|
|
1
|
+
import { E as Ephemeris } from './nav-BAI1a9vK.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* NovAtel OEM4/6/7 binary framing shared by the measurement and
|
|
5
|
+
* navigation decoders: sync pattern 0xAA 0x44 0x12, a 28+-byte header,
|
|
6
|
+
* and a reflected CRC-32 (poly 0xEDB88320) over the whole frame.
|
|
7
|
+
*/
|
|
8
|
+
/** Minimum (standard) OEM4 binary header length. */
|
|
9
|
+
declare const OEM4_HLEN = 28;
|
|
10
|
+
/** Reflected CRC-32 (poly 0xEDB88320, init 0) — NovAtel "32-bit CRC". */
|
|
11
|
+
declare function crc32(data: Uint8Array, start: number, len: number): number;
|
|
12
|
+
/** One CRC-valid OEM4 frame located in a byte stream. */
|
|
13
|
+
interface Oem4Frame {
|
|
14
|
+
/** Message ID. */
|
|
15
|
+
id: number;
|
|
16
|
+
/** Offset of the frame start (first sync byte). */
|
|
17
|
+
start: number;
|
|
18
|
+
/** Offset of the payload (frame start + header length). */
|
|
19
|
+
payload: number;
|
|
20
|
+
/** Payload length in bytes. */
|
|
21
|
+
msgLen: number;
|
|
22
|
+
/** True when the header's message-type field marks a binary body. */
|
|
23
|
+
binary: boolean;
|
|
24
|
+
/** GPS week from the header. */
|
|
25
|
+
week: number;
|
|
26
|
+
/** GPS time of week from the header (ms). */
|
|
27
|
+
towMs: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Iterate every CRC-valid OEM4 frame in `data`. Corrupt or truncated
|
|
31
|
+
* candidates resync at the next byte; CRC failures additionally
|
|
32
|
+
* increment `stats.badCrc`.
|
|
33
|
+
*/
|
|
34
|
+
declare function oem4Frames(data: Uint8Array, view: DataView, stats: {
|
|
35
|
+
badCrc: number;
|
|
36
|
+
}): Generator<Oem4Frame>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* NovAtel navigation-message decoding: RAWEPHEM (message 41, raw GPS
|
|
40
|
+
* LNAV subframes 1–3) and GLOEPHEMERIS (message 723, decoded GLONASS
|
|
41
|
+
* L1 C/A ephemeris).
|
|
42
|
+
*
|
|
43
|
+
* Ported from RTKLIB demo5 (rtklibexplorer fork, src/rcv/novatel.c:
|
|
44
|
+
* decode_rawephemb / decode_gloephemerisb, Copyright (c) 2007-2020
|
|
45
|
+
* T. Takasu, BSD-2-Clause) and cross-checked against the OEM7
|
|
46
|
+
* Commands and Logs Reference Manual. Output records mirror what
|
|
47
|
+
* `parseNavFile` produces for the equivalent RINEX 3 navigation file:
|
|
48
|
+
* GPS `tocDate` is a GPS-scale Date, GLONASS `tocDate` is the UTC
|
|
49
|
+
* epoch, GLONASS state vectors are in km (PZ-90), the RINEX clock bias
|
|
50
|
+
* is −τ_n, and `messageFrameTime` is the frame time as seconds of the
|
|
51
|
+
* UTC week.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
interface NovatelNavResult {
|
|
55
|
+
/** Broadcast ephemerides in stream order, duplicates suppressed. */
|
|
56
|
+
ephemerides: Ephemeris[];
|
|
57
|
+
/** Frames whose CRC failed (corruption indicator). */
|
|
58
|
+
badCrc: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Decode every navigation message (RAWEPHEM, GLOEPHEMERIS) in a
|
|
62
|
+
* NovAtel binary byte stream. Repeated broadcasts of an unchanged
|
|
63
|
+
* ephemeris are suppressed the same way RTKLIB does: GPS by issue of
|
|
64
|
+
* data, GLONASS by reference time and health.
|
|
65
|
+
*/
|
|
66
|
+
declare function parseNovatelNav(data: Uint8Array): NovatelNavResult;
|
|
67
|
+
|
|
1
68
|
/**
|
|
2
69
|
* NovAtel OEM4/6/7 raw-measurement decoding (RANGE log, message 43).
|
|
3
70
|
*
|
|
@@ -15,6 +82,7 @@
|
|
|
15
82
|
* without known parity are dropped, and code/phase are individually
|
|
16
83
|
* gated by their lock flags.
|
|
17
84
|
*/
|
|
85
|
+
|
|
18
86
|
interface NovatelMeasurement {
|
|
19
87
|
/** RINEX PRN, e.g. "G04", "R11", "S23", "J01". */
|
|
20
88
|
prn: string;
|
|
@@ -54,4 +122,4 @@ interface NovatelParseResult {
|
|
|
54
122
|
*/
|
|
55
123
|
declare function parseNovatelRange(data: Uint8Array): NovatelParseResult;
|
|
56
124
|
|
|
57
|
-
export { type NovatelEpoch, type NovatelMeasurement, type NovatelParseResult, parseNovatelRange };
|
|
125
|
+
export { type NovatelEpoch, type NovatelMeasurement, type NovatelNavResult, type NovatelParseResult, OEM4_HLEN, type Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelRange };
|
package/dist/novatel.d.ts
CHANGED
|
@@ -1,3 +1,70 @@
|
|
|
1
|
+
import { E as Ephemeris } from './nav-BAI1a9vK.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* NovAtel OEM4/6/7 binary framing shared by the measurement and
|
|
5
|
+
* navigation decoders: sync pattern 0xAA 0x44 0x12, a 28+-byte header,
|
|
6
|
+
* and a reflected CRC-32 (poly 0xEDB88320) over the whole frame.
|
|
7
|
+
*/
|
|
8
|
+
/** Minimum (standard) OEM4 binary header length. */
|
|
9
|
+
declare const OEM4_HLEN = 28;
|
|
10
|
+
/** Reflected CRC-32 (poly 0xEDB88320, init 0) — NovAtel "32-bit CRC". */
|
|
11
|
+
declare function crc32(data: Uint8Array, start: number, len: number): number;
|
|
12
|
+
/** One CRC-valid OEM4 frame located in a byte stream. */
|
|
13
|
+
interface Oem4Frame {
|
|
14
|
+
/** Message ID. */
|
|
15
|
+
id: number;
|
|
16
|
+
/** Offset of the frame start (first sync byte). */
|
|
17
|
+
start: number;
|
|
18
|
+
/** Offset of the payload (frame start + header length). */
|
|
19
|
+
payload: number;
|
|
20
|
+
/** Payload length in bytes. */
|
|
21
|
+
msgLen: number;
|
|
22
|
+
/** True when the header's message-type field marks a binary body. */
|
|
23
|
+
binary: boolean;
|
|
24
|
+
/** GPS week from the header. */
|
|
25
|
+
week: number;
|
|
26
|
+
/** GPS time of week from the header (ms). */
|
|
27
|
+
towMs: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Iterate every CRC-valid OEM4 frame in `data`. Corrupt or truncated
|
|
31
|
+
* candidates resync at the next byte; CRC failures additionally
|
|
32
|
+
* increment `stats.badCrc`.
|
|
33
|
+
*/
|
|
34
|
+
declare function oem4Frames(data: Uint8Array, view: DataView, stats: {
|
|
35
|
+
badCrc: number;
|
|
36
|
+
}): Generator<Oem4Frame>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* NovAtel navigation-message decoding: RAWEPHEM (message 41, raw GPS
|
|
40
|
+
* LNAV subframes 1–3) and GLOEPHEMERIS (message 723, decoded GLONASS
|
|
41
|
+
* L1 C/A ephemeris).
|
|
42
|
+
*
|
|
43
|
+
* Ported from RTKLIB demo5 (rtklibexplorer fork, src/rcv/novatel.c:
|
|
44
|
+
* decode_rawephemb / decode_gloephemerisb, Copyright (c) 2007-2020
|
|
45
|
+
* T. Takasu, BSD-2-Clause) and cross-checked against the OEM7
|
|
46
|
+
* Commands and Logs Reference Manual. Output records mirror what
|
|
47
|
+
* `parseNavFile` produces for the equivalent RINEX 3 navigation file:
|
|
48
|
+
* GPS `tocDate` is a GPS-scale Date, GLONASS `tocDate` is the UTC
|
|
49
|
+
* epoch, GLONASS state vectors are in km (PZ-90), the RINEX clock bias
|
|
50
|
+
* is −τ_n, and `messageFrameTime` is the frame time as seconds of the
|
|
51
|
+
* UTC week.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
interface NovatelNavResult {
|
|
55
|
+
/** Broadcast ephemerides in stream order, duplicates suppressed. */
|
|
56
|
+
ephemerides: Ephemeris[];
|
|
57
|
+
/** Frames whose CRC failed (corruption indicator). */
|
|
58
|
+
badCrc: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Decode every navigation message (RAWEPHEM, GLOEPHEMERIS) in a
|
|
62
|
+
* NovAtel binary byte stream. Repeated broadcasts of an unchanged
|
|
63
|
+
* ephemeris are suppressed the same way RTKLIB does: GPS by issue of
|
|
64
|
+
* data, GLONASS by reference time and health.
|
|
65
|
+
*/
|
|
66
|
+
declare function parseNovatelNav(data: Uint8Array): NovatelNavResult;
|
|
67
|
+
|
|
1
68
|
/**
|
|
2
69
|
* NovAtel OEM4/6/7 raw-measurement decoding (RANGE log, message 43).
|
|
3
70
|
*
|
|
@@ -15,6 +82,7 @@
|
|
|
15
82
|
* without known parity are dropped, and code/phase are individually
|
|
16
83
|
* gated by their lock flags.
|
|
17
84
|
*/
|
|
85
|
+
|
|
18
86
|
interface NovatelMeasurement {
|
|
19
87
|
/** RINEX PRN, e.g. "G04", "R11", "S23", "J01". */
|
|
20
88
|
prn: string;
|
|
@@ -54,4 +122,4 @@ interface NovatelParseResult {
|
|
|
54
122
|
*/
|
|
55
123
|
declare function parseNovatelRange(data: Uint8Array): NovatelParseResult;
|
|
56
124
|
|
|
57
|
-
export { type NovatelEpoch, type NovatelMeasurement, type NovatelParseResult, parseNovatelRange };
|
|
125
|
+
export { type NovatelEpoch, type NovatelMeasurement, type NovatelNavResult, type NovatelParseResult, OEM4_HLEN, type Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelRange };
|
package/dist/novatel.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
+
OEM4_HLEN,
|
|
3
|
+
crc32,
|
|
4
|
+
oem4Frames,
|
|
5
|
+
parseNovatelNav,
|
|
2
6
|
parseNovatelRange
|
|
3
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-I4UV45NT.js";
|
|
8
|
+
import "./chunk-HVXYFUCB.js";
|
|
9
|
+
import "./chunk-LEEU5OIO.js";
|
|
4
10
|
export {
|
|
11
|
+
OEM4_HLEN,
|
|
12
|
+
crc32,
|
|
13
|
+
oem4Frames,
|
|
14
|
+
parseNovatelNav,
|
|
5
15
|
parseNovatelRange
|
|
6
16
|
};
|