@@ -146,6 +146,10 @@ class Integrity():
146146 sig_k_t = [0.0 , 0.04 , 0.07 , 0.10 , 0.20 , 0.25 , 0.30 , 0.40 , 0.50 , 0.70 ,
147147 1 , 2 , 5 , 7 , 10 , - 1 ]
148148
149+ # GNSS Signal Modulation Mask Table 8-45
150+ mod_t = ['BPSK(1)' , 'BPSK(5)' , 'BPSK(10)' , 'BOC(1,1)' , 'CBOC(6,1,1/11)' ,
151+ 'AltBOC(15,10)' , '' , '' ]
152+
149153 # Validity Period DFi065
150154 vp_tbl = [1 , 2 , 5 , 10 , 15 , 30 , 60 , 120 , 240 ,
151155 300 , 600 , 900 , 1800 , 3600 , 7200 , 10800 ]
@@ -1219,13 +1223,14 @@ def out_log_ssr_orb(self, sys, flg_vel=True):
12191223
12201224 def out_log (self , obs = None , eph = None , geph = None , seph = None ):
12211225 """ output ssr message to log file """
1226+ sys = - 1
12221227 if self .is_ssrtype (self .msgtype , True ):
12231228 sys = self .get_ssr_sys (self .msgtype )
12241229 inet = self .inet
12251230 self .fh .write ("{:4d}\t {:s}\n " .format (self .msgtype ,
12261231 time2str (self .time )))
12271232
1228- if self .subtype not in [sRTCM .SSR_META , sRTCM .SSR_GRID ]:
1233+ if sys > 0 and self .subtype not in [sRTCM .SSR_META , sRTCM .SSR_GRID ]:
12291234 self .fh .write (f" Update Interval: { self .udint_t [self .uint ]} [s]" )
12301235
12311236 self .fh .write (f" MultiMsg: { self .mi } \n " )
@@ -1452,6 +1457,61 @@ def out_log(self, obs=None, eph=None, geph=None, seph=None):
14521457 self .fh .write ("\n " )
14531458 self .fh .flush ()
14541459
1460+ if self .msgtype == 54 : # RTCM SC134 integrity messages
1461+ self .fh .write (f" Multiple Message Sequence :{ self .integ .seq :} \n " )
1462+ self .fh .write (" Message Type: {:4d}-{:-2d}\n " .
1463+ format (self .msgtype , self .subtype ))
1464+ if self .subtype == 9 : # MT54-9 VMAP
1465+ self .fh .write (f" TOF (s): { self .integ .tow :9.3f} \n " )
1466+ self .fh .write (f" Number of Area Points: { self .integ .narea :} \n " )
1467+ self .fh .write (f" Number of Azimuth Slices: {
1468+ self .integ .naz :} \n " )
1469+ self .fh .write (" Area Points (lat, long, alt):\n " )
1470+ for k in range (self .integ .narea ):
1471+ self .fh .write (" {:2d}\t {:12.9f}\t {:12.9f}\t {:4.0f}\n " .format
1472+ (k + 1 , self .integ .pos [k , 0 ], self .integ .pos [k , 1 ],
1473+ self .integ .pos [k , 2 ]))
1474+
1475+ self .fh .write (" Visibility mask (az, el):\n " )
1476+ for k in range (self .integ .naz ):
1477+ self .fh .write (" {:3.0f}\t {:3.0f}\n " .format
1478+ (self .integ .azel [k ][0 ], self .integ .azel [k ][1 ]))
1479+ elif self .subtype == 10 :
1480+ self .fh .write (f" TOF (s): { self .integ .tow :9.3f} \n " )
1481+ self .fh .write (f" Number of Area Points: { self .integ .narea :} \n " )
1482+ self .fh .write (f" Multipath Model ID: { self .integ .mm_id :} \n " )
1483+ self .fh .write (" Boundary Points (lat, long, alt):\n " )
1484+ for k in range (self .integ .narea ):
1485+ self .fh .write (" {:2d}\t {:12.9f}\t {:12.9f}\t {:4.0f}\n " .format
1486+ (k + 1 , self .integ .pos [k , 0 ], self .integ .pos [k , 1 ],
1487+ self .integ .pos [k , 2 ]))
1488+
1489+ if self .integ .mm_id == 0 :
1490+
1491+ self .fh .write (
1492+ " Components (Prob, Exp, stdev):\n " )
1493+ for k in range (self .integ .narea ):
1494+ for j in range (self .integ .np [k ]):
1495+ self .fh .write (" {:2d}\t {:1d}\t {:6.4f}\t {:7.2f}\t {:7.2f}\n " .format
1496+ (k + 1 , j + 1 , self .integ .mm_param [k ][j ][0 ],
1497+ self .integ .mm_param [k ][j ][1 ],
1498+ self .integ .mm_param [k ][j ][2 ]))
1499+ elif self .integ .mm_id in [1 , 2 ]:
1500+ n = 3 if self .integ .mm_id == 1 else 4
1501+ self .fh .write (
1502+ " Multipath Parameters (Modulation,a,b,c(,d)) :\n " )
1503+ for k in range (self .integ .narea ):
1504+ for j in range (self .integ .np [k ]):
1505+ s = int (self .integ .mm_param [k ][j ][0 ])
1506+ self .fh .write (" {:2d}\t {:1d}\t {:10s}" .format
1507+ (k + 1 , j + 1 , self .integ .mod_t [s ]))
1508+ for i in range (n ):
1509+ self .fh .write ("\t {:7.4f}" .format
1510+ (self .integ .mm_param [k ][j ][i + 1 ]))
1511+ self .fh .write ("\n " )
1512+
1513+ self .fh .flush ()
1514+
14551515 if eph is not None :
14561516 sys , prn = sat2prn (eph .sat )
14571517 self .fh .write (" {:20s}{:6d} ({:s})\n " .format ("PRN:" , prn ,
@@ -3026,22 +3086,22 @@ def decode_integrity_cnr_acg(self, msg, i):
30263086 def decode_integrity_vmap (self , msg , i ):
30273087 """ RTCM SC-134 Satellite Visibility Map Message (MT9) """
30283088
3029- if self .test_mode : # for test
3030- wg , st , rev = bs .unpack_from ('u4u8u8' , msg , i )
3031- i += 20
3032- self .subtype = st
3033- self .ver = rev
3034- self .wg = wg - 1
3035-
30363089 # GPS Epoch Time (TOW) DFi008
30373090 # number of area points DFi201
30383091 # Number of Azimuth Slices DFi205
30393092 # Message Continuation Flag DFi021
3040- tow , narea , naz , mcf = bs .unpack_from ('u30u8u6u1' , msg , i )
3093+
3094+ tow , narea , naz , mi = bs .unpack_from ('u30u8u6u1' , msg , i )
30413095 i += 45
3042- self .integ .pos = np .zeros ((narea , 3 ))
3096+ # Multiple Message Sequence Number DFi079
3097+ self .integ .seq = bs .unpack_from ('u5' , msg , i )[0 ]
3098+ i += 5
30433099
3044- tow *= 1e-3
3100+ self .integ .tow = tow * 1e-3
3101+ self .integ .narea = narea
3102+ self .integ .naz = naz
3103+ self .mi = mi
3104+ self .integ .pos = np .zeros ((narea , 3 ))
30453105
30463106 for k in range (narea ):
30473107 # Area Point - Lat DFi202
@@ -3052,71 +3112,59 @@ def decode_integrity_vmap(self, msg, i):
30523112
30533113 self .integ .pos [k , :] = [lat * 1.1e-8 , lon * 1.1e-8 , alt ]
30543114
3055- self .integ .azel = np .zeros ((naz , 2 ))
3115+ self .integ .azel = np .zeros ((naz , 2 ))
30563116
3057- # Azimuth DFi206
3058- # Elevation Mask DFi208
3059- az = 0
3060- for k in range (naz ):
3061- daz , mask_el = bs .unpack_from ('u9u7' , msg , i )
3062- i += 16
3063- az += daz
3064- self .integ .azel [k , :] = [az , mask_el ]
3117+ # Azimuth DFi206
3118+ # Elevation Mask DFi208
3119+ az = 0
3120+ for k in range (naz ):
3121+ daz , mask_el = bs .unpack_from ('u9u7' , msg , i )
3122+ i += 16
3123+ az += daz
3124+ self .integ .azel [k , :] = [az , mask_el ]
30653125
30663126 return i
30673127
30683128 def decode_integrity_mmap (self , msg , i ):
30693129 """ RTCM SC-134 Multipath Map Message (MT10) """
30703130
3071- if self .test_mode : # for test
3072- wg , st , rev = bs .unpack_from ('u4u8u8' , msg , i )
3073- i += 20
3074- self .subtype = st
3075- self .ver = rev
3076- self .wg = wg - 1
3077-
3078- # GPS Epoch Time (TOW) DFi008
3079- # number of area points DFi201
3080- # multipath model ID DFi209: 0:GMM,1:MBM,2:JM
3081- tow , narea , mm_id , mcf = bs .unpack_from (
3082- 'u30u8u3u1' , msg , i )
3083- i += 42
3084- tow *= 1e-3
3085- self .integ .pos = np .zeros ((narea , 3 ))
3086- self .integ .mm_id = mm_id
3087-
3088- if mm_id == 0 :
3131+ # GPS Epoch Time (TOW) DFi008
3132+ # number of area points DFi201
3133+ # multipath model ID DFi209: 0:GMM,1:MBM,2:JM
3134+ tow , narea , mm_id , self .mi , self .integ .seq = bs .unpack_from (
3135+ 'u30u8u3u1u5' , msg , i )
3136+ i += 47
3137+ self .integ .tow = tow * 1e-3
3138+ self .integ .narea = narea
3139+ self .integ .pos = np .zeros ((narea , 3 ))
3140+ self .integ .mm_id = mm_id
30893141
3090- for k in range (narea ):
3091- # Area Point - Lat DFi202
3092- # Area Point - Lon DFi203
3093- # Area Point - Height DFi204
3094- lat , lon , alt = bs .unpack_from ('s34s35s14' , msg , i )
3095- i += 83
3142+ sigmask = np .zeros (narea , dtype = np .int32 )
30963143
3097- self .integ .pos [k , :] = [lat * 1.1e-8 , lon * 1.1e-8 , alt ]
3144+ self .integ .np = np .zeros (narea , dtype = np .int32 )
3145+ self .integ .mm_param = {}
3146+ n = 4 if mm_id == 1 else 5
30983147
3099- elif mm_id == 1 or mm_id == 2 :
3100- sigmask = np .array (narea , dtype = np .int32 )
3101- for k in range (narea ):
3102- # GNSS Signal Modulation Mask - DFi214
3103- # Area Point - Lat DFi202
3104- # Area Point - Lon DFi203
3105- # Area Point - Height DFi204
3106- sigmask [k ], lat , lon , alt = bs .unpack_from (
3107- 'u8s34s35s14' , msg , i )
3108- i += 91
3109-
3110- self .integ .pos [k , :] = [lat * 1.1e-8 , lon * 1.1e-8 , alt ]
3148+ for k in range (narea ):
3149+ if mm_id in [1 , 2 ]:
3150+ sigmask [k ] = bs .unpack_from ('u8' , msg , i )[0 ]
3151+ i += 8
3152+ # Area Point - Lat DFi202
3153+ # Area Point - Lon DFi203
3154+ # Area Point - Height DFi204
3155+ lat , lon , alt = bs .unpack_from ('s34s35s14' , msg , i )
3156+ i += 83
3157+ self .integ .pos [k , :] = [lat * 1.1e-8 , lon * 1.1e-8 , alt ]
3158+ # i += 26 # ?
31113159
31123160 if mm_id == 0 :
31133161 # Number of GMM components DFi210
31143162 ngmm = bs .unpack_from ('u2' , msg , i )[0 ]
31153163 i += 2
3164+ self .integ .np [k ] = ngmm
3165+ prm = np .zeros ((ngmm , 3 ))
31163166
3117- self .integ .mm_param = np .zeros ((ngmm , 3 ))
3118-
3119- for k in range (ngmm ):
3167+ for j in range (ngmm ):
31203168 # GMM component probability DFi211
31213169 # GMM component expectation DFi212
31223170 # GMM component standard deviation DFi213
@@ -3126,33 +3174,34 @@ def decode_integrity_mmap(self, msg, i):
31263174 prob *= 0.0625
31273175 exp = self .integ .mu_k_t [exp_ ]
31283176 std = self .integ .sig_k_t [std_ ]
3129- self .integ .mm_param [k , :] = [prob , exp , std ]
3177+ prm [j , :] = [prob , exp , std ]
3178+
3179+ self .integ .mm_param [k ] = prm
31303180
31313181 elif mm_id == 1 or mm_id == 2 :
3132- self .integ .mm_param = {}
3133- n = 3 if mm_id == 1 else 4
3134-
3135- for k in range (narea ):
3136- sig_t , nsig = self .decode_mask (sigmask [k ], 8 , ofst = 0 )
3137- prm = np .zeros ((nsig , n ))
3138-
3139- for j in range (nsig ):
3140- # Multipath parameter a DFi215
3141- # Multipath parameter b DFi216
3142- # Multipath parameter c DFi217
3143- a , b , c = bs .unpack_from ('u4s5s5' , msg , i )
3144- i += 14
3182+ # mm_id=1: Mats Brenner Model Data
3183+ sig_t , nsig = self .decode_mask (sigmask [k ], 8 , ofst = 0 )
3184+ self .integ .np [k ] = nsig
3185+ prm = np .zeros ((nsig , n ))
3186+
3187+ for j in range (nsig ):
3188+ # Multipath parameter a DFi215
3189+ # Multipath parameter b DFi216
3190+ # Multipath parameter c DFi217
3191+ a , b , c = bs .unpack_from ('u4s5s5' , msg , i )
3192+ i += 14
31453193
3146- a = self .integ .sig_k_t [a ]
3147- prm [j , 0 :3 ] = [a , b * 0.25 , c * 0.0625 ]
3194+ prm [j , 0 ] = sig_t [j ]
3195+ a = self .integ .sig_k_t [a ]
3196+ prm [j , 1 :4 ] = [a , b * 0.25 , c * 0.0625 ]
31483197
3149- if mm_id == 2 :
3150- # Multipath parameter d DFi218
3151- d = bs .unpack_from ('u8' , msg , i )[0 ]
3152- i += 8
3153- prm [j , 3 ] = d * 0.3515625
3198+ if mm_id == 2 :
3199+ # Multipath parameter d DFi218
3200+ d = bs .unpack_from ('u8' , msg , i )[0 ]
3201+ i += 8
3202+ prm [j , 4 ] = d * 0.3515625
31543203
3155- self .integ .mm_param [k ] = prm
3204+ self .integ .mm_param [k ] = prm
31563205
31573206 return i
31583207
@@ -3201,6 +3250,19 @@ def decode_integrity_ssr(self, msg, i):
32013250 self .integ .iod_sys = iod_sys
32023251 self .integ .flag = flag_t
32033252
3253+ def decode_sc134_test_header (self , msg , i ):
3254+ # MT51-56 has subtype to extent message type space
3255+ # DFi028 uint8 as in Table 9-35
3256+
3257+ # Message Type DF002 uint12
3258+ # Working Group DFi020 uint4
3259+ # Sub-Message DFi028 uint8
3260+ # Message Revision DFi00x uint4 => uint8?
3261+ wg , self .subtype , self .ver = bs .unpack_from ('u4u8u8' , msg , i )
3262+ self .wg = wg - 1
3263+ i += 20
3264+ return i
3265+
32043266 def decode (self , msg , subtype = None , scanmode = False ):
32053267 """ decode RTCM messages """
32063268 i = 24
@@ -3370,12 +3432,13 @@ def decode(self, msg, subtype=None, scanmode=False):
33703432 self .subtype = sRTCM .INTEG_SSR_TROP
33713433 self .decode_integrity_ssr (msg , i )
33723434 elif self .msgtype == 54 : # SSR integrity test msg
3435+ i = self .decode_sc134_test_header (msg , i )
33733436 if self .subtype == 9 :
33743437 self .decode_integrity_vmap (msg , i )
3375- elif self .subtype == 10 :
3376- self .decode_integrity_mmap (msg , i )
3377- else :
3378- self .subtype = - 1
3438+ elif self .subtype == 10 :
3439+ self .decode_integrity_mmap (msg , i )
3440+ else :
3441+ self .subtype = - 1
33793442
33803443 if self .monlevel > 0 and self .fh is not None :
33813444 self .out_log (obs , eph , geph , seph )
0 commit comments