|
| 1 | +""" |
| 2 | +QZSS MADOCA-PPP correction data decoder |
| 3 | +
|
| 4 | +[1] Quasi-Zenith Satellite System Interface Specification Multi-GNSS |
| 5 | + Advanced Orbit and Clock Augmentation - Precise Point Positioning |
| 6 | + (IS-QZSS-MDC-003), 2024 |
| 7 | +
|
| 8 | +""" |
| 9 | + |
| 10 | +import numpy as np |
| 11 | +import bitstruct as bs |
| 12 | +from cssrlib.cssrlib import cssr, sCSSRTYPE |
| 13 | +from cssrlib.gnss import gpst2time, uGNSS, prn2sat |
| 14 | + |
| 15 | + |
| 16 | +class areaInfo(): |
| 17 | + def __init__(self, sid, latr, lonr, p1=0, p2=0): |
| 18 | + self.sid = sid |
| 19 | + self.latr = latr |
| 20 | + self.lonr = lonr |
| 21 | + if sid == 0: |
| 22 | + self.lats = p1 |
| 23 | + self.lons = p2 |
| 24 | + elif sid == 1: |
| 25 | + self.rng = p1 |
| 26 | + |
| 27 | + |
| 28 | +class ionoCorr(): |
| 29 | + def __init__(self): |
| 30 | + self.t0 = None |
| 31 | + self.qi = [] |
| 32 | + self.iodssr = 0 |
| 33 | + self.ct = 0 |
| 34 | + self.sat = [] |
| 35 | + self.c = np.zeros((6)) |
| 36 | + |
| 37 | + |
| 38 | +class cssr_mdc(cssr): |
| 39 | + def __init__(self, foutname=None): |
| 40 | + super().__init__(foutname) |
| 41 | + self.MAXNET = 1 |
| 42 | + self.cssrmode = sCSSRTYPE.QZS_MADOCA |
| 43 | + self.buff = bytearray(250*10) |
| 44 | + |
| 45 | + self.pnt = {} |
| 46 | + self.ci = {} |
| 47 | + |
| 48 | + def decode_mdc_stec_area(self, buff, i=0): |
| 49 | + """ decoder for MT1 - STEC Coverage Message """ |
| 50 | + msgtype, subtype = bs.unpack_from('u12u4', buff, i) |
| 51 | + i += 16 |
| 52 | + tow, uid, mi, iodssr = bs.unpack_from('u20u4u1u4', buff, i) |
| 53 | + i += 29 |
| 54 | + self.tow0 = tow//3600*3600 |
| 55 | + reg, alrt, len_, narea = bs.unpack_from('u8u1u16u5', buff, i) |
| 56 | + i += 30 |
| 57 | + if reg not in self.pnt: |
| 58 | + self.pnt[reg] = {} |
| 59 | + |
| 60 | + for k in range(narea): |
| 61 | + area, sid = bs.unpack_from('u5u1', buff, i) |
| 62 | + i += 6 |
| 63 | + |
| 64 | + if sid == 0: |
| 65 | + latr, lonr, lats, lons = bs.unpack_from('s11u12u8u8', buff, i) |
| 66 | + if self.monlevel > 2: |
| 67 | + print(f"{reg} {area:2d} {sid} {latr*0.1:5.1f} " |
| 68 | + f"{lonr*0.1:5.1f} {lats*0.1:3.1f} {lons*0.1:3.1f}") |
| 69 | + self.pnt[reg][area] = areaInfo( |
| 70 | + sid, latr*0.1, lonr*0.1, lats*0.1, lons*0.1) |
| 71 | + else: |
| 72 | + latr, lonr, rng = bs.unpack_from('s15u16u8', buff, i) |
| 73 | + if self.monlevel > 2: |
| 74 | + print(f"{reg} {area:2d} {sid} {latr*0.01:6.2f} " |
| 75 | + f"{lonr*0.01:6.2f} {rng*10}") |
| 76 | + self.pnt[reg][area] = areaInfo( |
| 77 | + sid, latr*0.01, lonr*0.01, rng*10.0) |
| 78 | + i += 39 |
| 79 | + return i |
| 80 | + |
| 81 | + def decode_mdc_stec_corr(self, buff, i=0): |
| 82 | + """ decoder for MT2 - STEC Correction Message """ |
| 83 | + msgtype, subtype = bs.unpack_from('u12u4', buff, i) |
| 84 | + i += 16 |
| 85 | + dtow, uid, mi, iodssr = bs.unpack_from('u12u4u1u4', buff, i) |
| 86 | + i += 21 |
| 87 | + reg, area, ct = bs.unpack_from('u8u5u2', buff, i) |
| 88 | + i += 15 |
| 89 | + |
| 90 | + nsat = bs.unpack_from('u5u5u5u5u5', buff, i) |
| 91 | + i += 25 |
| 92 | + # gps, glo, gal, bds, qzss |
| 93 | + |
| 94 | + sys_t = [uGNSS.GPS, uGNSS.GLO, uGNSS.GAL, uGNSS.BDS, uGNSS.QZS] |
| 95 | + |
| 96 | + if reg not in self.ci: |
| 97 | + self.ci[reg] = {} |
| 98 | + if area not in self.ci[reg]: |
| 99 | + self.ci[reg][area] = ionoCorr() |
| 100 | + |
| 101 | + c01 = c10 = c11 = c02 = c20 = 0 |
| 102 | + nsat_total = np.sum(nsat) |
| 103 | + c = np.zeros((nsat_total, 6)) |
| 104 | + qi = np.zeros((nsat_total), dtype=int) |
| 105 | + sat_ = [] |
| 106 | + j = 0 |
| 107 | + for gnss in range(5): |
| 108 | + sys = sys_t[gnss] |
| 109 | + for k in range(nsat[gnss]): |
| 110 | + prn, qi[j], c00 = bs.unpack_from('u6u6s14', buff, i) |
| 111 | + if sys == uGNSS.QZS: |
| 112 | + prn += 192 |
| 113 | + sat = prn2sat(sys, prn) |
| 114 | + |
| 115 | + i += 26 |
| 116 | + if ct > 0: |
| 117 | + c01, c10 = bs.unpack_from('s12s12', buff, i) |
| 118 | + i += 24 |
| 119 | + if ct > 1: |
| 120 | + c11 = bs.unpack_from('s10', buff, i)[0] |
| 121 | + i += 10 |
| 122 | + if ct > 2: |
| 123 | + c02, c20 = bs.unpack_from('s8s8', buff, i) |
| 124 | + i += 16 |
| 125 | + |
| 126 | + sat_ += [sat] |
| 127 | + c[j, :] = [c00*0.05, c01*0.02, c10*0.02, c11*0.02, |
| 128 | + c02*5e-3, c20*5e-3] |
| 129 | + j += 1 |
| 130 | + |
| 131 | + self.ci[reg][area].t0 = gpst2time(self.week, self.tow0+dtow) |
| 132 | + self.ci[reg][area].iodssr = iodssr |
| 133 | + self.ci[reg][area].sat = sat_ |
| 134 | + self.ci[reg][area].qi = qi |
| 135 | + self.ci[reg][area].ct = ct |
| 136 | + self.ci[reg][area].c = c |
| 137 | + return i |
0 commit comments