gnss-js 1.12.0 → 1.14.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/index.d.cts CHANGED
@@ -9,7 +9,10 @@ export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResul
9
9
  export { E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, p as parseNavFile } from './nav-BAI1a9vK.cjs';
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
- export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.cjs';
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';
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';
13
16
  export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.cjs';
14
17
  export { KlobucharCoeffs, SppOptions, SppSolution, ionoFree, klobucharDelay, satClockCorrection, solveSpp } from './positioning.cjs';
15
18
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.cjs';
package/dist/index.d.ts CHANGED
@@ -9,7 +9,10 @@ export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResul
9
9
  export { E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, p as parseNavFile } from './nav-BAI1a9vK.js';
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
- export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.js';
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';
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';
13
16
  export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.js';
14
17
  export { KlobucharCoeffs, SppOptions, SppSolution, ionoFree, klobucharDelay, satClockCorrection, solveSpp } from './positioning.js';
15
18
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.js';
package/dist/index.js CHANGED
@@ -1,29 +1,3 @@
1
- import {
2
- connectToMountpoint,
3
- fetchSourcetable,
4
- parseSourcetable
5
- } from "./chunk-BJHTBYNG.js";
6
- import {
7
- CompletenessAccumulator,
8
- CycleSlipAccumulator,
9
- IonoAccumulator,
10
- MultipathAccumulator,
11
- analyzeQuality,
12
- applyIonoDcb,
13
- computeIonoRate,
14
- detrendIonoArcs,
15
- parseSinexBiasDcb
16
- } from "./chunk-Z5UZUNCB.js";
17
- import {
18
- frequencyLabel,
19
- parseAntex
20
- } from "./chunk-5CMSYIYM.js";
21
- import {
22
- computeStats,
23
- nmeaCoordToDecimal,
24
- parseNmeaFile,
25
- verifyChecksum
26
- } from "./chunk-YDMYO3YK.js";
27
1
  import {
28
2
  BAND_PRESETS,
29
3
  CONSTELLATIONS,
@@ -59,6 +33,41 @@ import {
59
33
  phiBOCs,
60
34
  phiBPSK
61
35
  } from "./chunk-2K3FCJBX.js";
36
+ import {
37
+ parseUbxRawx
38
+ } from "./chunk-5IXK25MX.js";
39
+ import {
40
+ parseSbfMeas
41
+ } from "./chunk-YIHO74OS.js";
42
+ import {
43
+ parseNovatelRange
44
+ } from "./chunk-SWKWJEGY.js";
45
+ import {
46
+ connectToMountpoint,
47
+ fetchSourcetable,
48
+ parseSourcetable
49
+ } from "./chunk-BJHTBYNG.js";
50
+ import {
51
+ CompletenessAccumulator,
52
+ CycleSlipAccumulator,
53
+ IonoAccumulator,
54
+ MultipathAccumulator,
55
+ analyzeQuality,
56
+ applyIonoDcb,
57
+ computeIonoRate,
58
+ detrendIonoArcs,
59
+ parseSinexBiasDcb
60
+ } from "./chunk-Z5UZUNCB.js";
61
+ import {
62
+ frequencyLabel,
63
+ parseAntex
64
+ } from "./chunk-5CMSYIYM.js";
65
+ import {
66
+ computeStats,
67
+ nmeaCoordToDecimal,
68
+ parseNmeaFile,
69
+ verifyChecksum
70
+ } from "./chunk-YDMYO3YK.js";
62
71
  import {
63
72
  Scale,
64
73
  getDateFromDayOfWeek,
@@ -103,13 +112,14 @@ import {
103
112
  klobucharDelay,
104
113
  satClockCorrection,
105
114
  solveSpp
106
- } from "./chunk-LKFSXVIZ.js";
115
+ } from "./chunk-E5CP37P2.js";
107
116
  import {
108
117
  computeAllPositions,
109
118
  computeDop,
110
119
  computeLiveSkyPositions,
111
120
  computeSatPosition,
112
121
  computeVisibility,
122
+ computeVisibilityFromPositions,
113
123
  dopplerHz,
114
124
  ecefToAzEl,
115
125
  ephInfoToEphemeris,
@@ -119,7 +129,7 @@ import {
119
129
  navTimesFromEph,
120
130
  rangeRate,
121
131
  selectEphemeris
122
- } from "./chunk-DMNFB7Q6.js";
132
+ } from "./chunk-VAHMHYID.js";
123
133
  import {
124
134
  getBdsTime,
125
135
  getDateFromBdsTime,
@@ -361,6 +371,7 @@ export {
361
371
  computeSatPosition,
362
372
  computeStats,
363
373
  computeVisibility,
374
+ computeVisibilityFromPositions,
364
375
  connectToMountpoint,
365
376
  createGzipLineSink,
366
377
  createStationMeta,
@@ -458,10 +469,13 @@ export {
458
469
  parseIonex,
459
470
  parseNavFile,
460
471
  parseNmeaFile,
472
+ parseNovatelRange,
461
473
  parseRinexStream,
474
+ parseSbfMeas,
462
475
  parseSinexBiasDcb,
463
476
  parseSourcetable,
464
477
  parseSp3,
478
+ parseUbxRawx,
465
479
  phiAltBOC,
466
480
  phiBOCc,
467
481
  phiBOCs,
@@ -0,0 +1,270 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/novatel/index.ts
21
+ var novatel_exports = {};
22
+ __export(novatel_exports, {
23
+ parseNovatelRange: () => parseNovatelRange
24
+ });
25
+ module.exports = __toCommonJS(novatel_exports);
26
+ var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
27
+ var MS_PER_WEEK = 7 * 864e5;
28
+ var HDR = 28;
29
+ var ID_RANGE = 43;
30
+ var ID_RANGECMP = 140;
31
+ var ID_GLOEPHEMERIS = 723;
32
+ var C_LIGHT = 299792458;
33
+ var ADR_ROLL = 8388608;
34
+ function carrierFreq(sys, code, gloK) {
35
+ const band = code[0];
36
+ switch (sys) {
37
+ case "G":
38
+ case "J":
39
+ return band === "1" ? 157542e4 : band === "2" ? 12276e5 : 117645e4;
40
+ case "S":
41
+ return band === "1" ? 157542e4 : 117645e4;
42
+ case "E":
43
+ return band === "1" ? 157542e4 : band === "5" ? 117645e4 : band === "7" ? 120714e4 : band === "8" ? 1191795e3 : 127875e4;
44
+ case "C":
45
+ return band === "1" ? 157542e4 : band === "2" ? 1561098e3 : band === "5" ? 117645e4 : band === "7" ? 120714e4 : 126852e4;
46
+ case "R": {
47
+ if (gloK === null) return 0;
48
+ if (band === "1") return 1602e6 + gloK * 562500;
49
+ if (band === "2") return 1246e6 + gloK * 437500;
50
+ return 1202025e3;
51
+ }
52
+ default:
53
+ return 0;
54
+ }
55
+ }
56
+ function exsign(v, bits) {
57
+ return v & 1 << bits - 1 ? v - 2 ** bits : v;
58
+ }
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
+ var SIGNALS = {
70
+ 0: {
71
+ 0: ["G", "1C"],
72
+ 5: ["G", "2P"],
73
+ 9: ["G", "2W"],
74
+ 14: ["G", "5Q"],
75
+ 16: ["G", "1L"],
76
+ 17: ["G", "2S"]
77
+ },
78
+ 1: { 0: ["R", "1C"], 1: ["R", "2C"], 5: ["R", "2P"], 6: ["R", "3Q"] },
79
+ 2: { 0: ["S", "1C"], 6: ["S", "5I"] },
80
+ 3: {
81
+ 1: ["E", "1C"],
82
+ 2: ["E", "1C"],
83
+ 6: ["E", "6B"],
84
+ 7: ["E", "6C"],
85
+ 12: ["E", "5Q"],
86
+ 17: ["E", "7Q"],
87
+ 20: ["E", "8Q"]
88
+ },
89
+ 4: {
90
+ 0: ["C", "2I"],
91
+ 1: ["C", "7I"],
92
+ 2: ["C", "6I"],
93
+ 4: ["C", "2I"],
94
+ 5: ["C", "7I"],
95
+ 6: ["C", "6I"],
96
+ 7: ["C", "1P"],
97
+ 9: ["C", "5P"],
98
+ 11: ["C", "7D"]
99
+ },
100
+ 5: {
101
+ 0: ["J", "1C"],
102
+ 14: ["J", "5Q"],
103
+ 16: ["J", "1L"],
104
+ 17: ["J", "2S"],
105
+ 27: ["J", "6L"]
106
+ },
107
+ 6: { 0: ["I", "5A"] }
108
+ };
109
+ function parseNovatelRange(data) {
110
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
111
+ const epochs = [];
112
+ const messageCounts = {};
113
+ const obsCodes = {};
114
+ let badCrc = 0;
115
+ const gloFcn = /* @__PURE__ */ new Map();
116
+ for (let j = 0; j + HDR + 4 <= data.length; j++) {
117
+ if (data[j] !== 170 || data[j + 1] !== 68 || data[j + 2] !== 18)
118
+ continue;
119
+ const hl = data[j + 3];
120
+ const id = view.getUint16(j + 4, true);
121
+ const ln = view.getUint16(j + 8, true);
122
+ if (id !== ID_GLOEPHEMERIS || hl < HDR || j + hl + ln + 4 > data.length)
123
+ continue;
124
+ if (crc32(data, j, hl + ln) !== view.getUint32(j + hl + ln, true)) continue;
125
+ const slot = view.getUint16(j + hl, true) - 37;
126
+ const k = view.getUint16(j + hl + 2, true) - 7;
127
+ if (slot >= 1 && slot <= 32) gloFcn.set(slot, k);
128
+ j += hl + ln + 3;
129
+ }
130
+ let i = 0;
131
+ while (i + HDR + 4 <= data.length) {
132
+ if (data[i] !== 170 || data[i + 1] !== 68 || data[i + 2] !== 18) {
133
+ i++;
134
+ continue;
135
+ }
136
+ const hlen = data[i + 3];
137
+ const msgId = view.getUint16(i + 4, true);
138
+ const msgLen = view.getUint16(i + 8, true);
139
+ const total = hlen + msgLen + 4;
140
+ if (hlen < HDR || i + total > data.length) {
141
+ i++;
142
+ continue;
143
+ }
144
+ if (crc32(data, i, hlen + msgLen) !== view.getUint32(i + hlen + msgLen, true)) {
145
+ badCrc++;
146
+ i++;
147
+ continue;
148
+ }
149
+ messageCounts[msgId] = (messageCounts[msgId] ?? 0) + 1;
150
+ const binary = (data[i + 6] >> 4 & 3) === 0;
151
+ const week = view.getUint16(i + 14, true);
152
+ const towMs = view.getUint32(i + 16, true);
153
+ if (msgId === ID_RANGECMP && binary && week > 0) {
154
+ const p = i + hlen;
155
+ const nobs = view.getUint32(p, true);
156
+ if (p + 4 + nobs * 24 <= i + hlen + msgLen) {
157
+ const meas = [];
158
+ for (let k = 0; k < nobs; k++) {
159
+ const o = p + 4 + 24 * k;
160
+ const stat = view.getUint32(o, true);
161
+ const satsys = stat >>> 16 & 7;
162
+ const sigtype = stat >>> 21 & 31;
163
+ const plock = stat >>> 10 & 1;
164
+ const parity = stat >>> 11 & 1;
165
+ const clock = stat >>> 12 & 1;
166
+ const sig = SIGNALS[satsys]?.[sigtype];
167
+ if (!sig) continue;
168
+ let [sysL, code] = sig;
169
+ let prnNum = data[o + 17];
170
+ if (sysL === "R") prnNum -= 37;
171
+ if (sysL === "S" && prnNum >= 183 && prnNum <= 191 && code === "1C") {
172
+ sysL = "J";
173
+ code = "1Z";
174
+ prnNum -= 182;
175
+ } else if (sysL === "S") {
176
+ prnNum -= 100;
177
+ }
178
+ if (prnNum < 1 || prnNum > 99) continue;
179
+ if (sysL === "R" && !parity) continue;
180
+ const gloK = sysL === "R" ? gloFcn.get(prnNum) ?? null : null;
181
+ const dop = exsign(view.getUint32(o + 4, true) & 268435455, 28) / 256;
182
+ const psr = (view.getUint32(o + 7, true) >>> 4) / 128 + data[o + 11] * 2097152;
183
+ let cp = null;
184
+ const freq = carrierFreq(sysL, code, gloK);
185
+ if (freq > 0) {
186
+ const adr = view.getInt32(o + 12, true) / 256;
187
+ const rolls = psr * freq / C_LIGHT / ADR_ROLL + adr / ADR_ROLL;
188
+ cp = -adr + ADR_ROLL * Math.floor(rolls + (rolls <= 0 ? -0.5 : 0.5));
189
+ }
190
+ const lockt = (view.getUint32(o + 18, true) & 2097151) / 32;
191
+ const cn0 = ((view.getUint16(o + 20, true) & 1023) >>> 5) + 20;
192
+ meas.push({
193
+ prn: `${sysL}${String(prnNum).padStart(2, "0")}`,
194
+ code,
195
+ pr: clock ? psr : null,
196
+ cp: plock ? cp : null,
197
+ doppler: plock ? dop : null,
198
+ cn0,
199
+ lockTimeS: lockt,
200
+ gloChannel: gloK
201
+ });
202
+ const codes = obsCodes[sysL] ??= [];
203
+ if (!codes.includes(code)) codes.push(code);
204
+ }
205
+ epochs.push({
206
+ timeMs: GPS_EPOCH_MS + week * MS_PER_WEEK + towMs,
207
+ meas
208
+ });
209
+ }
210
+ } else if (msgId === ID_RANGE && binary && week > 0) {
211
+ const p = i + hlen;
212
+ const nobs = view.getUint32(p, true);
213
+ if (p + 4 + nobs * 44 <= i + hlen + msgLen) {
214
+ const meas = [];
215
+ for (let k = 0; k < nobs; k++) {
216
+ const o = p + 4 + 44 * k;
217
+ const stat = view.getUint32(o + 40, true);
218
+ const satsys = stat >>> 16 & 7;
219
+ const sigtype = stat >>> 21 & 31;
220
+ const plock = stat >>> 10 & 1;
221
+ const parity = stat >>> 11 & 1;
222
+ const clock = stat >>> 12 & 1;
223
+ const sig = SIGNALS[satsys]?.[sigtype];
224
+ if (!sig) continue;
225
+ let [sysL, code] = sig;
226
+ let prnNum = view.getUint16(o, true);
227
+ if (sysL === "R") prnNum -= 37;
228
+ if (sysL === "S" && prnNum >= 183 && prnNum <= 191 && code === "1C") {
229
+ sysL = "J";
230
+ code = "1Z";
231
+ prnNum -= 182;
232
+ } else if (sysL === "S") {
233
+ prnNum -= 100;
234
+ }
235
+ if (prnNum < 1 || prnNum > 99) continue;
236
+ if (sysL === "R" && !parity) continue;
237
+ const prn = `${sysL}${String(prnNum).padStart(2, "0")}`;
238
+ const gfrq = view.getUint16(o + 2, true);
239
+ const psr = view.getFloat64(o + 4, true);
240
+ const adr = view.getFloat64(o + 16, true);
241
+ const dop = view.getFloat32(o + 28, true);
242
+ const snr = view.getFloat32(o + 32, true);
243
+ const lockt = view.getFloat32(o + 36, true);
244
+ meas.push({
245
+ prn,
246
+ code,
247
+ pr: clock ? psr : null,
248
+ cp: plock ? -adr : null,
249
+ doppler: plock ? dop : null,
250
+ cn0: snr,
251
+ lockTimeS: lockt,
252
+ gloChannel: sysL === "R" ? gfrq - 8 : null
253
+ });
254
+ const codes = obsCodes[sysL] ??= [];
255
+ if (!codes.includes(code)) codes.push(code);
256
+ }
257
+ epochs.push({
258
+ timeMs: GPS_EPOCH_MS + week * MS_PER_WEEK + towMs,
259
+ meas
260
+ });
261
+ }
262
+ }
263
+ i += total;
264
+ }
265
+ return { epochs, messageCounts, obsCodes, badCrc };
266
+ }
267
+ // Annotate the CommonJS export names for ESM import in node:
268
+ 0 && (module.exports = {
269
+ parseNovatelRange
270
+ });
@@ -0,0 +1,57 @@
1
+ /**
2
+ * NovAtel OEM4/6/7 raw-measurement decoding (RANGE log, message 43).
3
+ *
4
+ * Framing: 0xAA 0x44 0x12, a 28-byte binary header (message ID,
5
+ * GPS week + milliseconds), payload, and a reflected CRC-32
6
+ * (poly 0xEDB88320) over the whole frame. Each RANGE observation is a
7
+ * 44-byte record whose channel-tracking-status word carries the
8
+ * constellation and signal type.
9
+ *
10
+ * Field layout and signal tables ported from RTKLIB demo5
11
+ * (rtklibexplorer fork, src/rcv/novatel.c, BSD-2-Clause) and
12
+ * cross-checked against the OEM7 Commands and Logs Reference Manual.
13
+ * Notably: RINEX carrier phase is the NEGATED accumulated Doppler
14
+ * range (L = −adr), GLONASS PRNs are offset by 37, GLONASS phases
15
+ * without known parity are dropped, and code/phase are individually
16
+ * gated by their lock flags.
17
+ */
18
+ interface NovatelMeasurement {
19
+ /** RINEX PRN, e.g. "G04", "R11", "S23", "J01". */
20
+ prn: string;
21
+ /** RINEX band+attribute, e.g. "1C", "2W", "5Q". */
22
+ code: string;
23
+ /** Pseudorange (m), null when the code is unlocked. */
24
+ pr: number | null;
25
+ /** Carrier phase (cycles, RINEX sign), null when phase is unlocked. */
26
+ cp: number | null;
27
+ /** Instantaneous Doppler (Hz), null when phase is unlocked. */
28
+ doppler: number | null;
29
+ /** C/N0 (dB-Hz). */
30
+ cn0: number;
31
+ /** Continuous lock time (s). */
32
+ lockTimeS: number;
33
+ /** GLONASS frequency channel k (freqId − 8), null for CDMA systems. */
34
+ gloChannel: number | null;
35
+ }
36
+ interface NovatelEpoch {
37
+ /** Epoch (GPS-scale ms — same convention as the RINEX parser). */
38
+ timeMs: number;
39
+ meas: NovatelMeasurement[];
40
+ }
41
+ interface NovatelParseResult {
42
+ epochs: NovatelEpoch[];
43
+ /** Count per message ID, for diagnostics. */
44
+ messageCounts: Record<number, number>;
45
+ /** Observation codes seen per system letter, in first-seen order. */
46
+ obsCodes: Record<string, string[]>;
47
+ /** Frames whose CRC failed (corruption indicator). */
48
+ badCrc: number;
49
+ }
50
+ /**
51
+ * Decode every valid RANGE message in a NovAtel binary byte stream.
52
+ * Other messages are counted and skipped; CRC failures resync at the
53
+ * next byte.
54
+ */
55
+ declare function parseNovatelRange(data: Uint8Array): NovatelParseResult;
56
+
57
+ export { type NovatelEpoch, type NovatelMeasurement, type NovatelParseResult, parseNovatelRange };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * NovAtel OEM4/6/7 raw-measurement decoding (RANGE log, message 43).
3
+ *
4
+ * Framing: 0xAA 0x44 0x12, a 28-byte binary header (message ID,
5
+ * GPS week + milliseconds), payload, and a reflected CRC-32
6
+ * (poly 0xEDB88320) over the whole frame. Each RANGE observation is a
7
+ * 44-byte record whose channel-tracking-status word carries the
8
+ * constellation and signal type.
9
+ *
10
+ * Field layout and signal tables ported from RTKLIB demo5
11
+ * (rtklibexplorer fork, src/rcv/novatel.c, BSD-2-Clause) and
12
+ * cross-checked against the OEM7 Commands and Logs Reference Manual.
13
+ * Notably: RINEX carrier phase is the NEGATED accumulated Doppler
14
+ * range (L = −adr), GLONASS PRNs are offset by 37, GLONASS phases
15
+ * without known parity are dropped, and code/phase are individually
16
+ * gated by their lock flags.
17
+ */
18
+ interface NovatelMeasurement {
19
+ /** RINEX PRN, e.g. "G04", "R11", "S23", "J01". */
20
+ prn: string;
21
+ /** RINEX band+attribute, e.g. "1C", "2W", "5Q". */
22
+ code: string;
23
+ /** Pseudorange (m), null when the code is unlocked. */
24
+ pr: number | null;
25
+ /** Carrier phase (cycles, RINEX sign), null when phase is unlocked. */
26
+ cp: number | null;
27
+ /** Instantaneous Doppler (Hz), null when phase is unlocked. */
28
+ doppler: number | null;
29
+ /** C/N0 (dB-Hz). */
30
+ cn0: number;
31
+ /** Continuous lock time (s). */
32
+ lockTimeS: number;
33
+ /** GLONASS frequency channel k (freqId − 8), null for CDMA systems. */
34
+ gloChannel: number | null;
35
+ }
36
+ interface NovatelEpoch {
37
+ /** Epoch (GPS-scale ms — same convention as the RINEX parser). */
38
+ timeMs: number;
39
+ meas: NovatelMeasurement[];
40
+ }
41
+ interface NovatelParseResult {
42
+ epochs: NovatelEpoch[];
43
+ /** Count per message ID, for diagnostics. */
44
+ messageCounts: Record<number, number>;
45
+ /** Observation codes seen per system letter, in first-seen order. */
46
+ obsCodes: Record<string, string[]>;
47
+ /** Frames whose CRC failed (corruption indicator). */
48
+ badCrc: number;
49
+ }
50
+ /**
51
+ * Decode every valid RANGE message in a NovAtel binary byte stream.
52
+ * Other messages are counted and skipped; CRC failures resync at the
53
+ * next byte.
54
+ */
55
+ declare function parseNovatelRange(data: Uint8Array): NovatelParseResult;
56
+
57
+ export { type NovatelEpoch, type NovatelMeasurement, type NovatelParseResult, parseNovatelRange };
@@ -0,0 +1,6 @@
1
+ import {
2
+ parseNovatelRange
3
+ } from "./chunk-SWKWJEGY.js";
4
+ export {
5
+ parseNovatelRange
6
+ };
package/dist/orbit.cjs CHANGED
@@ -25,6 +25,7 @@ __export(orbit_exports, {
25
25
  computeLiveSkyPositions: () => computeLiveSkyPositions,
26
26
  computeSatPosition: () => computeSatPosition,
27
27
  computeVisibility: () => computeVisibility,
28
+ computeVisibilityFromPositions: () => computeVisibilityFromPositions,
28
29
  dopplerHz: () => dopplerHz,
29
30
  ecefToAzEl: () => ecefToAzEl,
30
31
  ecefToGeodetic: () => ecefToGeodetic,
@@ -662,8 +663,14 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
662
663
  const stepMs = stepSec * 1e3;
663
664
  const times = [];
664
665
  for (let t = startMs; t <= endMs; t += stepMs) times.push(t);
666
+ return computeVisibilityFromPositions(
667
+ computeAllPositions(ephemerides, times, rxPos),
668
+ elevationMaskDeg
669
+ );
670
+ }
671
+ function computeVisibilityFromPositions(all, elevationMaskDeg = 10) {
672
+ const times = all.times;
665
673
  const maskRadFor = maskRadForAzimuth(elevationMaskDeg);
666
- const all = computeAllPositions(ephemerides, times, rxPos);
667
674
  const elevation = {};
668
675
  const azimuth = {};
669
676
  const subLat = {};
@@ -753,6 +760,7 @@ function computeVisibility(ephemerides, rxPos, startMs, endMs, stepSec = 300, el
753
760
  computeLiveSkyPositions,
754
761
  computeSatPosition,
755
762
  computeVisibility,
763
+ computeVisibilityFromPositions,
756
764
  dopplerHz,
757
765
  ecefToAzEl,
758
766
  ecefToGeodetic,
package/dist/orbit.d.cts CHANGED
@@ -185,5 +185,12 @@ declare function maskRadForAzimuth(maskDeg: number | number[]): (azRad: number)
185
185
  * local horizon/obstruction profile.
186
186
  */
187
187
  declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number | number[]): VisibilityResult;
188
+ /**
189
+ * Visibility aggregation from precomputed satellite tracks — the same
190
+ * counting/DOP/pass logic as `computeVisibility`, but source-agnostic:
191
+ * feed it positions from broadcast ephemerides, TLE/SGP4 propagation,
192
+ * SP3 interpolation, or anything else shaped like AllPositionsData.
193
+ */
194
+ declare function computeVisibilityFromPositions(all: AllPositionsData, elevationMaskDeg?: number | number[]): VisibilityResult;
188
195
 
189
- export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris };
196
+ export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris };
package/dist/orbit.d.ts CHANGED
@@ -185,5 +185,12 @@ declare function maskRadForAzimuth(maskDeg: number | number[]): (azRad: number)
185
185
  * local horizon/obstruction profile.
186
186
  */
187
187
  declare function computeVisibility(ephemerides: Ephemeris[], rxPos: [number, number, number], startMs: number, endMs: number, stepSec?: number, elevationMaskDeg?: number | number[]): VisibilityResult;
188
+ /**
189
+ * Visibility aggregation from precomputed satellite tracks — the same
190
+ * counting/DOP/pass logic as `computeVisibility`, but source-agnostic:
191
+ * feed it positions from broadcast ephemerides, TLE/SGP4 propagation,
192
+ * SP3 interpolation, or anything else shaped like AllPositionsData.
193
+ */
194
+ declare function computeVisibilityFromPositions(all: AllPositionsData, elevationMaskDeg?: number | number[]): VisibilityResult;
188
195
 
189
- export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris };
196
+ export { type AllPositionsData, type DopValues, type EpochSkyData, type SatAzEl, type SatPoint, type SatPosition, type VisibilityPass, type VisibilityResult, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris };
package/dist/orbit.js CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  computeLiveSkyPositions,
5
5
  computeSatPosition,
6
6
  computeVisibility,
7
+ computeVisibilityFromPositions,
7
8
  dopplerHz,
8
9
  ecefToAzEl,
9
10
  ephInfoToEphemeris,
@@ -13,7 +14,7 @@ import {
13
14
  navTimesFromEph,
14
15
  rangeRate,
15
16
  selectEphemeris
16
- } from "./chunk-DMNFB7Q6.js";
17
+ } from "./chunk-VAHMHYID.js";
17
18
  import "./chunk-HVXYFUCB.js";
18
19
  import {
19
20
  ecefToGeodetic,
@@ -28,6 +29,7 @@ export {
28
29
  computeLiveSkyPositions,
29
30
  computeSatPosition,
30
31
  computeVisibility,
32
+ computeVisibilityFromPositions,
31
33
  dopplerHz,
32
34
  ecefToAzEl,
33
35
  ecefToGeodetic,
@@ -3,8 +3,8 @@ import {
3
3
  klobucharDelay,
4
4
  satClockCorrection,
5
5
  solveSpp
6
- } from "./chunk-LKFSXVIZ.js";
7
- import "./chunk-DMNFB7Q6.js";
6
+ } from "./chunk-E5CP37P2.js";
7
+ import "./chunk-VAHMHYID.js";
8
8
  import "./chunk-HVXYFUCB.js";
9
9
  import "./chunk-37QNKGTC.js";
10
10
  import "./chunk-6FAL6P4G.js";