cssrlib 1.2.1__tar.gz → 1.3.2__tar.gz
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.
- {cssrlib-1.2.1/src/cssrlib.egg-info → cssrlib-1.3.2}/PKG-INFO +2 -1
- {cssrlib-1.2.1 → cssrlib-1.3.2}/pyproject.toml +2 -1
- {cssrlib-1.2.1 → cssrlib-1.3.2}/setup.cfg +1 -1
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/__init__.py +2 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/cssr_bds.py +21 -13
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/cssr_has.py +18 -16
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/cssr_mdc.py +64 -41
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/cssr_pvs.py +16 -11
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/cssrlib.py +808 -105
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/dgps.py +41 -22
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/ephemeris.py +96 -60
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/ewss.py +34 -30
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/gnss.py +589 -333
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/mlambda.py +174 -100
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/osnma.py +44 -39
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/peph.py +219 -117
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/plot.py +41 -16
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/pntpos.py +66 -34
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/ppp.py +97 -117
- cssrlib-1.3.2/src/cssrlib/ppprtk.py +23 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/pppssr.py +315 -177
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/qznma.py +49 -32
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/rawnav.py +97 -100
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/rinex.py +52 -59
- cssrlib-1.3.2/src/cssrlib/rtcm.py +4974 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/rtk.py +6 -10
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/sbas.py +213 -106
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/test/test_eph.py +1 -1
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/tlesim.py +4 -6
- cssrlib-1.3.2/src/cssrlib/utils.py +258 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2/src/cssrlib.egg-info}/PKG-INFO +2 -1
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib.egg-info/SOURCES.txt +1 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib.egg-info/requires.txt +1 -0
- cssrlib-1.2.1/src/cssrlib/ppprtk.py +0 -24
- cssrlib-1.2.1/src/cssrlib/rtcm.py +0 -2797
- {cssrlib-1.2.1 → cssrlib-1.3.2}/LICENSE +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/MANIFEST.in +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/README.md +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/data/30340780.21q +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/data/3034078M1.21O +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/data/SEPT078M.21P +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/data/SEPT078M1.21O +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/test/test_gnss.py +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/test/test_peph.py +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/test/test_rnx.py +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib/test/test_rtk.py +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib.egg-info/dependency_links.txt +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib.egg-info/not-zip-safe +0 -0
- {cssrlib-1.2.1 → cssrlib-1.3.2}/src/cssrlib.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cssrlib
|
|
3
|
-
Version: 1.2
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: Python Toolkit for PPP/PPP-RTK positioning
|
|
5
5
|
Home-page: https://github.com/hirokawa/cssrlib
|
|
6
6
|
Author: Rui Hirokawa
|
|
@@ -16,6 +16,7 @@ Requires-Dist: notebook
|
|
|
16
16
|
Requires-Dist: numpy
|
|
17
17
|
Requires-Dist: matplotlib
|
|
18
18
|
Requires-Dist: cartopy
|
|
19
|
+
Requires-Dist: cryptography
|
|
19
20
|
Dynamic: license-file
|
|
20
21
|
|
|
21
22
|
CSSRlib - Toolkit for PPP-RTK/RTK in Python using Compact SSR
|
|
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "cssrlib"
|
|
10
|
-
version = "1.2
|
|
10
|
+
version = "1.3.2"
|
|
11
11
|
description = "Python Toolkit for PPP/PPP-RTK positioning"
|
|
12
12
|
authors = [
|
|
13
13
|
{name="Rui Hirokawa", email="rui.hirokawa@gmail.com"},
|
|
@@ -23,4 +23,5 @@ dependencies = [
|
|
|
23
23
|
"numpy",
|
|
24
24
|
"matplotlib",
|
|
25
25
|
"cartopy",
|
|
26
|
+
"cryptography",
|
|
26
27
|
]
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
"""
|
|
2
|
-
BDS PPP correction data decoder
|
|
1
|
+
"""BDS PPP correction data decoder.
|
|
3
2
|
|
|
4
|
-
[1] BeiDou Navigation Satellite System Signal In Space
|
|
3
|
+
[1] BeiDou Navigation Satellite System Signal In Space ICD
|
|
5
4
|
Precise Point Positioning Service Signal PPP-B2b (Version 1.0), 2020
|
|
6
5
|
"""
|
|
7
6
|
|
|
@@ -12,7 +11,10 @@ from cssrlib.gnss import bdt2time, bdt2gpst, uGNSS, uSIG, uTYP, rSigRnx
|
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
class cssr_bds(cssr):
|
|
14
|
+
"""Class to decode BDS PPP (B2b) Compact SSR messages."""
|
|
15
|
+
|
|
15
16
|
def __init__(self, foutname=None):
|
|
17
|
+
"""Initialize BDS PPP SSR decoder."""
|
|
16
18
|
super().__init__(foutname)
|
|
17
19
|
self.MAXNET = 1
|
|
18
20
|
self.cssrmode = sCSSRTYPE.BDS_PPP
|
|
@@ -23,6 +25,7 @@ class cssr_bds(cssr):
|
|
|
23
25
|
self.cb_scl = 0.017
|
|
24
26
|
|
|
25
27
|
def ssig2rsig(self, sys: sGNSS, utyp: uTYP, ssig):
|
|
28
|
+
"""Convert SSR signal index to RINEX signal code."""
|
|
26
29
|
gps_tbl = {
|
|
27
30
|
0: uSIG.L1C,
|
|
28
31
|
1: uSIG.L1P,
|
|
@@ -72,13 +75,14 @@ class cssr_bds(cssr):
|
|
|
72
75
|
return rSigRnx(sys, utyp, usig_tbl[ssig])
|
|
73
76
|
|
|
74
77
|
def sval(self, u, n, scl):
|
|
75
|
-
"""
|
|
78
|
+
"""Calculate signed value based on n-bit int, lsb."""
|
|
76
79
|
invalid = -2**(n-1)
|
|
77
80
|
dnu = -(2**(n-1)-1) # this value seems to be invalid
|
|
78
81
|
y = np.nan if u == invalid or u == dnu else u*scl
|
|
79
82
|
return y
|
|
80
83
|
|
|
81
84
|
def slot2prn(self, slot):
|
|
85
|
+
"""Convert BDS B2b satellite slot index to system and PRN."""
|
|
82
86
|
prn = 0
|
|
83
87
|
sys = uGNSS.NONE
|
|
84
88
|
if slot >= 1 and slot <= 63:
|
|
@@ -96,6 +100,7 @@ class cssr_bds(cssr):
|
|
|
96
100
|
return sys, prn
|
|
97
101
|
|
|
98
102
|
def decode_head(self, msg, i, st=-1):
|
|
103
|
+
"""Decode BDS PPP message header."""
|
|
99
104
|
self.tod, _, iodssr = bs.unpack_from('u17u4u2', msg, i)
|
|
100
105
|
i += 23
|
|
101
106
|
|
|
@@ -107,10 +112,11 @@ class cssr_bds(cssr):
|
|
|
107
112
|
if self.week >= 0:
|
|
108
113
|
self.time = bdt2gpst(bdt2time(self.week, self.tow))
|
|
109
114
|
|
|
110
|
-
head = {'
|
|
115
|
+
head = {'udi': 0, 'mi': 0, 'iodssr': iodssr}
|
|
111
116
|
return head, i
|
|
112
117
|
|
|
113
118
|
def add_gnss(self, mask, blen, gnss):
|
|
119
|
+
"""Add decoded GNSS satellite mask entries."""
|
|
114
120
|
prn, nsat = self.decode_mask(mask, blen)
|
|
115
121
|
self.nsat_g[gnss] = nsat
|
|
116
122
|
self.nsat_n += nsat
|
|
@@ -124,7 +130,7 @@ class cssr_bds(cssr):
|
|
|
124
130
|
self.gnss_n.append(gnss)
|
|
125
131
|
|
|
126
132
|
def decode_cssr_mask(self, msg, i):
|
|
127
|
-
"""
|
|
133
|
+
"""Decode MT1 Mask message."""
|
|
128
134
|
head, i = self.decode_head(msg, i, sCSSR.MASK)
|
|
129
135
|
|
|
130
136
|
self.iodp = bs.unpack_from('u4', msg, i)[0]
|
|
@@ -179,6 +185,7 @@ class cssr_bds(cssr):
|
|
|
179
185
|
return i
|
|
180
186
|
|
|
181
187
|
def decode_cssr_orb_sat(self, msg, i, inet, sat_n):
|
|
188
|
+
"""Decode satellite orbit correction for BDS PPP."""
|
|
182
189
|
slot, iodn, iodc = bs.unpack_from('u9u10u3', msg, i)
|
|
183
190
|
i += 22
|
|
184
191
|
|
|
@@ -216,7 +223,7 @@ class cssr_bds(cssr):
|
|
|
216
223
|
return i
|
|
217
224
|
|
|
218
225
|
def decode_cssr_orb(self, msg, i, inet=0):
|
|
219
|
-
"""
|
|
226
|
+
"""Decode MT2 orbit + URA message."""
|
|
220
227
|
head, i = self.decode_head(msg, i)
|
|
221
228
|
sat_n = np.array(self.sat_n)
|
|
222
229
|
|
|
@@ -233,7 +240,7 @@ class cssr_bds(cssr):
|
|
|
233
240
|
return i
|
|
234
241
|
|
|
235
242
|
def decode_cssr_cbias(self, msg, i, inet=0):
|
|
236
|
-
"""
|
|
243
|
+
"""Decode MT3 Code Bias Correction message."""
|
|
237
244
|
head, i = self.decode_head(msg, i)
|
|
238
245
|
nsat = self.nsat_n
|
|
239
246
|
self.flg_net = False
|
|
@@ -270,7 +277,7 @@ class cssr_bds(cssr):
|
|
|
270
277
|
return i
|
|
271
278
|
|
|
272
279
|
def decode_cssr_clk_sat(self, msg, i, inet, sat):
|
|
273
|
-
"""
|
|
280
|
+
"""Decode clock correction for satellite."""
|
|
274
281
|
iodc, dclk = bs.unpack_from('u3s{:d}'.format(self.dclk_blen), msg, i)
|
|
275
282
|
i += 3+self.dclk_blen
|
|
276
283
|
|
|
@@ -285,7 +292,7 @@ class cssr_bds(cssr):
|
|
|
285
292
|
return i
|
|
286
293
|
|
|
287
294
|
def decode_cssr_clk(self, msg, i, inet=0):
|
|
288
|
-
"""
|
|
295
|
+
"""Decode MT4 Clock Correction message."""
|
|
289
296
|
head, i = self.decode_head(msg, i)
|
|
290
297
|
if self.iodssr != head['iodssr']:
|
|
291
298
|
return -1
|
|
@@ -311,7 +318,7 @@ class cssr_bds(cssr):
|
|
|
311
318
|
return i
|
|
312
319
|
|
|
313
320
|
def decode_cssr_ura(self, msg, i):
|
|
314
|
-
"""
|
|
321
|
+
"""Decode MT5 URA message."""
|
|
315
322
|
head, i = self.decode_head(msg, i)
|
|
316
323
|
if self.iodssr != head['iodssr']:
|
|
317
324
|
return -1
|
|
@@ -332,7 +339,7 @@ class cssr_bds(cssr):
|
|
|
332
339
|
return i
|
|
333
340
|
|
|
334
341
|
def decode_cssr_comb1(self, msg, i, inet=0):
|
|
335
|
-
"""
|
|
342
|
+
"""Decode MT6 combined message #1."""
|
|
336
343
|
numc, numo = bs.unpack_from('u5u3', msg, i)
|
|
337
344
|
sat_n = np.array(self.sat_n)
|
|
338
345
|
|
|
@@ -354,7 +361,7 @@ class cssr_bds(cssr):
|
|
|
354
361
|
return i
|
|
355
362
|
|
|
356
363
|
def decode_cssr_comb2(self, msg, i, inet=0):
|
|
357
|
-
"""
|
|
364
|
+
"""Decode MT7 combined message #2."""
|
|
358
365
|
numc, numo = bs.unpack_from('u5u3', msg, i)
|
|
359
366
|
sat_n = np.array(self.sat_n)
|
|
360
367
|
|
|
@@ -377,6 +384,7 @@ class cssr_bds(cssr):
|
|
|
377
384
|
return i
|
|
378
385
|
|
|
379
386
|
def decode_cssr(self, msg, i=0):
|
|
387
|
+
"""Decode BDS PPP B2b message."""
|
|
380
388
|
mt = bs.unpack_from('u6', msg, i)[0]
|
|
381
389
|
i += 6
|
|
382
390
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Galileo HAS correction data decoder
|
|
1
|
+
"""Galileo HAS correction data decoder.
|
|
3
2
|
|
|
4
3
|
[1] Galileo High Accuracy Service Signal-in-Space
|
|
5
4
|
Interface Control Document (HAS SIS ICD), Issue 1.0, May 2022
|
|
@@ -15,7 +14,10 @@ from binascii import unhexlify
|
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
class cssr_has(cssr):
|
|
17
|
+
"""Class to decode Galileo HAS Compact SSR messages."""
|
|
18
|
+
|
|
18
19
|
def __init__(self, foutname=None):
|
|
20
|
+
"""Initialize Galileo HAS SSR decoder."""
|
|
19
21
|
super().__init__(foutname)
|
|
20
22
|
self.MAXNET = 1
|
|
21
23
|
self.cssrmode = sCSSRTYPE.GAL_HAS_SIS
|
|
@@ -29,13 +31,14 @@ class cssr_has(cssr):
|
|
|
29
31
|
self.pb_scl = 0.01 # cycles
|
|
30
32
|
|
|
31
33
|
def sval(self, u, n, scl):
|
|
32
|
-
"""
|
|
34
|
+
"""Calculate signed value based on n-bit int, lsb."""
|
|
33
35
|
invalid = -2**(n-1)
|
|
34
36
|
dnu = 2**(n-1)-1
|
|
35
37
|
y = np.nan if u == invalid or u == dnu else u*scl
|
|
36
38
|
return y
|
|
37
39
|
|
|
38
40
|
def decode_cssr_clk_sub(self, msg, i=0):
|
|
41
|
+
"""Decode Galileo HAS clock subset correction message."""
|
|
39
42
|
head, i = self.decode_head(msg, i)
|
|
40
43
|
self.flg_net = False
|
|
41
44
|
if self.iodssr != head['iodssr']:
|
|
@@ -58,12 +61,11 @@ class cssr_has(cssr):
|
|
|
58
61
|
return i
|
|
59
62
|
|
|
60
63
|
def decode_head(self, msg, i, st=-1):
|
|
61
|
-
"""
|
|
62
|
-
|
|
64
|
+
"""Decode header part of HAS messages."""
|
|
63
65
|
if st == sCSSR.MASK:
|
|
64
|
-
|
|
66
|
+
udi = 0
|
|
65
67
|
else:
|
|
66
|
-
|
|
68
|
+
udi = bs.unpack_from('u4', msg, i)[0]
|
|
67
69
|
i += 4
|
|
68
70
|
|
|
69
71
|
if self.tow0 >= 0:
|
|
@@ -71,13 +73,12 @@ class cssr_has(cssr):
|
|
|
71
73
|
if self.week >= 0:
|
|
72
74
|
self.time = gpst2time(self.week, self.tow)
|
|
73
75
|
|
|
74
|
-
head = {'
|
|
76
|
+
head = {'udi': udi, 'mi': 0, 'iodssr': self.iodssr}
|
|
75
77
|
return head, i
|
|
76
78
|
|
|
77
79
|
def decode_cssr(self, msg, i=0):
|
|
78
|
-
"""
|
|
79
|
-
|
|
80
|
-
# Galileo HAS-SIS only defines MT=1, MT=4073 is CSSR message used in the
|
|
80
|
+
"""Decode HAS messages."""
|
|
81
|
+
# Galileo HAS-SIS only defines MT=1; MT=4073 is CSSR used in the
|
|
81
82
|
# Galileo HAS test dataset
|
|
82
83
|
#
|
|
83
84
|
if self.msgtype != 1 and self.msgtype != 4073:
|
|
@@ -131,9 +132,10 @@ class cssr_has(cssr):
|
|
|
131
132
|
|
|
132
133
|
|
|
133
134
|
class cnav_msg():
|
|
134
|
-
"""
|
|
135
|
+
"""Class to handle Galileo E6 (CNAV) message."""
|
|
135
136
|
|
|
136
137
|
def __init__(self):
|
|
138
|
+
"""Initialize Galileo C/NAV HAS message decoder."""
|
|
137
139
|
self.mid_decoded = []
|
|
138
140
|
self.mid_ = -1
|
|
139
141
|
self.ms_ = -1
|
|
@@ -148,10 +150,11 @@ class cnav_msg():
|
|
|
148
150
|
self.monlevel = 0
|
|
149
151
|
|
|
150
152
|
def load_gmat(self, file_gm):
|
|
153
|
+
"""Load Reed-Solomon generator matrix for Galileo HAS decoding."""
|
|
151
154
|
self.gMat = np.genfromtxt(file_gm, dtype="u1", delimiter=",")
|
|
152
155
|
|
|
153
156
|
def decode_has_header(self, buff, i):
|
|
154
|
-
"""
|
|
157
|
+
"""Decode header of HAS pages (obsoleted)."""
|
|
155
158
|
if bs.unpack_from('u24', buff, i)[0] == 0xaf3bc3:
|
|
156
159
|
return 0, 0, 0, 0, 0
|
|
157
160
|
|
|
@@ -160,7 +163,7 @@ class cnav_msg():
|
|
|
160
163
|
return hass, mt, mid, ms, pid
|
|
161
164
|
|
|
162
165
|
def decode_has_page(self, idx, has_pages, gMat, ms):
|
|
163
|
-
""" HPVRS
|
|
166
|
+
"""Decode HPVRS Reed-Solomon RS(255,32,224) page."""
|
|
164
167
|
HASmsg = bytes()
|
|
165
168
|
k = len(idx)
|
|
166
169
|
if k >= ms:
|
|
@@ -172,8 +175,7 @@ class cnav_msg():
|
|
|
172
175
|
return HASmsg
|
|
173
176
|
|
|
174
177
|
def decode_cnav(self, tow, vi):
|
|
175
|
-
"""
|
|
176
|
-
|
|
178
|
+
"""Decode Galileo CNAV message."""
|
|
177
179
|
HASmsg = None
|
|
178
180
|
|
|
179
181
|
for vn in vi:
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
"""
|
|
2
|
-
QZSS MADOCA-PPP correction data decoder
|
|
1
|
+
"""QZSS MADOCA-PPP correction data decoder.
|
|
3
2
|
|
|
4
3
|
[1] Quasi-Zenith Satellite System Interface Specification Multi-GNSS
|
|
5
4
|
Advanced Orbit and Clock Augmentation - Precise Point Positioning
|
|
6
|
-
(IS-QZSS-MDC-
|
|
5
|
+
(IS-QZSS-MDC-005draft), October, 2026
|
|
7
6
|
|
|
8
7
|
"""
|
|
9
8
|
|
|
@@ -11,10 +10,14 @@ import numpy as np
|
|
|
11
10
|
import bitstruct as bs
|
|
12
11
|
from cssrlib.cssrlib import cssr, sCSSRTYPE, sCSSR, local_corr, sCType
|
|
13
12
|
from cssrlib.gnss import gpst2time, time2str, uGNSS, prn2sat, rCST, sat2id
|
|
13
|
+
from cssrlib.gnss import pos2ecef, gtime_t
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class areaInfo():
|
|
17
|
+
"""Class to store MADOCA-PPP service area information."""
|
|
18
|
+
|
|
17
19
|
def __init__(self, sid, latr, lonr, p1=0, p2=0):
|
|
20
|
+
"""Initialize MADOCA-PPP area information."""
|
|
18
21
|
self.sid = sid
|
|
19
22
|
self.latr = latr
|
|
20
23
|
self.lonr = lonr
|
|
@@ -26,7 +29,10 @@ class areaInfo():
|
|
|
26
29
|
|
|
27
30
|
|
|
28
31
|
class ionoCorr():
|
|
32
|
+
"""Class to store MADOCA-PPP regional ionospheric corrections."""
|
|
33
|
+
|
|
29
34
|
def __init__(self):
|
|
35
|
+
"""Initialize MADOCA-PPP ionospheric correction data."""
|
|
30
36
|
self.t0 = None
|
|
31
37
|
self.qi = []
|
|
32
38
|
self.iodssr = 0
|
|
@@ -36,7 +42,10 @@ class ionoCorr():
|
|
|
36
42
|
|
|
37
43
|
|
|
38
44
|
class cssr_mdc(cssr):
|
|
45
|
+
"""Class to decode QZSS MADOCA-PPP L6D/L6E messages."""
|
|
46
|
+
|
|
39
47
|
def __init__(self, foutname=None):
|
|
48
|
+
"""Initialize MADOCA-PPP L6 message decoder."""
|
|
40
49
|
super().__init__(foutname)
|
|
41
50
|
|
|
42
51
|
self.cssrmode = sCSSRTYPE.QZS_MADOCA
|
|
@@ -44,6 +53,8 @@ class cssr_mdc(cssr):
|
|
|
44
53
|
|
|
45
54
|
self.pnt = {}
|
|
46
55
|
self.ci = {}
|
|
56
|
+
self.reg_alrt = {}
|
|
57
|
+
self.reg_iod = {}
|
|
47
58
|
|
|
48
59
|
self.area = -1
|
|
49
60
|
self.reg = -1
|
|
@@ -51,6 +62,10 @@ class cssr_mdc(cssr):
|
|
|
51
62
|
self.narea_t = {1: 8, 2: 16, 3: 5, 4: 1, 5: 8}
|
|
52
63
|
self.MAXNET = np.sum(list(self.narea_t.values()))
|
|
53
64
|
|
|
65
|
+
self.tmax = {sCType.CLOCK: 60.0, sCType.ORBIT: 60.0,
|
|
66
|
+
sCType.CBIAS: 60.0, sCType.PBIAS: 60.0,
|
|
67
|
+
sCType.TROP: 120.0, sCType.STEC: 300.0}
|
|
68
|
+
|
|
54
69
|
for inet in range(self.MAXNET+1):
|
|
55
70
|
self.lc.append(local_corr())
|
|
56
71
|
self.lc[inet].inet = inet
|
|
@@ -60,35 +75,40 @@ class cssr_mdc(cssr):
|
|
|
60
75
|
self.lc[inet].t0 = {}
|
|
61
76
|
|
|
62
77
|
def find_grid_index(self, pos):
|
|
63
|
-
"""
|
|
64
|
-
|
|
78
|
+
"""Find region/area."""
|
|
65
79
|
latd, lond = np.rad2deg(pos[0:2])
|
|
80
|
+
rr = pos2ecef(pos)
|
|
66
81
|
self.reg = self.area = -1
|
|
82
|
+
min_dist = 1e5
|
|
67
83
|
|
|
68
84
|
for reg in self.pnt.keys():
|
|
85
|
+
if self.reg_alrt.get(reg, 0) != 0:
|
|
86
|
+
continue
|
|
69
87
|
for area in self.pnt[reg].keys():
|
|
70
88
|
p = self.pnt[reg][area]
|
|
89
|
+
ref_ecef = pos2ecef(
|
|
90
|
+
np.array([p.latr*rCST.D2R, p.lonr*rCST.D2R, 0.0]))
|
|
91
|
+
dist = np.linalg.norm(rr - ref_ecef)*1e-3 # [km]
|
|
92
|
+
if dist > min_dist:
|
|
93
|
+
continue
|
|
71
94
|
if p.sid == 0: # rectangle shape:
|
|
72
95
|
if p.latr-p.lats <= latd and latd <= p.latr+p.lats and \
|
|
73
96
|
p.lonr-p.lons <= lond and lond <= p.lonr+p.lons:
|
|
74
97
|
self.reg = reg
|
|
75
98
|
self.area = area
|
|
76
|
-
|
|
99
|
+
min_dist = dist
|
|
77
100
|
elif p.sid == 1: # circle
|
|
78
|
-
|
|
79
|
-
de = (lond - p.lonr)*rCST.D2R * \
|
|
80
|
-
rCST.RE_WGS84*np.cos(p.lonr*rCST.D2R)
|
|
81
|
-
r = np.sqrt(dn**2+de**2)
|
|
82
|
-
if r <= p.rng:
|
|
101
|
+
if dist <= p.rng:
|
|
83
102
|
self.reg = reg
|
|
84
103
|
self.area = area
|
|
85
|
-
|
|
104
|
+
min_dist = dist
|
|
86
105
|
|
|
87
106
|
inet = self.get_inet(self.reg, self.area)
|
|
107
|
+
self.inet = inet
|
|
88
108
|
return inet
|
|
89
109
|
|
|
90
110
|
def get_dpos(self, pos):
|
|
91
|
-
"""
|
|
111
|
+
"""Calculate position offset from reference."""
|
|
92
112
|
if self.reg < 0 or self.area < 0:
|
|
93
113
|
print("get_dpos: region, area not defined.")
|
|
94
114
|
return 0, 0
|
|
@@ -101,7 +121,7 @@ class cssr_mdc(cssr):
|
|
|
101
121
|
return dlat, dlon
|
|
102
122
|
|
|
103
123
|
def get_stec(self, dlat=0.0, dlon=0.0):
|
|
104
|
-
"""
|
|
124
|
+
"""Calculate STEC correction by interporation."""
|
|
105
125
|
if self.inet < 0:
|
|
106
126
|
print("get_stec: region, area not defined.")
|
|
107
127
|
return np.zeros(self.nsat_n)
|
|
@@ -118,14 +138,19 @@ class cssr_mdc(cssr):
|
|
|
118
138
|
return stec
|
|
119
139
|
|
|
120
140
|
def decode_mdc_stec_area(self, buff, i=0):
|
|
121
|
-
"""
|
|
141
|
+
"""Decode MT1 STEC coverage message."""
|
|
122
142
|
tow, uid, mi, iodssr = bs.unpack_from('u20u4u1u4', buff, i)
|
|
123
143
|
i += 29
|
|
144
|
+
self.tow = tow
|
|
124
145
|
self.tow0 = tow//3600*3600
|
|
146
|
+
if self.week >= 0:
|
|
147
|
+
self.time = gpst2time(self.week, self.tow)
|
|
125
148
|
reg, alrt, len_, narea = bs.unpack_from('u8u1u16u5', buff, i)
|
|
126
149
|
i += 30
|
|
127
150
|
self.reg = reg
|
|
128
151
|
self.alrt = alrt
|
|
152
|
+
self.reg_alrt[reg] = alrt
|
|
153
|
+
self.reg_iod[reg] = iodssr
|
|
129
154
|
|
|
130
155
|
if reg not in self.pnt:
|
|
131
156
|
self.pnt[reg] = {}
|
|
@@ -152,8 +177,7 @@ class cssr_mdc(cssr):
|
|
|
152
177
|
return i
|
|
153
178
|
|
|
154
179
|
def get_inet(self, reg, area):
|
|
155
|
-
""" region
|
|
156
|
-
|
|
180
|
+
"""Convert region and area ID to network index."""
|
|
157
181
|
if reg < 0 or area < 0:
|
|
158
182
|
return -1
|
|
159
183
|
|
|
@@ -168,9 +192,17 @@ class cssr_mdc(cssr):
|
|
|
168
192
|
return inet
|
|
169
193
|
|
|
170
194
|
def decode_mdc_stec_corr(self, buff, i=0):
|
|
171
|
-
"""
|
|
195
|
+
"""Decode MT2 STEC correction message."""
|
|
172
196
|
dtow, uid, mi, iodssr = bs.unpack_from('u12u4u1u4', buff, i)
|
|
173
197
|
i += 21
|
|
198
|
+
if self.tow0 >= 0:
|
|
199
|
+
tow = self.tow0 + dtow
|
|
200
|
+
if self.tow >= 0 and tow < self.tow - 1800:
|
|
201
|
+
tow += 3600
|
|
202
|
+
self.tow = tow
|
|
203
|
+
t0 = gpst2time(self.week, self.tow) if self.week >= 0 else gtime_t()
|
|
204
|
+
if self.week >= 0:
|
|
205
|
+
self.time = t0
|
|
174
206
|
reg, area, stype_ = bs.unpack_from('u8u5u2', buff, i)
|
|
175
207
|
i += 15
|
|
176
208
|
|
|
@@ -184,7 +216,6 @@ class cssr_mdc(cssr):
|
|
|
184
216
|
|
|
185
217
|
inet = self.get_inet(reg, area)
|
|
186
218
|
|
|
187
|
-
self.lc[inet].nsat_n = np.sum(nsat)
|
|
188
219
|
ci = {}
|
|
189
220
|
qi = {}
|
|
190
221
|
stype = {}
|
|
@@ -193,39 +224,29 @@ class cssr_mdc(cssr):
|
|
|
193
224
|
for gnss in range(5):
|
|
194
225
|
sys = sys_t[gnss]
|
|
195
226
|
for k in range(nsat[gnss]):
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
prn, qi_, c00 = bs.unpack_from('u6u6s14', buff, i)
|
|
199
|
-
i += 26
|
|
227
|
+
prn, cls_, val = bs.unpack_from('u6u3u3', buff, i)
|
|
228
|
+
i += 12
|
|
200
229
|
|
|
201
230
|
if sys == uGNSS.QZS:
|
|
202
231
|
prn += 192
|
|
203
232
|
sat = prn2sat(sys, prn)
|
|
204
|
-
|
|
233
|
+
ci_sat, i = self.decode_cssr_stec_coeff(buff, stype_, i)
|
|
234
|
+
if np.isnan(ci_sat).any():
|
|
235
|
+
continue
|
|
236
|
+
qi[sat] = self.quality_idx(cls_, val)
|
|
205
237
|
stype[sat] = stype_
|
|
206
|
-
|
|
207
|
-
if stype_ > 0:
|
|
208
|
-
c01, c10 = bs.unpack_from('s12s12', buff, i)
|
|
209
|
-
i += 24
|
|
210
|
-
if stype_ > 1:
|
|
211
|
-
c11 = bs.unpack_from('s10', buff, i)[0]
|
|
212
|
-
i += 10
|
|
213
|
-
if stype_ > 2:
|
|
214
|
-
c02, c20 = bs.unpack_from('s8s8', buff, i)
|
|
215
|
-
i += 16
|
|
216
|
-
|
|
217
238
|
sat_ += [sat]
|
|
218
|
-
ci[sat] =
|
|
219
|
-
|
|
220
|
-
c02*5e-3, c20*5e-3])
|
|
239
|
+
ci[sat] = ci_sat
|
|
240
|
+
self.set_t0(inet, sat, sCType.STEC, t0)
|
|
221
241
|
j += 1
|
|
222
242
|
|
|
243
|
+
self.lc[inet].nsat_n = len(sat_)
|
|
244
|
+
self.lc[inet].flg_stec = 2
|
|
223
245
|
self.lc[inet].stype = stype
|
|
224
246
|
self.lc[inet].sat_n = sat_
|
|
225
247
|
self.lc[inet].ci = ci
|
|
226
248
|
self.lc[inet].stec_quality = qi
|
|
227
249
|
|
|
228
|
-
t0 = gpst2time(self.week, self.tow0+dtow)
|
|
229
250
|
self.set_t0(inet, 0, sCType.STEC, t0)
|
|
230
251
|
self.lc[inet].cstat |= (1 << sCType.STEC)
|
|
231
252
|
|
|
@@ -236,7 +257,7 @@ class cssr_mdc(cssr):
|
|
|
236
257
|
def out_log(self):
|
|
237
258
|
# if self.msgtype not in (1, 2):
|
|
238
259
|
# return super(cssr_mdc, self).out_log()
|
|
239
|
-
|
|
260
|
+
"""Write decoded MADOCA-PPP STEC messages to log file."""
|
|
240
261
|
sz_t = [1, 3, 4, 6]
|
|
241
262
|
|
|
242
263
|
if self.time == -1:
|
|
@@ -276,9 +297,11 @@ class cssr_mdc(cssr):
|
|
|
276
297
|
self.fh.flush()
|
|
277
298
|
|
|
278
299
|
def decode_cssr(self, msg, i=0):
|
|
279
|
-
"""
|
|
300
|
+
"""Decode Compact SSR message with MADOCA-PPP extension."""
|
|
280
301
|
df = {'msgtype': 4073}
|
|
281
302
|
while df['msgtype'] in [1, 2, 4073]:
|
|
303
|
+
if len(msg)*8 < i + 16:
|
|
304
|
+
return 0
|
|
282
305
|
df = bs.unpack_from_dict('u12u4', ['msgtype', 'subtype'], msg, i)
|
|
283
306
|
i += 16
|
|
284
307
|
if df['msgtype'] not in [1, 2, 4073]:
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
"""
|
|
2
|
-
PVS (PPP via SouthPAN) correction data decoder
|
|
1
|
+
"""PVS (PPP via SouthPAN) correction data decoder.
|
|
3
2
|
|
|
4
3
|
[1] Service Definition Document for Open Services, SBAS-STN-0001,
|
|
5
|
-
Revision
|
|
4
|
+
Revision 04, April 2026
|
|
6
5
|
|
|
7
6
|
[2] Service Definition Document for Data Access Services, SBAS-STN-0002,
|
|
8
|
-
Revision
|
|
7
|
+
Revision 02, April 2026
|
|
9
8
|
|
|
10
9
|
For use of SSR corrections see section A 3.9.2 in
|
|
11
10
|
|
|
@@ -24,7 +23,7 @@ from binascii import unhexlify
|
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
def decode_sinca_line(line):
|
|
27
|
-
""" SINCA (SISNeT compression algorithm)
|
|
26
|
+
"""Decode SINCA (SISNeT compression algorithm) line."""
|
|
28
27
|
if line[0:4] != '*MSG':
|
|
29
28
|
return None
|
|
30
29
|
v = line.split(',')
|
|
@@ -47,7 +46,10 @@ def decode_sinca_line(line):
|
|
|
47
46
|
|
|
48
47
|
|
|
49
48
|
class cssr_pvs(cssr):
|
|
49
|
+
"""Class to decode SouthPAN PVS PPP messages."""
|
|
50
|
+
|
|
50
51
|
def __init__(self, foutname=None):
|
|
52
|
+
"""Initialize PVS PPP decoder."""
|
|
51
53
|
super().__init__(foutname)
|
|
52
54
|
self.MAXNET = 1
|
|
53
55
|
self.cssrmode = sCSSRTYPE.PVS_PPP
|
|
@@ -67,6 +69,7 @@ class cssr_pvs(cssr):
|
|
|
67
69
|
self.nav_mode = {uGNSS.GPS: 0, uGNSS.GAL: 1}
|
|
68
70
|
|
|
69
71
|
def slot2sat(self, slot):
|
|
72
|
+
"""Convert satellite slot index to satellite number."""
|
|
70
73
|
sat = 0
|
|
71
74
|
if slot >= 1 and slot <= 32:
|
|
72
75
|
prn = slot
|
|
@@ -86,14 +89,16 @@ class cssr_pvs(cssr):
|
|
|
86
89
|
return sat
|
|
87
90
|
|
|
88
91
|
def adjust_time_week(self, time, time0):
|
|
92
|
+
"""Adjust time-of-week for week rollover."""
|
|
89
93
|
dt = timediff(time, time0)
|
|
90
|
-
if dt > rCST.
|
|
91
|
-
time = timeadd(time, -rCST.
|
|
92
|
-
elif dt < -rCST.
|
|
93
|
-
time = timeadd(time, rCST.
|
|
94
|
+
if dt > rCST.HALFWEEK_SEC:
|
|
95
|
+
time = timeadd(time, -rCST.WEEK_SEC)
|
|
96
|
+
elif dt < -rCST.HALFWEEK_SEC:
|
|
97
|
+
time = timeadd(time, rCST.WEEK_SEC)
|
|
94
98
|
return time
|
|
95
99
|
|
|
96
100
|
def check_validity(self, time):
|
|
101
|
+
"""Check validity time of PVS SSR corrections."""
|
|
97
102
|
for sat in self.sat_n:
|
|
98
103
|
if timediff(time, self.lc[0].t0[sat][sCType.CLOCK]) > \
|
|
99
104
|
self.tmax[sCType.CLOCK]:
|
|
@@ -104,7 +109,7 @@ class cssr_pvs(cssr):
|
|
|
104
109
|
self.lc[0].dorb[sat] = np.zeros(3)
|
|
105
110
|
|
|
106
111
|
def decode_cssr_orb(self, msg, i, inet=0):
|
|
107
|
-
"""
|
|
112
|
+
"""Decode Type 32 clock-ephemeris correction and covariance matrix."""
|
|
108
113
|
slot, iodn = bs.unpack_from('u8u10', msg, i)
|
|
109
114
|
i += 18
|
|
110
115
|
dx, dy, dz, db = bs.unpack_from('s11s11s11s12', msg, i)
|
|
@@ -158,7 +163,7 @@ class cssr_pvs(cssr):
|
|
|
158
163
|
return i
|
|
159
164
|
|
|
160
165
|
def decode_cssr(self, msg, i=0):
|
|
161
|
-
|
|
166
|
+
"""Decode PVS PPP DFMC SBAS message."""
|
|
162
167
|
_, mt = bs.unpack_from('u4u6', msg, i)
|
|
163
168
|
i += 10
|
|
164
169
|
|