MRTKLIB 0.7.14
Modernized GNSS Positioning Library
Loading...
Searching...
No Matches
mrtk_rtcm3_local_corr.c
Go to the documentation of this file.
1/*------------------------------------------------------------------------------
2 * mrtk_rtcm3_local_corr.c : RTCM3 local correction message encoder/decoder
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_rtcm3_local_corr.c
18 * @brief MRTKLIB RTCM Module — RTCM3 local correction message functions.
19 */
20#include <math.h>
21#include <string.h>
22
23#include "mrtklib/mrtk_atmos.h"
24#include "mrtklib/mrtk_bits.h"
25#include "mrtklib/mrtk_coords.h"
26#include "mrtklib/mrtk_rtcm.h"
27#include "mrtklib/mrtk_sys.h"
28#include "mrtklib/mrtk_trace.h"
29
30/*--- local constants (duplicated to avoid rtklib.h dependency) -------------*/
31#define SYS_GPS 0x01
32#define SYS_GLO 0x04
33#define SYS_GAL 0x08
34#define SYS_QZS 0x10
35#define SYS_CMP 0x20
36
37#define TSYS_GAL 3
38
39static const double PI = 3.1415926535897932;
40static const double D2R = 3.1415926535897932 / 180.0;
41static const double R2D = 180.0 / 3.1415926535897932;
42static const double RE_WGS84 = 6378137.0;
43
44#define TOW_LSB 30.0 /* epoch time 30s */
45#define BTYPE_GRID 0 /* block type grid */
46#define BTYPE_STA 1 /* block type station */
47#define ION_BLKSIZE 2.0 /* ionosphere block size */
48#define TRP_BLKSIZE 4.0 /* troposphere block size */
49
50/*--- forward declarations for legacy functions resolved at link time -------*/
51
52#define GN(gp) (gp == 1 ? 64 : 16)
53
54/* initialize station setting --------------------------------------------------
55 * initialize station settings based on provided block information
56 * args : blkinf_t *b IO block information
57 *-----------------------------------------------------------------------------*/
59 int i, br, gr;
60 double gridsize;
61
62 gr = (int)sqrt(GN(b->gpitch));
63 br = (int)360.0 / b->bs;
64 b->bpos[0] = 90.0 - (int)(b->bn / br) * b->bs;
65 b->bpos[1] = (b->bn % br) * b->bs;
66 if (b->bpos[1] >= 180) {
67 b->bpos[1] -= 360;
68 }
69 b->bpos[0] = b->bpos[0] * D2R;
70 b->bpos[1] = b->bpos[1] * D2R;
71
72 if (b->btype == BTYPE_GRID) {
73 gridsize = (double)b->bs / (double)gr;
74 /* init grid position */
75 for (i = 0; i < gr * gr; i++) {
76 if (i < 32) {
77 if (!((b->mask[0] >> i) & 1)) {
78 continue;
79 }
80 } else {
81 if (!((b->mask[1] >> (i - 32)) & 1)) {
82 continue;
83 }
84 }
85 b->grid[b->n][0] = b->bpos[0] - ((i / gr) * gridsize) * D2R;
86 b->grid[b->n][1] = b->bpos[1] + ((i % gr) * gridsize) * D2R;
87 b->grid[b->n][2] = 0;
88 b->gp[b->n] = i;
89 b->n++;
90 }
91 }
92}
93
94#define ION_BAS_LSB 0.35 /* ionospheric delay base value resolution */
95#define ION_DET_LSB 0.002 /* ionospheric delay detail value resolution */
96#define ION_STD_LSB 0.02 /* ionospheric delay std index resolution */
97#define ION_STD_MAX 2.56 /* ionospheric delay std index=7 */
98#define LAT_LSB 0.001 /* station pos latitude resolution */
99#define LON_LSB 0.001 /* station pos longitude resolution */
100#define TRP_BAS_LSB 0.1 /* tropspheric delay base value resolution */
101#define TRP_DET_LSB 0.002 /* tropspheric delay detail value resolution */
102#define TRP_STD_LSB 0.002 /* tropspheric delay std index resolution */
103#define TRP_STD_MAX 0.256 /* tropspheric delay std index=7 */
104
105#define ROUND(x) (int)floor((x) + 0.5)
106
107/* decode local correction grid rtcm message header --------------------------*/
108static int decode_lclhead(rtcm_t* rtcm, int type, blkinf_t* blkinf) {
109 int p = 24, wn;
110 double tow;
111 gtime_t ntime;
112 static gtime_t ptime = {0};
113
114 /* message no */
115 /* 'type' is already partially decoded, thus skipped */
116 p += 12;
117
118 /* gps epoch time */
119 tow = getbitu(rtcm->buff, p, 15);
120 p += 15;
121 tow = tow * TOW_LSB;
122
123 /* tow -> gpstime with cpu time */
124 time2gst(rtcm->time, &wn);
125 ntime = gst2time(wn, tow);
126 if (ptime.time != 0) {
127 if (timediff(ntime, ptime) > (double)86400 * 6) {
128 wn -= 1;
129 ntime = gst2time(wn, tow);
130 }
131 }
132 rtcm->time = ntime;
133 ptime = ntime;
134
135 if (type == 2001 || type == 2011) {
136 blkinf->bn = getbitu(rtcm->buff, p, 12);
137 p += 12;
138 blkinf->bs = TRP_BLKSIZE;
139 } else if ((2002 <= type && type <= 2006) || (2012 <= type && type <= 2016)) {
140 blkinf->bn = getbitu(rtcm->buff, p, 14);
141 p += 14;
142 blkinf->bs = ION_BLKSIZE;
143 }
144
145 /* grid pitch and mask */
146 if (2001 <= type && type <= 2006) {
147 /* grid pitch */
148 blkinf->gpitch = getbitu(rtcm->buff, p, 1);
149 p += 1;
150 /* grid mask */
151 if (blkinf->gpitch) {
152 blkinf->mask[0] = getbitu(rtcm->buff, p, 32);
153 p += 32;
154 blkinf->mask[1] = getbitu(rtcm->buff, p, 32);
155 p += 32;
156 } else {
157 blkinf->mask[0] = getbitu(rtcm->buff, p, 16);
158 p += 16;
159 }
160 blkinf->btype = BTYPE_GRID;
161 initblkinf(blkinf);
162 }
163
164 /* number of station */
165 if (type == 2011) {
166 blkinf->btype = BTYPE_STA;
167 initblkinf(blkinf);
168 blkinf->n = getbitu(rtcm->buff, p, 9);
169 p += 9;
170 } else if (2012 <= type && type <= 2016) {
171 blkinf->btype = BTYPE_STA;
172 initblkinf(blkinf);
173 blkinf->n = getbitu(rtcm->buff, p, 8);
174 p += 8;
175 }
176
177 return p;
178}
179/* decode local tropospheric delay correction grid RTCM message ----------------
180 * decode local tropospheric correction grid from RTCM message
181 * args : rtcm_t *rtcm IO RTCM control struct
182 * int type I message type
183 * return : status (12: success, other: error)
184 *-----------------------------------------------------------------------------*/
185int decode_lcltrop(rtcm_t* rtcm, int type) {
186 int i, p = 0, ctnum, tp = 0;
187 unsigned int lat, lon;
188 double base, trp, ind, ecef[3];
189 double zhd, zazel[] = {0.0, PI / 2.0};
190 blkinf_t *blkinf, tmpblkinf = {0};
191 sitetrp_t* strp;
192
193 if (!rtcm_lclblk(rtcm)) {
194 trace(NULL, 1, "decode_lcltrop: lclblk malloc error\n");
195 return -1;
196 }
197 p = decode_lclhead(rtcm, type, &tmpblkinf);
198 trace(NULL, 3, "decode_lcltrop : %s,bn=%4d,btype=%d,gp=%d,gnum=%d\n", time_str(rtcm->time, 0), tmpblkinf.bn,
199 tmpblkinf.btype, tmpblkinf.gpitch, tmpblkinf.n);
200 for (i = 0; i < rtcm->lclblk->tnum; i++) {
201 if (rtcm->lclblk->tblkinf[i].bn == tmpblkinf.bn) {
202 break;
203 }
204 }
205 ctnum = i;
206 if (i == rtcm->lclblk->tnum) {
207 rtcm->lclblk->tnum++;
208 }
209 memcpy(&rtcm->lclblk->tblkinf[i], &tmpblkinf, sizeof(blkinf_t));
210 blkinf = &rtcm->lclblk->tblkinf[i];
211
212 base = getbitu(rtcm->buff, p, 6) * TRP_BAS_LSB;
213 p += 6;
214 for (i = 0; i < blkinf->n; i++) {
215 /* latitude and longitude */
216 if (type == 2011) {
217 lat = getbitu(rtcm->buff, p, 12);
218 p += 12;
219 lon = getbitu(rtcm->buff, p, 12);
220 p += 12;
221 blkinf->grid[i][0] = blkinf->bpos[0] - lat * LAT_LSB * D2R;
222 blkinf->grid[i][1] = blkinf->bpos[1] + lon * LON_LSB * D2R;
223 }
224 if (type == 2001) {
225 tp = blkinf->gp[i];
226 } else if (type == 2011) {
227 tp = i;
228 }
229
230 strp = &rtcm->lclblk->tstat[ctnum][tp];
231 trp = getbitu(rtcm->buff, p, 9) * TRP_DET_LSB;
232 p += 9;
233 ind = getbitu(rtcm->buff, p, 3);
234 p += 3;
235 if (ind == 7) {
236 continue;
237 }
238
239 /* zenith hydrostatic delay */
240 zhd = tropmodel(rtcm->time, blkinf->grid[i], zazel, 0.0);
241 strp->trpd.time = rtcm->time;
242 strp->trpd.trp[0] = trp + base + zhd;
243 strp->trpd.std[0] = TRP_STD_LSB * pow(2, ind);
244 pos2ecef(blkinf->grid[i], ecef);
245 memcpy(strp->site.ecef, ecef, sizeof(strp->site.ecef));
246 trace(NULL, 4, "decode_lcltrop : %s,bn=%4d,lat=%.3f,lon=%.3f,base=%lf,detail=%lf,std=%lf\n",
247 time_str(rtcm->time, 0), blkinf->bn, blkinf->grid[i][0] * R2D, blkinf->grid[i][1] * R2D, base, trp,
248 strp->trpd.std[0]);
249 }
250
251 return 12;
252}
253
254/* decode local ionospheric delay correction grid RTCM message ----------------
255 * decode local ionospheric correction grid from RTCM message
256 * args : rtcm_t *rtcm IO RTCM control struct
257 * int type I message type
258 * return : status (12: success, other: error)
259 *-----------------------------------------------------------------------------*/
260int decode_lcliono(rtcm_t* rtcm, int type) {
261 int i, j, p = 0, ns, nsat, sat, msys, minprn, ssat, cinum, tp = 0;
262 int prn[MAXSAT] = {0};
263 unsigned int smask[2] = {0}, nbase, lat, lon;
264 double base, ion, ind, ecef[3];
265 blkinf_t *blkinf, tmpblkinf = {0};
266 ion_t* ionp;
267
268 if (!rtcm_lclblk(rtcm)) {
269 trace(NULL, 1, "decode_lcliono: lclblk malloc error\n");
270 return -1;
271 }
272 switch (type) {
273 case 2002:
274 msys = SYS_GPS;
275 minprn = MINPRNGPS;
276 nsat = NSATGPS;
277 break;
278 case 2003:
279 msys = SYS_GLO;
280 minprn = MINPRNGLO;
281 nsat = NSATGLO;
282 break;
283 case 2004:
284 msys = SYS_GAL;
285 minprn = MINPRNGAL;
286 nsat = NSATGAL;
287 break;
288 case 2005:
289 msys = SYS_QZS;
290 minprn = MINPRNQZS;
291 nsat = NSATQZS;
292 break;
293 case 2006:
294 msys = SYS_CMP;
295 minprn = MINPRNCMP;
296 nsat = NSATCMP;
297 break;
298 case 2012:
299 msys = SYS_GPS;
300 minprn = MINPRNGPS;
301 nsat = NSATGPS;
302 break;
303 case 2013:
304 msys = SYS_GLO;
305 minprn = MINPRNGLO;
306 nsat = NSATGLO;
307 break;
308 case 2014:
309 msys = SYS_GAL;
310 minprn = MINPRNGAL;
311 nsat = NSATGAL;
312 break;
313 case 2015:
314 msys = SYS_QZS;
315 minprn = MINPRNQZS;
316 nsat = NSATQZS;
317 break;
318 case 2016:
319 msys = SYS_CMP;
320 minprn = MINPRNCMP;
321 nsat = NSATCMP;
322 break;
323 default:
324 return 0;
325 }
326
327 p = decode_lclhead(rtcm, type, &tmpblkinf);
328 trace(NULL, 3, "decode_lcliono : %s,bn=%4d,btype=%d,gp=%d\n", time_str(rtcm->time, 0), tmpblkinf.bn,
329 tmpblkinf.btype, tmpblkinf.gpitch);
330 for (i = 0; i < rtcm->lclblk->inum; i++) {
331 if (rtcm->lclblk->iblkinf[i].bn == tmpblkinf.bn) {
332 break;
333 }
334 }
335 if (i >= rtcm->lclblk->inum) {
336 rtcm->lclblk->inum++;
337 }
338 cinum = i;
339 memcpy(&rtcm->lclblk->iblkinf[cinum], &tmpblkinf, sizeof(blkinf_t));
340 blkinf = &rtcm->lclblk->iblkinf[cinum];
341
342 if (nsat > 32) {
343 smask[0] = getbitu(rtcm->buff, p, 32);
344 p += 32;
345 smask[1] = getbitu(rtcm->buff, p, nsat - 32);
346 p += nsat - 32;
347 } else {
348 smask[0] = getbitu(rtcm->buff, p, nsat);
349 p += nsat;
350 }
351 for (j = 0, ns = 0; j < nsat; j++) {
352 if (j < 32) {
353 if (((smask[0] >> j) & 1)) {
354 prn[ns++] = j + minprn;
355 }
356 } else {
357 if (((smask[1] >> (j - 32)) & 1)) {
358 prn[ns++] = j + minprn;
359 }
360 }
361 }
362
363 /* latitude and longitude */
364 if (2012 <= type && type <= 2016) {
365 for (i = 0; i < blkinf->n; i++) {
366 lat = getbitu(rtcm->buff, p, 11);
367 p += 11;
368 lon = getbitu(rtcm->buff, p, 11);
369 p += 11;
370 blkinf->grid[i][0] = blkinf->bpos[0] - lat * LAT_LSB * D2R;
371 blkinf->grid[i][1] = blkinf->bpos[1] + lon * LON_LSB * D2R;
372 }
373 }
374
375 /* clear old data */
376 ssat = satno(msys, minprn);
377 for (i = 0; i < blkinf->n; i++) {
378 if (2002 <= type && type <= 2006) {
379 tp = blkinf->gp[i];
380 } else if (2012 <= type && type <= 2016) {
381 tp = i;
382 }
383 for (j = ssat - 1; j < ssat + nsat - 1; j++) {
384 ionp = &rtcm->lclblk->istat[cinum][tp].iond[j];
385 ionp->ion = 0.0;
386 ionp->std = 0.0;
387 }
388 pos2ecef(blkinf->grid[i], ecef);
389 memcpy(rtcm->lclblk->istat[cinum][tp].site.ecef, ecef, sizeof(rtcm->lclblk->istat[cinum][tp].site.ecef));
390 }
391
392 for (i = 0; i < ns; i++) {
393 nbase = getbitu(rtcm->buff, p, 8);
394 p += 8;
395 base = nbase * ION_BAS_LSB;
396 if (!(sat = satno(msys, prn[i]))) {
397 continue;
398 }
399 for (j = 0; j < blkinf->n; j++) {
400 if (2002 <= type && type <= 2006) {
401 tp = blkinf->gp[j];
402 } else if (2012 <= type && type <= 2016) {
403 tp = j;
404 }
405 ionp = &rtcm->lclblk->istat[cinum][tp].iond[sat - 1];
406 ion = getbitu(rtcm->buff, p, 9) * ION_DET_LSB;
407 p += 9;
408 ind = getbitu(rtcm->buff, p, 3);
409 p += 3;
410 /*if (ind==7) continue;*/
411
412 ionp->time = rtcm->time;
413 ionp->ion = ion + base;
414 ionp->std = ION_STD_LSB * pow(2, ind);
415 trace(NULL, 4,
416 "decode_lcliono : %s,sys=%d,prn=%d,bn=%5d,gn=%d,lat=%.3f,lon=%.3f,base=%lf,detail=%lf,std=%lf\n",
417 time_str(rtcm->time, 0), msys, prn[j], blkinf->bn, tp, blkinf->grid[j][0] * R2D,
418 blkinf->grid[j][1] * R2D, base, ion, ionp->std);
419 }
420 }
421 return 12;
422}
423/* encode local correction grid rtcm message header --------------------------*/
424static int encode_lclhead(rtcm_t* rtcm, int type, blkinf_t* blkinf) {
425 int p = 24, week, epoch;
426 double tow;
427
428 /* message no */
429 setbitu(rtcm->buff, p, 12, type);
430 p += 12;
431
432 /* gps epoch time */
433 tow = time2gpst(rtcm->time, &week) / TOW_LSB;
434 epoch = ROUND(tow);
435 setbitu(rtcm->buff, p, 15, epoch);
436 p += 15;
437
438 /* block number */
439 if (type == 2001 || type == 2011) {
440 setbitu(rtcm->buff, p, 12, blkinf->bn);
441 p += 12;
442 } else if ((2002 <= type && type <= 2006) || (2012 <= type && type <= 2016)) {
443 setbitu(rtcm->buff, p, 14, blkinf->bn);
444 p += 14;
445 }
446
447 /* grid pitch and mask */
448 if (2001 <= type && type <= 2006) {
449 /* grid pitch */
450 setbitu(rtcm->buff, p, 1, blkinf->gpitch);
451 p += 1;
452 /* grid mask */
453 if (blkinf->gpitch) {
454 setbitu(rtcm->buff, p, 32, blkinf->mask[0]);
455 p += 32;
456 setbitu(rtcm->buff, p, 32, blkinf->mask[1]);
457 p += 32;
458 } else {
459 setbitu(rtcm->buff, p, 16, blkinf->mask[0]);
460 p += 16;
461 }
462 }
463
464 /* number of station */
465 if (type == 2011) {
466 setbitu(rtcm->buff, p, 9, blkinf->n);
467 p += 9;
468 } else if (2012 <= type && type <= 2016) {
469 setbitu(rtcm->buff, p, 8, blkinf->n);
470 p += 8;
471 }
472 return p;
473}
474/* encode local tropospheric delay correction grid RTCM message ----------------
475 * encode local tropospheric correction grid to RTCM message
476 * args : rtcm_t *rtcm IO RTCM control struct
477 * int type I message type
478 * return : status (1: success, other: error)
479 *-----------------------------------------------------------------------------*/
480int encode_lcltrop(rtcm_t* rtcm, int type) {
481 int i, p = 0, n = 0, tp = 0;
482 unsigned int base, detail, stdev, lat, lon;
483 double zhd, zazel[] = {0.0, PI / 2.0}, zwd[MAXTRPSTA] = {0.0};
484 trp_t* trpp;
485 blkinf_t* blkinf;
486
487 if (!rtcm->lclblk) {
488 return 0;
489 }
490 blkinf = &rtcm->lclblk->tblkinf[rtcm->lclblk->outtn];
491 /* base value */
492 for (i = 0, base = -1; i < blkinf->n; i++) {
493 if (type == 2001) {
494 tp = blkinf->gp[i];
495 } else if (type == 2011) {
496 tp = i;
497 }
498 trpp = &rtcm->lclblk->tstat[rtcm->lclblk->outtn][tp].trpd;
499 if (timediff(rtcm->time, trpp->time) > 0 || trpp->time.time == 0) {
500 continue;
501 }
502 rtcm->time = trpp->time;
503 /* zenith wet delay */
504 zhd = tropmodel(trpp->time, blkinf->grid[tp], zazel, 0.0);
505 zwd[i] = trpp->trp[0] - zhd;
506 if ((base == -1) || (base > (unsigned int)(zwd[i] / TRP_BAS_LSB))) {
507 base = (unsigned int)(zwd[i] / TRP_BAS_LSB);
508 }
509 n++;
510 }
511 if (!n) {
512 return 0;
513 }
514
515 /* encode trop message */
516 p = encode_lclhead(rtcm, type, blkinf);
517 trace(NULL, 3, "encode_lcltrop : %s,bn=%4d,btype=%d,gp=%d,gnum=%d\n", time_str(rtcm->time, 0), blkinf->bn,
518 blkinf->btype, blkinf->gpitch, blkinf->n);
519 setbitu(rtcm->buff, p, 6, base);
520 p += 6; /* Base Value LSB:0.1m */
521 for (i = 0; i < blkinf->n; i++) {
522 if (type == 2001) {
523 tp = blkinf->gp[i];
524 } else if (type == 2011) {
525 tp = i;
526 }
527 trpp = &rtcm->lclblk->tstat[rtcm->lclblk->outtn][tp].trpd;
528 if (trpp->std[0] == 0) {
529 continue;
530 }
531
532 /* latitude and longitude */
533 if (type == 2011) {
534 lat = (unsigned int)((blkinf->bpos[0] - blkinf->grid[i][0]) * R2D / LAT_LSB);
535 lon = (unsigned int)((blkinf->grid[i][1] - blkinf->bpos[1]) * R2D / LON_LSB);
536 setbitu(rtcm->buff, p, 12, lat);
537 p += 12;
538 setbitu(rtcm->buff, p, 12, lon);
539 p += 12;
540 }
541
542 /* zenith wet delay */
543 detail = (unsigned int)((zwd[i] - base * TRP_BAS_LSB) / TRP_DET_LSB);
544 stdev = (unsigned int)(log(trpp->std[0] / TRP_STD_LSB) / log(2));
545 if (zwd[i] < base * TRP_BAS_LSB) {
546 detail = 0;
547 stdev = 7;
548 trace(NULL, 4, "encode_lcltrop zwd<base: %s,bn=%4d,gn=%d,lat=%.3f,lon=%.3f,base=%lf,zwd=%lf\n",
549 time_str(rtcm->time, 0), blkinf->bn, tp, blkinf->grid[tp][0] * R2D, blkinf->grid[tp][1] * R2D,
550 base * ION_BAS_LSB, zwd[i]);
551 } else if (TRP_STD_MAX <= trpp->std[0]) {
552 stdev = 7;
553 trace(NULL, 4, "encode_lcltrop TRP_STD_MAX<std: %s,bn=%4d,gn=%d,lat=%.3f,lon=%.3f,base=%lf,zwd=%lf\n",
554 time_str(rtcm->time, 0), blkinf->bn, tp, blkinf->grid[tp][0] * R2D, blkinf->grid[tp][1] * R2D,
555 base * ION_BAS_LSB, zwd[i]);
556 }
557
558 setbitu(rtcm->buff, p, 9, detail);
559 p += 9; /* Detail Value */
560 setbitu(rtcm->buff, p, 3, stdev);
561 p += 3; /* STD Index */
562
563 trace(NULL, 4, "encode_lcltrop : %s,bn=%4d,gn=%d,lat=%.3f,lon=%.3f,base=%.3f,detail=%.3f,std=%.3f\n",
564 time_str(rtcm->time, 0), blkinf->bn, tp, blkinf->grid[tp][0] * R2D, blkinf->grid[tp][1] * R2D,
565 base * TRP_BAS_LSB, detail * TRP_DET_LSB, pow(2.0, stdev) * TRP_STD_LSB);
566 }
567 rtcm->nbit = p;
568
569 return 1;
570}
571/* encode local ionospheric delay correction grid RTCM message -----------------
572 * encode local ionospheric correction grid to RTCM message
573 * args : rtcm_t *rtcm IO RTCM control struct
574 * int type I message type
575 * return : status (1: success, other: error)
576 *-----------------------------------------------------------------------------*/
577int encode_lcliono(rtcm_t* rtcm, int type) {
578 int i, j, p = 0, n = 0, nsat, msys, minprn, sys, prn, ssat, tp = 0;
579 double ion[MAXIONSTA][MAXOBS] = {{0}}, std[MAXIONSTA][MAXOBS] = {{0}};
580 unsigned int base[MAXOBS] = {-1}, satmask[2], detail, stdev, lat, lon;
581 ion_t* ionp;
582 blkinf_t* blkinf;
583
584 if (!rtcm->lclblk) {
585 return 0;
586 }
587 switch (type) {
588 case 2002:
589 msys = SYS_GPS;
590 minprn = MINPRNGPS;
591 nsat = NSATGPS;
592 break;
593 case 2003:
594 msys = SYS_GLO;
595 minprn = MINPRNGLO;
596 nsat = NSATGLO;
597 break;
598 case 2004:
599 msys = SYS_GAL;
600 minprn = MINPRNGAL;
601 nsat = NSATGAL;
602 break;
603 case 2005:
604 msys = SYS_QZS;
605 minprn = MINPRNQZS;
606 nsat = NSATQZS;
607 break;
608 case 2006:
609 msys = SYS_CMP;
610 minprn = MINPRNCMP;
611 nsat = NSATCMP;
612 break;
613 case 2012:
614 msys = SYS_GPS;
615 minprn = MINPRNGPS;
616 nsat = NSATGPS;
617 break;
618 case 2013:
619 msys = SYS_GLO;
620 minprn = MINPRNGLO;
621 nsat = NSATGLO;
622 break;
623 case 2014:
624 msys = SYS_GAL;
625 minprn = MINPRNGAL;
626 nsat = NSATGAL;
627 break;
628 case 2015:
629 msys = SYS_QZS;
630 minprn = MINPRNQZS;
631 nsat = NSATQZS;
632 break;
633 case 2016:
634 msys = SYS_CMP;
635 minprn = MINPRNCMP;
636 nsat = NSATCMP;
637 break;
638 default:
639 return 0;
640 }
641
642 ssat = satno(msys, minprn);
643 blkinf = &rtcm->lclblk->iblkinf[rtcm->lclblk->outin];
644 /* search base value */
645 for (i = 0; i < nsat; i++) {
646 base[i] = -1;
647 }
648 for (i = 0, satmask[0] = 0, satmask[1] = 0; i < blkinf->n; i++) {
649 if (2002 <= type && type <= 2006) {
650 tp = blkinf->gp[i];
651 } else if (2012 <= type && type <= 2016) {
652 tp = i;
653 }
654 for (j = ssat - 1; j < ssat + nsat - 1; j++) {
655 ionp = &rtcm->lclblk->istat[rtcm->lclblk->outin][tp].iond[j];
656 sys = satsys(j + 1, &prn);
657 prn -= minprn;
658 if (ionp->ion <= 0.0) {
659 continue;
660 }
661 rtcm->time = ionp->time;
662 ion[i][prn] = ionp->ion;
663 std[i][prn] = ionp->std;
664 /* use the smallest VTEC value in the entire area as the base */
665 if ((base[prn] == -1) || (base[prn] > (unsigned int)(ionp->ion / ION_BAS_LSB))) {
666 base[prn] = (unsigned int)(ionp->ion / ION_BAS_LSB);
667 }
668 if (prn < 32) {
669 satmask[0] |= (1 << (prn));
670 } else {
671 satmask[1] |= (1 << (prn - 32));
672 }
673 n++;
674 }
675 }
676 if (!n) {
677 return 0;
678 }
679
680 /* encode iono message */
681 p = encode_lclhead(rtcm, type, blkinf);
682 trace(NULL, 3, "encode_lcliono : %s,bn=%4d,btype=%d,gp=%d,gnum=%d\n", time_str(rtcm->time, 0), blkinf->bn,
683 blkinf->btype, blkinf->gpitch, blkinf->n);
684 if (nsat > 32) {
685 setbitu(rtcm->buff, p, 32, satmask[0]);
686 p += 32;
687 setbitu(rtcm->buff, p, nsat - 32, satmask[1]);
688 p += nsat - 32;
689 } else {
690 setbitu(rtcm->buff, p, nsat, satmask[0]);
691 p += nsat;
692 }
693
694 /* latitude and longitude */
695 if (2012 <= type && type <= 2016) {
696 for (i = 0; i < blkinf->n; i++) {
697 lat = (unsigned int)((blkinf->bpos[0] - blkinf->grid[i][0]) * R2D / LAT_LSB);
698 lon = (unsigned int)((blkinf->grid[i][1] - blkinf->bpos[1]) * R2D / LON_LSB);
699 setbitu(rtcm->buff, p, 11, lat);
700 p += 11;
701 setbitu(rtcm->buff, p, 11, lon);
702 p += 11;
703 }
704 }
705 for (i = 0; i < nsat; i++) {
706 if (i < 32) {
707 if (((satmask[0] >> i) & 1) == 0) {
708 continue;
709 }
710 } else {
711 if (((satmask[1] >> (i - 32)) & 1) == 0) {
712 continue;
713 }
714 }
715
716 setbitu(rtcm->buff, p, 8, base[i]);
717 p += 8; /* base value */
718 for (j = 0; j < blkinf->n; j++) {
719 detail = (unsigned int)((ion[j][i] - base[i] * ION_BAS_LSB) / ION_DET_LSB);
720 stdev = (unsigned int)(log(std[j][i] / ION_STD_LSB) / log(2));
721 if (ion[j][i] < base[i] * ION_BAS_LSB) {
722 detail = 0;
723 stdev = 7;
724 trace(NULL, 4, "encode_lcliono ion<base: %s,sys=%d,prn=%d,bn=%4d,gn=%d,base=%lf,ion=%lf\n",
725 time_str(rtcm->time, 0), msys, i + 1, blkinf->bn, blkinf->gp[j], base[i] * ION_BAS_LSB,
726 ion[j][i]);
727 } else if (ION_STD_MAX <= std[j][i]) {
728 stdev = 7;
729 trace(NULL, 4, "encode_lcliono ION_STD_MAX<std: %s,sys=%d,prn=%d,bn=%4d,gn=%d,base=%lf,ion=%lf\n",
730 time_str(rtcm->time, 0), msys, i + 1, blkinf->bn, blkinf->gp[j], base[i] * ION_BAS_LSB,
731 ion[j][i]);
732 }
733
734 setbitu(rtcm->buff, p, 9, detail);
735 p += 9; /* detail value */
736 setbitu(rtcm->buff, p, 3, stdev);
737 p += 3; /* std index */
738 trace(NULL, 4, "encode_lcliono : %s,sys=%d,prn=%d,bn=%4d,gn=%d,base=%lf,detail=%lf,std=%lf\n",
739 time_str(rtcm->time, 0), msys, i + 1, blkinf->bn, blkinf->gp[j], base[i] * ION_BAS_LSB,
740 detail * ION_DET_LSB, pow(2.0, stdev) * ION_STD_LSB);
741 }
742 }
743 rtcm->nbit = p;
744 return 1;
745}
double tropmodel(gtime_t time, const double *pos, const double *azel, double humi)
Compute tropospheric delay by standard atmosphere and Saastamoinen.
Definition mrtk_atmos.c:162
MRTKLIB Atmosphere Module — Ionospheric and tropospheric models.
void setbitu(uint8_t *buff, int pos, int len, uint32_t data)
Set unsigned bits in byte data.
Definition mrtk_bits.c:122
uint32_t getbitu(const uint8_t *buff, int pos, int len)
Extract unsigned bits from byte data.
Definition mrtk_bits.c:99
MRTKLIB Bits Module — Binary bit operations and CRC functions.
#define D2R
Definition mrtk_coords.c:36
void pos2ecef(const double *pos, double *r)
Transform geodetic position to ECEF position.
#define PI
Definition mrtk_coords.c:35
#define MAXSAT
Definition mrtk_coords.c:45
#define RE_WGS84
Definition mrtk_coords.c:38
MRTKLIB Coordinates Module — Coordinate transformations and geometry.
int satsys(int sat, int *prn)
Definition mrtk_nav.c:117
#define SYS_GPS
Definition mrtk_eph.c:65
#define SYS_QZS
Definition mrtk_eph.c:69
#define SYS_CMP
Definition mrtk_eph.c:70
#define SYS_GAL
Definition mrtk_eph.c:68
#define SYS_GLO
Definition mrtk_eph.c:67
#define NSATCMP
#define NSATQZS
#define NSATGPS
#define MINPRNCMP
#define MAXOBS
#define MINPRNQZS
#define MAXIONSTA
#define MAXTRPSTA
#define MINPRNGAL
#define MINPRNGLO
#define NSATGLO
#define NSATGAL
int satno(int sys, int prn)
Convert satellite system+prn/slot number to satellite number.
Definition mrtk_nav.c:58
#define R2D
Definition mrtk_obs.c:51
static rtcm_t * rtcm
#define MINPRNGPS
int encode_lcltrop(rtcm_t *rtcm, int type)
Encode local tropospheric delay correction grid RTCM message.
static int decode_lclhead(rtcm_t *rtcm, int type, blkinf_t *blkinf)
#define TRP_STD_MAX
#define ION_BLKSIZE
#define GN(gp)
#define TRP_BAS_LSB
#define LON_LSB
int decode_lcliono(rtcm_t *rtcm, int type)
Decode local ionospheric delay correction grid RTCM message.
#define ION_BAS_LSB
#define BTYPE_STA
int encode_lcliono(rtcm_t *rtcm, int type)
Encode local ionospheric delay correction grid RTCM message.
#define ION_STD_MAX
#define TRP_DET_LSB
#define TRP_BLKSIZE
int decode_lcltrop(rtcm_t *rtcm, int type)
Decode local tropospheric delay correction grid RTCM message.
void initblkinf(blkinf_t *b)
Initialize block information struct.
#define LAT_LSB
static int encode_lclhead(rtcm_t *rtcm, int type, blkinf_t *blkinf)
#define ROUND(x)
#define TOW_LSB
#define ION_STD_LSB
#define ION_DET_LSB
#define BTYPE_GRID
#define TRP_STD_LSB
lclblock_t * rtcm_lclblk(rtcm_t *rtcm)
Get the local correction block, lazily allocating it on first use.
Definition mrtk_rtcm.c:139
MRTKLIB RTCM Module — RTCM message types and functions.
MRTKLIB System Module — OS/filesystem utility functions.
gtime_t gst2time(int week, double sec)
Convert Galileo system time week/tow to gtime_t.
Definition mrtk_time.c:197
double timediff(gtime_t t1, gtime_t t2)
Compute time difference (t1 - t2).
Definition mrtk_time.c:279
double time2gpst(gtime_t t, int *week)
Convert gtime_t to GPS week/tow.
Definition mrtk_time.c:181
char * time_str(gtime_t t, int n)
Get time string (not reentrant).
Definition mrtk_time.c:530
double time2gst(gtime_t t, int *week)
Convert gtime_t to Galileo system time week/tow.
Definition mrtk_time.c:213
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.
double bpos[3]
Definition mrtk_nav.h:327
unsigned int mask[2]
Definition mrtk_nav.h:325
double bs
Definition mrtk_nav.h:323
int btype
Definition mrtk_nav.h:321
int gpitch
Definition mrtk_nav.h:324
double grid[MAXTRPSTA][3]
Definition mrtk_nav.h:328
int gp[MAXTRPSTA]
Definition mrtk_nav.h:329
GNSS time representation.
Definition mrtk_time.h:49
time_t time
Definition mrtk_time.h:50
gtime_t time
Definition mrtk_nav.h:262
double ion
Definition mrtk_nav.h:264
double std
Definition mrtk_nav.h:265
RTCM control struct type.
Definition mrtk_rtcm.h:50
trp_t trpd
Definition mrtk_nav.h:285
spos_t site
Definition mrtk_nav.h:284
double ecef[3]
Definition mrtk_nav.h:258
double std[3]
Definition mrtk_nav.h:274
double trp[3]
Definition mrtk_nav.h:273
gtime_t time
Definition mrtk_nav.h:272