MRTKLIB 0.7.14
Modernized GNSS Positioning Library
Loading...
Searching...
No Matches
mrtk_obs.c
Go to the documentation of this file.
1/*------------------------------------------------------------------------------
2 * mrtk_obs.c : observation data functions
3 *
4 * Copyright (C) 2026 H.SHIONO (MRTKLIB Project)
5 * Copyright (C) 2023-2025 Cabinet Office, Japan
6 * Copyright (C) 2024-2025 Lighthouse Technology & Consulting Co. Ltd.
7 * Copyright (C) 2023-2025 Japan Aerospace Exploration Agency
8 * Copyright (C) 2023-2025 TOSHIBA ELECTRONIC TECHNOLOGIES CORPORATION
9 * Copyright (C) 2015- Mitsubishi Electric Corp.
10 * Copyright (C) 2014 Geospatial Information Authority of Japan
11 * Copyright (C) 2014 T.SUZUKI
12 * Copyright (C) 2007-2023 T.TAKASU
13 *
14 * SPDX-License-Identifier: BSD-2-Clause
15 *----------------------------------------------------------------------------*/
16/**
17 * @file mrtk_obs.c
18 * @brief MRTKLIB Observation Module — Implementation.
19 *
20 * All functions and static data in this file are cut-and-paste extractions
21 * from the legacy rtkcmn.c with zero algorithmic changes.
22 */
23
24#include "mrtklib/mrtk_obs.h"
25
26#include <math.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include "mrtklib/mrtk_nav.h"
32#include "mrtklib/mrtk_opt.h"
33#include "mrtklib/mrtk_trace.h"
34
35/*============================================================================
36 * Forward Declarations (resolved at link time)
37 *===========================================================================*/
38
39/* satsys remains in mrtk_nav.c */
40extern int satsys(int sat, int* prn);
41
42/* timediff, time2gpst remain in mrtk_time.c */
43extern double timediff(gtime_t t1, gtime_t t2);
44extern double time2gpst(gtime_t t, int* week);
45
46/*============================================================================
47 * Private Constants
48 *===========================================================================*/
49
50#define PI 3.1415926535897932 /* pi */
51#define R2D (180.0 / PI) /* rad to deg */
52
53#define SYS_NONE 0x00 /* navigation system: none */
54#define SYS_GPS 0x01 /* navigation system: GPS */
55#define SYS_SBS 0x02 /* navigation system: SBAS */
56#define SYS_GLO 0x04 /* navigation system: GLONASS */
57#define SYS_GAL 0x08 /* navigation system: Galileo */
58#define SYS_QZS 0x10 /* navigation system: QZSS */
59#define SYS_CMP 0x20 /* navigation system: BeiDou */
60#define SYS_IRN 0x40 /* navigation system: NavIC */
61#define SYS_LEO 0x80 /* navigation system: LEO */
62#define SYS_BD2 0x100 /* navigation system: BeiDou-2 */
63#define SYS_ALL 0xFF /* navigation system: all */
64
65#define MAXFREQ 7 /* max NFREQ */
66
67#define FREQ1 1.57542E9 /* L1/E1/B1C frequency (Hz) */
68#define FREQ2 1.22760E9 /* L2 frequency (Hz) */
69#define FREQ5 1.17645E9 /* L5/E5a/B2a frequency (Hz) */
70#define FREQ6 1.27875E9 /* E6/L6 frequency (Hz) */
71#define FREQ7 1.20714E9 /* E5b frequency (Hz) */
72#define FREQ8 1.191795E9 /* E5a+b frequency (Hz) */
73#define FREQ9 2.492028E9 /* S frequency (Hz) */
74#define FREQ1_GLO 1.60200E9 /* GLONASS G1 base frequency (Hz) */
75#define DFRQ1_GLO 0.56250E6 /* GLONASS G1 bias frequency (Hz/n) */
76#define FREQ2_GLO 1.24600E9 /* GLONASS G2 base frequency (Hz) */
77#define DFRQ2_GLO 0.43750E6 /* GLONASS G2 bias frequency (Hz/n) */
78#define FREQ3_GLO 1.202025E9 /* GLONASS G3 frequency (Hz) */
79#define FREQ1a_GLO 1.600995E9 /* GLONASS G1a frequency (Hz) */
80#define FREQ2a_GLO 1.248060E9 /* GLONASS G2a frequency (Hz) */
81#define FREQ1_CMP 1.561098E9 /* BDS B1I frequency (Hz) */
82#define FREQ2_CMP 1.20714E9 /* BDS B2I/B2b frequency (Hz) */
83#define FREQ3_CMP 1.26852E9 /* BDS B3 frequency (Hz) */
84
85/*============================================================================
86 * Static Data Arrays
87 *===========================================================================*/
88
89static char* obscodes[] = {
90 /* observation code strings */
91
92 "", "1C", "1P", "1W", "1Y", "1M", "1N", "1S", "1L", "1E", /* 0- 9 */
93 "1A", "1B", "1X", "1Z", "2C", "2D", "2S", "2L", "2X", "2P", /* 10-19 */
94 "2W", "2Y", "2M", "2N", "5I", "5Q", "5X", "7I", "7Q", "7X", /* 20-29 */
95 "6A", "6B", "6C", "6X", "6Z", "6S", "6L", "8L", "8Q", "8X", /* 30-39 */
96 "2I", "2Q", "6I", "6Q", "3I", "3Q", "3X", "1I", "1Q", "5A", /* 40-49 */
97 "5B", "5C", "9A", "9B", "9C", "9X", "1D", "5D", "5P", "5Z", /* 50-59 */
98 "6E", "7D", "7P", "7Z", "8D", "8P", "4A", "4B", "4X", "6D", /* 60-69 */
99 "6P", "" /* 70- */
100};
101
102/*============================================================================
103 * Private Functions
104 *===========================================================================*/
105
106/* compare observation data -------------------------------------------------*/
107static int cmpobs(const void* p1, const void* p2) {
108 obsd_t *q1 = (obsd_t*)p1, *q2 = (obsd_t*)p2;
109 double tt = timediff(q1->time, q2->time);
110 if (fabs(tt) > DTTOL) {
111 return tt < 0 ? -1 : 1;
112 }
113 if (q1->rcv != q2->rcv) {
114 return (int)q1->rcv - (int)q2->rcv;
115 }
116 return (int)q1->sat - (int)q2->sat;
117}
118
119/*============================================================================
120 * Public Functions
121 *===========================================================================*/
122
123/* test SNR mask ---------------------------------------------------------------
124 * test SNR mask
125 * args : int base I rover or base-station (0:rover,1:base station)
126 * int idx I frequency index (0:L1,1:L2,2:L3,...)
127 * double el I elevation angle (rad)
128 * double snr I C/N0 (dBHz)
129 * snrmask_t *mask I SNR mask
130 * return : status (1:masked,0:unmasked)
131 *-----------------------------------------------------------------------------*/
132extern int testsnr(int base, int idx, double el, double snr, const snrmask_t* mask) {
133 double minsnr, a;
134 int i;
135
136 if (!mask->ena[base] || idx < 0 || idx >= NFREQ) {
137 return 0;
138 }
139
140 a = (el * R2D + 5.0) / 10.0;
141 i = (int)floor(a);
142 a -= i;
143 if (i < 1) {
144 minsnr = mask->mask[idx][0];
145 } else if (i > 8) {
146 minsnr = mask->mask[idx][8];
147 } else {
148 minsnr = (1.0 - a) * mask->mask[idx][i - 1] + a * mask->mask[idx][i];
149 }
150
151 return snr < minsnr;
152}
153/* test elevation mask ---------------------------------------------------------
154 * test elevation mask
155 * args : double *azel I azimuth/elevation angle {az,el} (rad)
156 * int16_t *elmask I elevation mask vector (360 x 1) (0.1 deg)
157 * elmask[i]: elevation mask at azimuth i (deg)
158 * return : status (1:masked,0:unmasked)
159 *-----------------------------------------------------------------------------*/
160extern int testelmask(const double* azel, const int16_t* elmask) {
161 double az = azel[0] * R2D;
162
163 az -= floor(az / 360.0) * 360.0; /* 0 <= az < 360.0 */
164
165 return azel[1] * R2D < elmask[(int)floor(az)] * 0.1;
166}
167/* obs type string to obs code -------------------------------------------------
168 * convert obs code type string to obs code
169 * args : char *str I obs code string ("1C","1P","1Y",...)
170 * return : obs code (CODE_???)
171 * notes : obs codes are based on RINEX 3.04
172 *-----------------------------------------------------------------------------*/
173extern uint8_t obs2code(const char* obs) {
174 int i;
175
176 for (i = 1; *obscodes[i]; i++) {
177 if (strcmp(obscodes[i], obs)) {
178 continue;
179 }
180 return (uint8_t)i;
181 }
182 return CODE_NONE;
183}
184/* obs code to obs code string -------------------------------------------------
185 * convert obs code to obs code string
186 * args : uint8_t code I obs code (CODE_???)
187 * return : obs code string ("1C","1P","1P",...)
188 * notes : obs codes are based on RINEX 3.05
189 *-----------------------------------------------------------------------------*/
190extern char* code2obs(uint8_t code) {
191 if (code <= CODE_NONE || MAXCODE < code) {
192 return "";
193 }
194 return obscodes[code];
195}
196/* obs code to frequency number ------------------------------------------------
197 * extract frequency number from obs code
198 * args : uint8_t code I obs code (CODE_???)
199 * return : frequency number (1,2,5,...) (0: error)
200 *-----------------------------------------------------------------------------*/
201extern int code2freq_num(uint8_t code) {
202 char str[2] = {0};
203 char* obs = code2obs(code);
204 if (strlen(obs) < 2) {
205 return 0;
206 }
207 str[0] = obs[0];
208 return atoi(str);
209}
210/* system and obs code to frequency index (obsdef-based) -----------------------
211 * convert system and obs code to frequency index using obsdef tables
212 * args : int sys I satellite system (SYS_???)
213 * uint8_t code I obs code (CODE_???)
214 * return : frequency index (-1: error)
215 * freq-index 0 1 2 3 4
216 * -----------------------------------------------------
217 * GPS L1 L2 L5 - -
218 * GLONASS G1 G2 - - -
219 * Galileo E1 E5a E5b E6 E5a+b
220 * QZSS L1 L5 L2 L6 -
221 * SBAS L1 L5 - - -
222 * BDS B1I B3I B2I/B2b B1C B2a
223 * NavIC L5 S - - -
224 *-----------------------------------------------------------------------------*/
225extern int code2freq_idx(int sys, uint8_t code) {
226 int fn = code2freq_num(code);
227 return freq_num2freq_idx(sys, fn);
228}
229/* system and obs code to frequency --------------------------------------------
230 * convert system and obs code to carrier frequency
231 * args : int sys I satellite system (SYS_???)
232 * uint8_t code I obs code (CODE_???)
233 * int fcn I frequency channel number for GLONASS
234 * return : carrier frequency (Hz) (0.0: error)
235 *-----------------------------------------------------------------------------*/
236extern double code2freq(int sys, uint8_t code, int fcn) { return freq_num2freq(sys, code2freq_num(code), fcn); }
237/* satellite and obs code to frequency -----------------------------------------
238 * convert satellite and obs code to carrier frequency
239 * args : int sat I satellite number
240 * uint8_t code I obs code (CODE_???)
241 * nav_t *nav_t I navigation data for GLONASS (NULL: not used)
242 * return : carrier frequency (Hz) (0.0: error)
243 *-----------------------------------------------------------------------------*/
244extern double sat2freq(int sat, uint8_t code, const nav_t* nav) {
245 int i, fcn = 0, sys, prn;
246
247 sys = satsys_bd2(sat, &prn);
248
249 if (sys == SYS_GLO) {
250 if (!nav) {
251 return 0.0;
252 }
253 for (i = 0; i < nav->ng; i++) {
254 if (nav->geph[i].sat == sat) {
255 break;
256 }
257 }
258 if (i < nav->ng) {
259 fcn = nav->geph[i].frq;
260 } else if (nav->glo_fcn[prn - 1] > 0) {
261 fcn = nav->glo_fcn[prn - 1] - 8;
262 } else {
263 return 0.0;
264 }
265 }
266 return code2freq(sys, code, fcn);
267}
268/* get code priority -----------------------------------------------------------
269 * get code priority for multiple codes in a frequency
270 * uses structured SIG_PRIORITY_TABLE via mrtk_get_signal_priority()
271 * args : int sys I system (SYS_???)
272 * uint8_t code I obs code (CODE_???)
273 * char *opt I code options (NULL:no option)
274 * return : priority (15:highest-1:lowest,0:error)
275 *-----------------------------------------------------------------------------*/
276extern int getcodepri(int sys, uint8_t code, const char* opt) {
277 const char *p, *optstr;
278 const uint8_t* plist;
279 mrtk_band_t band;
280 char *obs, str[8] = "";
281 int freq_num, i;
282
283 if (sys == SYS_BD2) {
284 sys = SYS_CMP;
285 }
286
287 switch (sys) {
288 case SYS_GPS:
289 optstr = "-GL%2s";
290 break;
291 case SYS_GLO:
292 optstr = "-RL%2s";
293 break;
294 case SYS_GAL:
295 optstr = "-EL%2s";
296 break;
297 case SYS_QZS:
298 optstr = "-JL%2s";
299 break;
300 case SYS_SBS:
301 optstr = "-SL%2s";
302 break;
303 case SYS_CMP:
304 optstr = "-CL%2s";
305 break;
306 case SYS_IRN:
307 optstr = "-IL%2s";
308 break;
309 default:
310 return 0;
311 }
312 obs = code2obs(code);
313 if (!obs[0]) {
314 return 0;
315 }
316
317 /* parse code options (opt override: exact match = 15, mismatch = 0) */
318 for (p = opt; p && (p = strchr(p, '-')); p++) {
319 if (sscanf(p, optstr, str) < 1 || str[0] != obs[0]) {
320 continue;
321 }
322 return str[1] == obs[1] ? 15 : 0;
323 }
324
325 /* look up priority from structured table */
326 freq_num = code2freq_num(code);
327 band = mrtk_rinex_freq_to_band(sys, freq_num);
328 if (band == MRTK_BAND_UNKNOWN) {
329 return 0;
330 }
331 plist = mrtk_get_signal_priority(sys, band);
332 if (!plist) {
333 return 0;
334 }
335 for (i = 0; i < MRTK_MAX_SIG_PRIORITY; i++) {
336 if (plist[i] == 0) {
337 break;
338 }
339 if (plist[i] == code) {
340 return 14 - i; /* 14=highest .. 1=lowest, matching legacy range */
341 }
342 }
343 return 0;
344}
345/* sort and unique observation data --------------------------------------------
346 * sort and unique observation data by time, rcv, sat
347 * args : obs_t *obs IO observation data
348 * return : number of epochs
349 *-----------------------------------------------------------------------------*/
350extern int sortobs(obs_t* obs) {
351 int i, j, n;
352
353 trace(NULL, 3, "sortobs: nobs=%d\n", obs->n);
354
355 if (obs->n <= 0) {
356 return 0;
357 }
358
359 qsort(obs->data, obs->n, sizeof(obsd_t), cmpobs);
360
361 /* delete duplicated data */
362 for (i = j = 0; i < obs->n; i++) {
363 if (obs->data[i].sat != obs->data[j].sat || obs->data[i].rcv != obs->data[j].rcv ||
364 timediff(obs->data[i].time, obs->data[j].time) != 0.0) {
365 obs->data[++j] = obs->data[i];
366 }
367 }
368 obs->n = j + 1;
369
370 for (i = n = 0; i < obs->n; i = j, n++) {
371 for (j = i + 1; j < obs->n; j++) {
372 if (timediff(obs->data[j].time, obs->data[i].time) > DTTOL) {
373 break;
374 }
375 }
376 }
377 return n;
378}
379
380/* signal replace --------------------------------------------------------------
381 * replaces the observation data in the obs structure with the data specified
382 * by the given frequency and signal code at the specified index
383 * args : obs_t *obs IO observation data
384 * int idx I observation index
385 * char f I freqency number
386 * char *c I code type
387 *-----------------------------------------------------------------------------*/
388extern void signal_replace(obsd_t* obs, int idx, char f, char* c) {
389 int i, j;
390 char* code;
391
392 for (i = 0; i < NFREQ + NEXOBS; i++) {
393 code = code2obs(obs->code[i]);
394 for (j = 0; c[j] != '\0'; j++) {
395 if (code[0] == f && code[1] == c[j]) {
396 break;
397 }
398 }
399 if (c[j] != '\0') {
400 break;
401 }
402 }
403 if (i < NFREQ + NEXOBS) {
404 obs->SNR[idx] = obs->SNR[i];
405 obs->LLI[idx] = obs->LLI[i];
406 obs->code[idx] = obs->code[i];
407 obs->L[idx] = obs->L[i];
408 obs->P[idx] = obs->P[i];
409 obs->D[idx] = obs->D[i];
410 } else {
411 obs->SNR[idx] = obs->LLI[idx] = obs->code[idx] = 0;
412 obs->P[idx] = obs->L[idx] = obs->D[idx] = 0.0;
413 }
414}
415
416/* screen by time --------------------------------------------------------------
417 * screening by time start, time end, and time interval
418 * args : gtime_t time I time
419 * gtime_t ts I time start (ts.time==0:no screening by ts)
420 * gtime_t te I time end (te.time==0:no screening by te)
421 * double tint I time interval (s) (0.0:no screen by tint)
422 * return : 1:on condition, 0:not on condition
423 *-----------------------------------------------------------------------------*/
424extern int screent(gtime_t time, gtime_t ts, gtime_t te, double tint) {
425 return (tint <= 0.0 || fmod(time2gpst(time, NULL) + DTTOL, tint) <= DTTOL * 2.0) &&
426 (ts.time == 0 || timediff(time, ts) >= -DTTOL) && (te.time == 0 || timediff(time, te) < DTTOL);
427}
428/* free observation data -------------------------------------------------------
429 * free memory for observation data
430 * args : obs_t *obs IO observation data
431 * return : none
432 *-----------------------------------------------------------------------------*/
433extern void freeobs(obs_t* obs) {
434 free(obs->data);
435 obs->data = NULL;
436 obs->n = obs->nmax = 0;
437}
438
439/*============================================================================
440 * Structured Signal Priority Table
441 *
442 * Derived from RTKLIB 2.4.3 b34 codepris[] (rinex.c), matched to MRTKLIB's
443 * obsdef tables (mrtk_nav.c). Each codes[] array lists observation codes in
444 * descending priority order; remaining slots are zero-initialized.
445 *===========================================================================*/
446
451
452/* clang-format off */
454 /* GPS — obsdef: "CPYWMNSL", "PYWCMNDLSX", "QXI" */
455 {
456 .sys = SYS_GPS,
457 .priority = {
458 .band = MRTK_BAND_GPS_L1,
459 .codes = {
460 CODE_L1C,
461 CODE_L1P,
462 CODE_L1Y,
463 CODE_L1W,
464 CODE_L1M,
465 CODE_L1N,
466 CODE_L1S,
467 CODE_L1L,
468 },
469 },
470 },
471 {
472 .sys = SYS_GPS,
473 .priority = {
474 .band = MRTK_BAND_GPS_L2,
475 .codes = {
476 CODE_L2P,
477 CODE_L2Y,
478 CODE_L2W,
479 CODE_L2C,
480 CODE_L2M,
481 CODE_L2N,
482 CODE_L2D,
483 CODE_L2L,
484 CODE_L2S,
485 CODE_L2X,
486 },
487 },
488 },
489 {
490 .sys = SYS_GPS,
491 .priority = {
492 .band = MRTK_BAND_GPS_L5,
493 .codes = {
494 CODE_L5Q,
495 CODE_L5X,
496 CODE_L5I,
497 },
498 },
499 },
500
501 /* GLONASS — obsdef: "CP", "CP", (G3 not in obsdef but kept for completeness) */
502 {
503 .sys = SYS_GLO,
504 .priority = {
505 .band = MRTK_BAND_GLO_G1,
506 .codes = {
507 CODE_L1C,
508 CODE_L1P,
509 },
510 },
511 },
512 {
513 .sys = SYS_GLO,
514 .priority = {
515 .band = MRTK_BAND_GLO_G2,
516 .codes = {
517 CODE_L2C,
518 CODE_L2P,
519 },
520 },
521 },
522 {
523 .sys = SYS_GLO,
524 .priority = {
525 .band = MRTK_BAND_GLO_G3,
526 .codes = {
527 CODE_L3I,
528 CODE_L3Q,
529 CODE_L3X,
530 },
531 },
532 },
533
534 /* Galileo — obsdef: "CABXZ", "QXI", "QXI", "CXE", "QXI" */
535 {
536 .sys = SYS_GAL,
537 .priority = {
538 .band = MRTK_BAND_GAL_E1,
539 .codes = {
540 CODE_L1C,
541 CODE_L1A,
542 CODE_L1B,
543 CODE_L1X,
544 CODE_L1Z,
545 },
546 },
547 },
548 {
549 .sys = SYS_GAL,
550 .priority = {
551 .band = MRTK_BAND_GAL_E5a,
552 .codes = {
553 CODE_L5Q,
554 CODE_L5X,
555 CODE_L5I,
556 },
557 },
558 },
559 {
560 .sys = SYS_GAL,
561 .priority = {
562 .band = MRTK_BAND_GAL_E5b,
563 .codes = {
564 CODE_L7Q,
565 CODE_L7X,
566 CODE_L7I,
567 },
568 },
569 },
570 {
571 .sys = SYS_GAL,
572 .priority = {
573 .band = MRTK_BAND_GAL_E6,
574 .codes = {
575 CODE_L6C,
576 CODE_L6X,
577 CODE_L6E,
578 },
579 },
580 },
581 {
582 .sys = SYS_GAL,
583 .priority = {
584 .band = MRTK_BAND_GAL_E5ab,
585 .codes = {
586 CODE_L8Q,
587 CODE_L8X,
588 CODE_L8I,
589 },
590 },
591 },
592
593 /* QZSS — obsdef: "LXSCE", "QXI", "LXS", "SEZ" */
594 {
595 .sys = SYS_QZS,
596 .priority = {
597 .band = MRTK_BAND_QZS_L1,
598 .codes = {
599 CODE_L1L,
600 CODE_L1X,
601 CODE_L1S,
602 CODE_L1C,
603 CODE_L1E,
604 },
605 },
606 },
607 {
608 .sys = SYS_QZS,
609 .priority = {
610 .band = MRTK_BAND_QZS_L5,
611 .codes = {
612 CODE_L5Q,
613 CODE_L5X,
614 CODE_L5I,
615 },
616 },
617 },
618 {
619 .sys = SYS_QZS,
620 .priority = {
621 .band = MRTK_BAND_QZS_L2,
622 .codes = {
623 CODE_L2L,
624 CODE_L2X,
625 CODE_L2S,
626 },
627 },
628 },
629 {
630 .sys = SYS_QZS,
631 .priority = {
632 .band = MRTK_BAND_QZS_L6,
633 .codes = {
634 CODE_L6S,
635 CODE_L6E,
636 CODE_L6Z,
637 },
638 },
639 },
640
641 /* SBAS — obsdef: "C", "IQX" */
642 {
643 .sys = SYS_SBS,
644 .priority = {
645 .band = MRTK_BAND_SBS_L1,
646 .codes = {
647 CODE_L1C,
648 },
649 },
650 },
651 {
652 .sys = SYS_SBS,
653 .priority = {
654 .band = MRTK_BAND_SBS_L5,
655 .codes = {
656 CODE_L5I,
657 CODE_L5Q,
658 CODE_L5X,
659 },
660 },
661 },
662
663 /* BDS — obsdef: "IQX"(B1I), "IQX"(B3), "DIQX"(B2b), "PXD"(B1C), "PXD"(B2a), "PXD"(B2ab) */
664 {
665 .sys = SYS_CMP,
666 .priority = {
667 .band = MRTK_BAND_BDS_B1I,
668 .codes = {
669 CODE_L2I,
670 CODE_L2Q,
671 CODE_L2X,
672 },
673 },
674 },
675 {
676 .sys = SYS_CMP,
677 .priority = {
678 .band = MRTK_BAND_BDS_B3,
679 .codes = {
680 CODE_L6I,
681 CODE_L6Q,
682 CODE_L6X,
683 },
684 },
685 },
686 {
687 .sys = SYS_CMP,
688 .priority = {
689 .band = MRTK_BAND_BDS_B2b,
690 .codes = {
691 CODE_L7D,
692 CODE_L7I,
693 CODE_L7Q,
694 CODE_L7X,
695 },
696 },
697 },
698 {
699 .sys = SYS_CMP,
700 .priority = {
701 .band = MRTK_BAND_BDS_B1C,
702 .codes = {
703 CODE_L1P,
704 CODE_L1X,
705 CODE_L1D,
706 },
707 },
708 },
709 {
710 .sys = SYS_CMP,
711 .priority = {
712 .band = MRTK_BAND_BDS_B2a,
713 .codes = {
714 CODE_L5P,
715 CODE_L5X,
716 CODE_L5D,
717 },
718 },
719 },
720 {
721 .sys = SYS_CMP,
722 .priority = {
723 .band = MRTK_BAND_BDS_B2ab,
724 .codes = {
725 CODE_L8P,
726 CODE_L8X,
727 CODE_L8D,
728 },
729 },
730 },
731
732 /* NavIC/IRNSS — obsdef: "ABCX", "ABCX" */
733 {
734 .sys = SYS_IRN,
735 .priority = {
736 .band = MRTK_BAND_IRN_L5,
737 .codes = {
738 CODE_L5A,
739 CODE_L5B,
740 CODE_L5C,
741 CODE_L5X,
742 },
743 },
744 },
745 {
746 .sys = SYS_IRN,
747 .priority = {
748 .band = MRTK_BAND_IRN_S,
749 .codes = {
750 CODE_L9A,
751 CODE_L9B,
752 CODE_L9C,
753 CODE_L9X,
754 },
755 },
756 },
757};
758/* clang-format on */
759
760/* mrtk_band2freq_hz: physical band -> base carrier frequency -----------------
761 * convert mrtk_band_t to base carrier frequency in Hz.
762 * for GLONASS G1/G2, returns the base frequency without FDMA offset.
763 * args : mrtk_band_t band I physical frequency band
764 * return : base carrier frequency (Hz), 0.0 on error
765 *----------------------------------------------------------------------------*/
766extern double mrtk_band2freq_hz(mrtk_band_t band) {
767 /* clang-format off */
768 switch (band) {
769 case MRTK_BAND_GPS_L1: return FREQ1;
770 case MRTK_BAND_GPS_L2: return FREQ2;
771 case MRTK_BAND_GPS_L5: return FREQ5;
772 case MRTK_BAND_GLO_G1: return FREQ1_GLO;
773 case MRTK_BAND_GLO_G2: return FREQ2_GLO;
774 case MRTK_BAND_GLO_G3: return FREQ3_GLO;
775 case MRTK_BAND_GAL_E1: return FREQ1;
776 case MRTK_BAND_GAL_E5a: return FREQ5;
777 case MRTK_BAND_GAL_E5b: return FREQ7;
778 case MRTK_BAND_GAL_E6: return FREQ6;
779 case MRTK_BAND_GAL_E5ab:return FREQ8;
780 case MRTK_BAND_QZS_L1: return FREQ1;
781 case MRTK_BAND_QZS_L2: return FREQ2;
782 case MRTK_BAND_QZS_L5: return FREQ5;
783 case MRTK_BAND_QZS_L6: return FREQ6;
784 case MRTK_BAND_SBS_L1: return FREQ1;
785 case MRTK_BAND_SBS_L5: return FREQ5;
786 case MRTK_BAND_BDS_B1I: return FREQ1_CMP;
787 case MRTK_BAND_BDS_B1C: return FREQ1;
788 case MRTK_BAND_BDS_B2a: return FREQ5;
789 case MRTK_BAND_BDS_B2b: return FREQ2_CMP;
790 case MRTK_BAND_BDS_B2ab:return FREQ8;
791 case MRTK_BAND_BDS_B3: return FREQ3_CMP;
792 case MRTK_BAND_IRN_L5: return FREQ5;
793 case MRTK_BAND_IRN_S: return FREQ9;
794 default: return 0.0;
795 }
796 /* clang-format on */
797}
798
799/* mrtk_rinex_freq_to_band: RINEX frequency digit -> physical band -----------
800 * convert RINEX frequency digit (1,2,3,...,9) to mrtk_band_t for a given
801 * satellite system.
802 * args : int sys I satellite system (SYS_???)
803 * int rinex_freq_id I RINEX frequency digit
804 * return : mrtk_band_t (MRTK_BAND_UNKNOWN on error)
805 *----------------------------------------------------------------------------*/
806extern mrtk_band_t mrtk_rinex_freq_to_band(int sys, int rinex_freq_id) {
807 switch (sys) {
808 case SYS_GPS:
809 switch (rinex_freq_id) {
810 case 1:
811 return MRTK_BAND_GPS_L1;
812 case 2:
813 return MRTK_BAND_GPS_L2;
814 case 5:
815 return MRTK_BAND_GPS_L5;
816 }
817 break;
818 case SYS_GLO:
819 switch (rinex_freq_id) {
820 case 1:
821 case 4:
822 return MRTK_BAND_GLO_G1; /* G1 FDMA + G1a CDMA */
823 case 2:
824 case 6:
825 return MRTK_BAND_GLO_G2; /* G2 FDMA + G2a CDMA */
826 case 3:
827 return MRTK_BAND_GLO_G3;
828 }
829 break;
830 case SYS_GAL:
831 switch (rinex_freq_id) {
832 case 1:
833 return MRTK_BAND_GAL_E1;
834 case 5:
835 return MRTK_BAND_GAL_E5a;
836 case 7:
837 return MRTK_BAND_GAL_E5b;
838 case 8:
839 return MRTK_BAND_GAL_E5ab;
840 case 6:
841 return MRTK_BAND_GAL_E6;
842 }
843 break;
844 case SYS_QZS:
845 switch (rinex_freq_id) {
846 case 1:
847 return MRTK_BAND_QZS_L1;
848 case 2:
849 return MRTK_BAND_QZS_L2;
850 case 5:
851 return MRTK_BAND_QZS_L5;
852 case 6:
853 return MRTK_BAND_QZS_L6;
854 }
855 break;
856 case SYS_SBS:
857 switch (rinex_freq_id) {
858 case 1:
859 return MRTK_BAND_SBS_L1;
860 case 5:
861 return MRTK_BAND_SBS_L5;
862 }
863 break;
864 case SYS_CMP:
865 switch (rinex_freq_id) {
866 case 1:
867 return MRTK_BAND_BDS_B1C;
868 case 2:
869 return MRTK_BAND_BDS_B1I;
870 case 5:
871 return MRTK_BAND_BDS_B2a;
872 case 7:
873 return MRTK_BAND_BDS_B2b;
874 case 8:
875 return MRTK_BAND_BDS_B2ab;
876 case 6:
877 return MRTK_BAND_BDS_B3;
878 }
879 break;
880 case SYS_IRN:
881 switch (rinex_freq_id) {
882 case 5:
883 return MRTK_BAND_IRN_L5;
884 case 9:
885 return MRTK_BAND_IRN_S;
886 }
887 break;
888 default:
889 break;
890 }
891 return MRTK_BAND_UNKNOWN;
892}
893
894/* claslib-compatible QZSS L1 priority ("CSLXZ"), applied only while CLAS
895 * processing is active: upstream claslib and MADOCALIB genuinely disagree on
896 * the QZSS L1 order, so the claslib order must not leak into other engines
897 * (it moves MADOCA-PPP solutions by centimetres against their references). */
901static int qzs_l1_claslib = 0;
902
903/* mrtk_use_claslib_qzs_l1_priority: toggle claslib QZSS L1 signal priority ---
904 * args : int on I 1: claslib order (C>S>L>X>Z), 0: MRTK default order
905 *----------------------------------------------------------------------------*/
907
908/* mrtk_get_signal_priority: get priority-ordered code list -------------------
909 * look up the priority-ordered observation code list for a (system, band) pair
910 * args : int sys I satellite system (SYS_???)
911 * mrtk_band_t band I physical frequency band
912 * return : pointer to code array (MRTK_MAX_SIG_PRIORITY elements), or NULL
913 *----------------------------------------------------------------------------*/
914extern const uint8_t* mrtk_get_signal_priority(int sys, mrtk_band_t band) {
915 int i;
916
917 if (band == MRTK_BAND_UNKNOWN || band >= MRTK_BAND_MAX) {
918 return NULL;
919 }
920 if (qzs_l1_claslib && sys == SYS_QZS && band == MRTK_BAND_QZS_L1) {
922 }
923 for (i = 0; i < (int)(sizeof(SIG_PRIORITY_TABLE) / sizeof(SIG_PRIORITY_TABLE[0])); i++) {
924 if (SIG_PRIORITY_TABLE[i].sys == sys && SIG_PRIORITY_TABLE[i].priority.band == band) {
925 return SIG_PRIORITY_TABLE[i].priority.codes;
926 }
927 }
928 return NULL;
929}
930
931/* mrtk_band_to_freq_num: physical band -> RINEX frequency number ------------
932 * reverse of mrtk_rinex_freq_to_band(). Converts mrtk_band_t back to the
933 * RINEX frequency digit for a given satellite system.
934 * args : int sys I satellite system (SYS_???)
935 * mrtk_band_t band I physical frequency band
936 * return : RINEX frequency number (1,2,5,...) or 0 on error
937 *----------------------------------------------------------------------------*/
938extern int mrtk_band_to_freq_num(int sys, mrtk_band_t band) {
939 switch (sys) {
940 case SYS_GPS:
941 switch (band) {
942 case MRTK_BAND_GPS_L1:
943 return 1;
944 case MRTK_BAND_GPS_L2:
945 return 2;
946 case MRTK_BAND_GPS_L5:
947 return 5;
948 default:
949 return 0;
950 }
951 case SYS_GLO:
952 switch (band) {
953 case MRTK_BAND_GLO_G1:
954 return 1;
955 case MRTK_BAND_GLO_G2:
956 return 2;
957 case MRTK_BAND_GLO_G3:
958 return 3;
959 default:
960 return 0;
961 }
962 case SYS_GAL:
963 switch (band) {
964 case MRTK_BAND_GAL_E1:
965 return 1;
967 return 5;
969 return 7;
970 case MRTK_BAND_GAL_E6:
971 return 6;
973 return 8;
974 default:
975 return 0;
976 }
977 case SYS_QZS:
978 switch (band) {
979 case MRTK_BAND_QZS_L1:
980 return 1;
981 case MRTK_BAND_QZS_L2:
982 return 2;
983 case MRTK_BAND_QZS_L5:
984 return 5;
985 case MRTK_BAND_QZS_L6:
986 return 6;
987 default:
988 return 0;
989 }
990 case SYS_SBS:
991 switch (band) {
992 case MRTK_BAND_SBS_L1:
993 return 1;
994 case MRTK_BAND_SBS_L5:
995 return 5;
996 default:
997 return 0;
998 }
999 case SYS_CMP:
1000 switch (band) {
1001 case MRTK_BAND_BDS_B1C:
1002 return 1;
1003 case MRTK_BAND_BDS_B1I:
1004 return 2;
1005 case MRTK_BAND_BDS_B2a:
1006 return 5;
1007 case MRTK_BAND_BDS_B3:
1008 return 6;
1009 case MRTK_BAND_BDS_B2b:
1010 return 7;
1011 case MRTK_BAND_BDS_B2ab:
1012 return 8;
1013 default:
1014 return 0;
1015 }
1016 case SYS_IRN:
1017 switch (band) {
1018 case MRTK_BAND_IRN_L5:
1019 return 5;
1020 case MRTK_BAND_IRN_S:
1021 return 9;
1022 default:
1023 return 0;
1024 }
1025 default:
1026 return 0;
1027 }
1028}
1029
1030/* mrtk_parse_signal_str: parse RINEX3-style signal string -------------------
1031 * parse a signal string like "G1C" into (system, band, code) components.
1032 * format: {sys_char}{freq_digit}{attr_char} (3 chars)
1033 * args : const char *str I signal string (e.g., "G1C", "E5Q", "J2X")
1034 * int *sys O satellite system (SYS_???)
1035 * mrtk_band_t *band O physical frequency band
1036 * uint8_t *code O observation code (CODE_???)
1037 * return : 0: success, -1: error
1038 *----------------------------------------------------------------------------*/
1039extern int mrtk_parse_signal_str(const char* str, int* sys, mrtk_band_t* band, uint8_t* code) {
1040 char obs_str[3];
1041 int freq_digit;
1042
1043 if (!str || strlen(str) < 3) {
1044 return -1;
1045 }
1046
1047 /* parse system character */
1048 switch (str[0]) {
1049 case 'G':
1050 *sys = SYS_GPS;
1051 break;
1052 case 'R':
1053 *sys = SYS_GLO;
1054 break;
1055 case 'E':
1056 *sys = SYS_GAL;
1057 break;
1058 case 'J':
1059 *sys = SYS_QZS;
1060 break;
1061 case 'S':
1062 *sys = SYS_SBS;
1063 break;
1064 case 'C':
1065 *sys = SYS_CMP;
1066 break;
1067 case 'I':
1068 *sys = SYS_IRN;
1069 break;
1070 default:
1071 return -1;
1072 }
1073
1074 /* parse frequency digit */
1075 freq_digit = str[1] - '0';
1076 if (freq_digit < 1 || freq_digit > 9) {
1077 return -1;
1078 }
1079 *band = mrtk_rinex_freq_to_band(*sys, freq_digit);
1080 if (*band == MRTK_BAND_UNKNOWN) {
1081 return -1;
1082 }
1083
1084 /* parse observation code: freq_digit + attribute char → obs code string */
1085 obs_str[0] = str[1]; /* freq digit */
1086 obs_str[1] = str[2]; /* attribute char */
1087 obs_str[2] = '\0';
1088 *code = obs2code(obs_str);
1089 if (*code == CODE_NONE) {
1090 return -1;
1091 }
1092
1093 return 0;
1094}
1095
1096/* sys index for sigcfg array ------------------------------------------------*/
1097static int sys2sigcfg_idx(int sys) {
1098 switch (sys) {
1099 case SYS_GPS:
1100 return 0;
1101 case SYS_GLO:
1102 return 1;
1103 case SYS_GAL:
1104 return 2;
1105 case SYS_QZS:
1106 return 3;
1107 case SYS_SBS:
1108 return 4;
1109 case SYS_CMP:
1110 return 5;
1111 case SYS_IRN:
1112 return 6;
1113 default:
1114 return -1;
1115 }
1116}
1117
1118/* mrtk_sigcfg_from_signals: build sigcfg from signal string array -----------
1119 * parse an array of RINEX3-style signal strings (e.g., "G1C", "E5Q") and
1120 * populate per-constellation sigcfg arrays. Also derives nf as the maximum
1121 * number of signals configured for any single constellation.
1122 * args : const char **sigs I array of signal strings
1123 * int nsig I number of signal strings
1124 * mrtk_sigcfg_t *cfg O per-constellation signal config [MRTK_NSYS]
1125 * int *nf O derived number of frequencies
1126 * return : 0: success, -1: error
1127 *----------------------------------------------------------------------------*/
1128extern int mrtk_sigcfg_from_signals(const char** sigs, int nsig, mrtk_sigcfg_t* cfg, int* nf) {
1129 int i, j, sys_idx, max_nf = 0;
1130 int sys;
1131 mrtk_band_t band;
1132 uint8_t code;
1133
1134 if (!sigs || !cfg || !nf || nsig <= 0) {
1135 return -1;
1136 }
1137
1138 /* zero-initialize all configs */
1139 memset(cfg, 0, sizeof(mrtk_sigcfg_t) * MRTK_NSYS);
1140
1141 for (i = 0; i < nsig; i++) {
1142 if (mrtk_parse_signal_str(sigs[i], &sys, &band, &code) != 0) {
1143 trace(NULL, 2, "mrtk_sigcfg_from_signals: invalid signal '%s'\n", sigs[i]);
1144 return -1;
1145 }
1146
1147 sys_idx = sys2sigcfg_idx(sys);
1148 if (sys_idx < 0) {
1149 return -1;
1150 }
1151
1152 if (cfg[sys_idx].nsig >= MRTK_MAXSIG_PER_SYS) {
1153 trace(NULL, 2, "mrtk_sigcfg_from_signals: too many signals for sys=%d\n", sys);
1154 return -1;
1155 }
1156
1157 /* reject duplicate bands within the same constellation */
1158 for (j = 0; j < cfg[sys_idx].nsig; j++) {
1159 if (cfg[sys_idx].sig[j].band == band) {
1160 trace(NULL, 2, "mrtk_sigcfg_from_signals: duplicate band for '%s'\n", sigs[i]);
1161 return -1;
1162 }
1163 }
1164
1165 cfg[sys_idx].sig[cfg[sys_idx].nsig].band = band;
1166 cfg[sys_idx].sig[cfg[sys_idx].nsig].preferred_code = code; /* reserved for future use */
1167 cfg[sys_idx].nsig++;
1168 }
1169
1170 /* derive nf as max signals across all constellations */
1171 for (i = 0; i < MRTK_NSYS; i++) {
1172 if (cfg[i].nsig > max_nf) {
1173 max_nf = cfg[i].nsig;
1174 }
1175 }
1176 *nf = max_nf;
1177
1178 return 0;
1179}
1180
1181/* mrtk_sigcfg_to_obsdef: bridge sigcfg to existing obsdef tables ------------
1182 * for each constellation with nsig > 0, convert sigcfg bands to RINEX
1183 * frequency numbers and call set_obsdef() to rearrange the obsdef table.
1184 * args : const mrtk_sigcfg_t *cfg I per-constellation signal config [MRTK_NSYS]
1185 * return : 0: success, -1: error
1186 *----------------------------------------------------------------------------*/
1187extern int mrtk_sigcfg_to_obsdef(const mrtk_sigcfg_t* cfg) {
1188 static const int sys_list[MRTK_NSYS] = {SYS_GPS, SYS_GLO, SYS_GAL, SYS_QZS, SYS_SBS, SYS_CMP, SYS_IRN};
1189 int freq_nums[MAXFREQ];
1190 int i, j;
1191
1192 if (!cfg) {
1193 return -1;
1194 }
1195
1196 for (i = 0; i < MRTK_NSYS; i++) {
1197 if (cfg[i].nsig <= 0) {
1198 continue;
1199 }
1200
1201 /* build freq_num array from sigcfg bands */
1202 memset(freq_nums, 0, sizeof(freq_nums));
1203 for (j = 0; j < cfg[i].nsig && j < MAXFREQ; j++) {
1204 freq_nums[j] = mrtk_band_to_freq_num(sys_list[i], cfg[i].sig[j].band);
1205 if (freq_nums[j] == 0) {
1206 trace(NULL, 2, "mrtk_sigcfg_to_obsdef: invalid band %d for sys=%02x\n", cfg[i].sig[j].band,
1207 sys_list[i]);
1208 return -1;
1209 }
1210 }
1211
1212 set_obsdef(sys_list[i], freq_nums);
1213 }
1214 return 0;
1215}
1216/* mrtk_sigcfg_freq_idx: sigcfg-driven obs slot for a decoded (sys,code) -------
1217 * #189: see mrtk_obs.h. When a constellation is configured in sigcfg, the
1218 * decoded code is kept only if it is the preferred code for one of the
1219 * configured bands (placed at that band's obsdef slot); any other code — a
1220 * non-preferred code on a configured band, or any code on a non-configured
1221 * band — is dropped. A constellation with no sigcfg entry yields NOOPINION so
1222 * the caller keeps its legacy (-R/-G/... option) behaviour.
1223 *-----------------------------------------------------------------------------*/
1224extern int mrtk_sigcfg_freq_idx(int sys, uint8_t code, const mrtk_sigcfg_t* cfg, int nex) {
1225 int sys_idx = sys2sigcfg_idx(sys);
1226 int fn, base_idx, i;
1227 const mrtk_sigcfg_t* c;
1228
1229 (void)nex; /* non-selected codes are dropped, not retained as extra obs (phase 1) */
1230
1231 if (sys_idx < 0 || !cfg) {
1232 return MRTK_SIGCFG_NOOPINION;
1233 }
1234 c = &cfg[sys_idx];
1235 if (c->nsig <= 0) {
1236 return MRTK_SIGCFG_NOOPINION; /* system not configured: fall back to defaults */
1237 }
1238
1239 fn = code2freq_num(code); /* this code's band (by frequency number) */
1240 for (i = 0; i < c->nsig; i++) {
1241 if (mrtk_band_to_freq_num(sys, c->sig[i].band) != fn) {
1242 continue; /* different band */
1243 }
1244 /* band is configured: accept only the preferred code (0 = auto/any) */
1245 if (c->sig[i].preferred_code == 0 || c->sig[i].preferred_code == code) {
1246 base_idx = code2freq_idx(sys, code);
1247 return (base_idx >= 0 && base_idx < NFREQ) ? base_idx : -1;
1248 }
1249 return -1; /* a different code is preferred for this band */
1250 }
1251 return -1; /* band not configured for this (configured) system */
1252}
#define SYS_GPS
Definition mrtk_eph.c:65
#define SYS_SBS
Definition mrtk_eph.c:66
#define SYS_QZS
Definition mrtk_eph.c:69
#define SYS_IRN
Definition mrtk_eph.c:71
#define SYS_CMP
Definition mrtk_eph.c:70
#define SYS_GAL
Definition mrtk_eph.c:68
#define SYS_GLO
Definition mrtk_eph.c:67
struct nav_s nav_t
Definition mrtk_eph.h:40
#define CODE_L5C
#define CODE_L5Q
#define CODE_L2N
#define CODE_L2Q
#define CODE_L6C
#define CODE_L1S
#define CODE_L5I
#define CODE_L2X
#define CODE_L3X
#define CODE_L6E
#define CODE_L1L
#define CODE_L5X
#define CODE_L7X
#define CODE_L2P
#define CODE_L2I
#define CODE_L6S
#define CODE_L5B
#define MAXCODE
#define CODE_L1C
#define CODE_L6I
#define CODE_L2C
#define CODE_L7I
#define DTTOL
#define CODE_L6X
#define CODE_NONE
#define CODE_L9C
#define CODE_L9A
#define CODE_L1Y
#define CODE_L8Q
#define CODE_L5P
#define CODE_L3Q
#define CODE_L5D
#define CODE_L1E
#define CODE_L8P
#define CODE_L3I
#define CODE_L1B
#define CODE_L7D
#define CODE_L2S
#define CODE_L9X
#define CODE_L7Q
#define CODE_L1W
#define CODE_L8X
#define CODE_L1M
#define CODE_L1N
#define CODE_L2W
#define CODE_L2L
#define CODE_L9B
#define CODE_L1Z
#define CODE_L1D
#define CODE_L5A
#define CODE_L2D
#define CODE_L2Y
#define CODE_L8I
#define CODE_L1P
mrtk_band_t
@ MRTK_BAND_GAL_E1
@ MRTK_BAND_SBS_L5
@ MRTK_BAND_BDS_B1I
@ MRTK_BAND_QZS_L1
@ MRTK_BAND_GAL_E6
@ MRTK_BAND_GAL_E5a
@ MRTK_BAND_BDS_B3
@ MRTK_BAND_BDS_B2b
@ MRTK_BAND_GLO_G3
@ MRTK_BAND_UNKNOWN
@ MRTK_BAND_GPS_L2
@ MRTK_BAND_GLO_G1
@ MRTK_BAND_IRN_L5
@ MRTK_BAND_GAL_E5b
@ MRTK_BAND_BDS_B1C
@ MRTK_BAND_GPS_L1
@ MRTK_BAND_MAX
@ MRTK_BAND_SBS_L1
@ MRTK_BAND_GLO_G2
@ MRTK_BAND_GAL_E5ab
@ MRTK_BAND_QZS_L2
@ MRTK_BAND_BDS_B2a
@ MRTK_BAND_IRN_S
@ MRTK_BAND_BDS_B2ab
@ MRTK_BAND_QZS_L6
@ MRTK_BAND_GPS_L5
@ MRTK_BAND_QZS_L5
#define CODE_L2M
#define CODE_L8D
#define CODE_L6Q
#define CODE_L6Z
#define CODE_L1X
#define CODE_L1A
void set_obsdef(int sys, const int *freq_nums)
Rearrange obsdef table for a satellite system by frequency numbers.
Definition mrtk_nav.c:502
int satsys_bd2(int sat, int *prn)
Distinguish BDS-2 from BDS-3.
Definition mrtk_nav.c:159
double freq_num2freq(int sys, int freq_num, int fcn)
Convert frequency number to frequency in Hz.
Definition mrtk_nav.c:680
int freq_num2freq_idx(int sys, int freq_num)
Convert frequency number to frequency index using obsdef table.
Definition mrtk_nav.c:661
MRTKLIB Navigation Module — Navigation data types and satellite/nav utility functions.
static const uint8_t QZS_L1_PRIORITY_CLASLIB[MRTK_MAX_SIG_PRIORITY]
Definition mrtk_obs.c:898
int satsys(int sat, int *prn)
Definition mrtk_nav.c:117
const uint8_t * mrtk_get_signal_priority(int sys, mrtk_band_t band)
Get priority-ordered code list for a (system, band) pair.
Definition mrtk_obs.c:914
#define FREQ5
Definition mrtk_obs.c:69
int sortobs(obs_t *obs)
Sort observation data by time, receiver, and satellite.
Definition mrtk_obs.c:350
#define FREQ2
Definition mrtk_obs.c:68
#define FREQ8
Definition mrtk_obs.c:72
#define FREQ6
Definition mrtk_obs.c:70
#define FREQ2_CMP
Definition mrtk_obs.c:82
void mrtk_use_claslib_qzs_l1_priority(int on)
Toggle the claslib-compatible QZSS L1 signal priority (C>S>L>X>Z).
Definition mrtk_obs.c:906
#define FREQ9
Definition mrtk_obs.c:73
int getcodepri(int sys, uint8_t code, const char *opt)
Get code priority for multiple codes in a frequency.
Definition mrtk_obs.c:276
#define R2D
Definition mrtk_obs.c:51
int code2freq_num(uint8_t code)
Extract frequency number from obs code.
Definition mrtk_obs.c:201
int mrtk_sigcfg_from_signals(const char **sigs, int nsig, mrtk_sigcfg_t *cfg, int *nf)
Build per-constellation signal config from a signal string array.
Definition mrtk_obs.c:1128
int mrtk_parse_signal_str(const char *str, int *sys, mrtk_band_t *band, uint8_t *code)
Parse a RINEX3-style signal string (e.g., "G1C") into components.
Definition mrtk_obs.c:1039
#define SYS_BD2
Definition mrtk_obs.c:62
int mrtk_sigcfg_freq_idx(int sys, uint8_t code, const mrtk_sigcfg_t *cfg, int nex)
Resolve the observation slot for a decoded (sys, code) from sigcfg.
Definition mrtk_obs.c:1224
#define FREQ7
Definition mrtk_obs.c:71
static int sys2sigcfg_idx(int sys)
Definition mrtk_obs.c:1097
double code2freq(int sys, uint8_t code, int fcn)
Convert system and obs code to carrier frequency.
Definition mrtk_obs.c:236
uint8_t obs2code(const char *obs)
Convert obs code type string to obs code.
Definition mrtk_obs.c:173
#define FREQ1
Definition mrtk_obs.c:67
int mrtk_band_to_freq_num(int sys, mrtk_band_t band)
Convert physical band back to RINEX frequency number for a given system.
Definition mrtk_obs.c:938
#define FREQ2_GLO
Definition mrtk_obs.c:76
double timediff(gtime_t t1, gtime_t t2)
Definition mrtk_time.c:279
#define FREQ1_GLO
Definition mrtk_obs.c:74
double time2gpst(gtime_t t, int *week)
Definition mrtk_time.c:181
static int qzs_l1_claslib
Definition mrtk_obs.c:901
static int cmpobs(const void *p1, const void *p2)
Definition mrtk_obs.c:107
#define FREQ3_CMP
Definition mrtk_obs.c:83
static char * obscodes[]
Definition mrtk_obs.c:89
char * code2obs(uint8_t code)
Convert obs code to obs code string.
Definition mrtk_obs.c:190
int testelmask(const double *azel, const int16_t *elmask)
Test elevation mask.
Definition mrtk_obs.c:160
double mrtk_band2freq_hz(mrtk_band_t band)
Convert physical band to base carrier frequency (Hz).
Definition mrtk_obs.c:766
#define FREQ1_CMP
Definition mrtk_obs.c:81
void freeobs(obs_t *obs)
Free observation data memory.
Definition mrtk_obs.c:433
void signal_replace(obsd_t *obs, int idx, char f, char *c)
Replace signal type in observation data.
Definition mrtk_obs.c:388
int code2freq_idx(int sys, uint8_t code)
Convert system and obs code to frequency index (obsdef-based).
Definition mrtk_obs.c:225
int testsnr(int base, int idx, double el, double snr, const snrmask_t *mask)
Test SNR mask.
Definition mrtk_obs.c:132
int mrtk_sigcfg_to_obsdef(const mrtk_sigcfg_t *cfg)
Apply signal config to obsdef tables (bridge to existing system).
Definition mrtk_obs.c:1187
#define FREQ3_GLO
Definition mrtk_obs.c:78
static const sig_priority_entry_t SIG_PRIORITY_TABLE[]
Definition mrtk_obs.c:453
#define MAXFREQ
Definition mrtk_obs.c:65
int screent(gtime_t time, gtime_t ts, gtime_t te, double tint)
Screen data by time range and interval.
Definition mrtk_obs.c:424
double sat2freq(int sat, uint8_t code, const nav_t *nav)
Convert satellite and obs code to carrier frequency.
Definition mrtk_obs.c:244
mrtk_band_t mrtk_rinex_freq_to_band(int sys, int rinex_freq_id)
Convert RINEX frequency digit to physical band for a given system.
Definition mrtk_obs.c:806
MRTKLIB Observation Module — Observation data types and utility functions.
#define MRTK_SIGCFG_NOOPINION
mrtk_sigcfg_freq_idx() sentinel: this constellation has no sigcfg entry, so the caller should fall ba...
Definition mrtk_obs.h:291
#define MRTK_MAXSIG_PER_SYS
Per-constellation signal configuration.
Definition mrtk_obs.h:193
#define MRTK_MAX_SIG_PRIORITY
Maximum number of codes in a priority list.
Definition mrtk_obs.h:206
#define MRTK_NSYS
Definition mrtk_obs.h:194
MRTKLIB Options Module — Processing and solution option types.
double timediff(gtime_t t1, gtime_t t2)
Compute time difference (t1 - t2).
Definition mrtk_time.c:279
void trace(mrtk_ctx_t *ctx, int level, const char *format,...)
Output trace message.
Definition mrtk_trace.c:78
MRTKLIB Trace Module — debug trace and logging functions.
int sat
Definition mrtk_eph.h:112
int frq
Definition mrtk_eph.h:114
GNSS time representation.
Definition mrtk_time.h:49
time_t time
Definition mrtk_time.h:50
Signal priority entry: band + priority-ordered code list.
Definition mrtk_obs.h:214
mrtk_signal_t sig[7]
Definition mrtk_obs.h:198
uint8_t preferred_code
Definition mrtk_obs.h:187
mrtk_band_t band
Definition mrtk_obs.h:186
int ng
Definition mrtk_nav.h:394
int glo_fcn[32]
Definition mrtk_nav.h:426
geph_t * geph
Definition mrtk_nav.h:407
Observation data collection.
Definition mrtk_obs.h:59
obsd_t * data
Definition mrtk_obs.h:61
int nmax
Definition mrtk_obs.h:60
int n
Definition mrtk_obs.h:60
Observation data record.
Definition mrtk_obs.h:44
float D[5+5]
Definition mrtk_obs.h:52
gtime_t time
Definition mrtk_obs.h:45
uint8_t sat
Definition mrtk_obs.h:46
uint8_t LLI[5+5]
Definition mrtk_obs.h:48
double L[5+5]
Definition mrtk_obs.h:50
uint8_t rcv
Definition mrtk_obs.h:46
double P[5+5]
Definition mrtk_obs.h:51
uint16_t SNR[5+5]
Definition mrtk_obs.h:47
uint8_t code[5+5]
Definition mrtk_obs.h:49
Definition mrtk_obs.c:447
int sys
Definition mrtk_obs.c:448
mrtk_sig_priority_t priority
Definition mrtk_obs.c:449
SNR mask type.
Definition mrtk_obs.h:67
int ena[2]
Definition mrtk_obs.h:68
double mask[5][9]
Definition mrtk_obs.h:69
#define free(x)
Definition toml.c:53