cssrlib 0.8.0__tar.gz → 1.0.1__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.
Files changed (48) hide show
  1. {cssrlib-0.8.0/src/cssrlib.egg-info → cssrlib-1.0.1}/PKG-INFO +14 -16
  2. {cssrlib-0.8.0 → cssrlib-1.0.1}/README.md +12 -14
  3. {cssrlib-0.8.0 → cssrlib-1.0.1}/setup.cfg +2 -2
  4. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/cssr_bds.py +75 -45
  5. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/cssr_has.py +10 -3
  6. cssrlib-1.0.1/src/cssrlib/cssr_pvs.py +176 -0
  7. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/cssrlib.py +224 -161
  8. cssrlib-1.0.1/src/cssrlib/dgps.py +289 -0
  9. cssrlib-1.0.1/src/cssrlib/ephemeris.py +894 -0
  10. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/gnss.py +139 -44
  11. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/peph.py +126 -18
  12. cssrlib-1.0.1/src/cssrlib/pntpos.py +546 -0
  13. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/ppp.py +27 -2
  14. cssrlib-1.0.1/src/cssrlib/ppprtk.py +24 -0
  15. cssrlib-1.0.1/src/cssrlib/pppssr.py +1412 -0
  16. cssrlib-1.0.1/src/cssrlib/rawnav.py +1662 -0
  17. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/rinex.py +282 -51
  18. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/rtcm.py +198 -113
  19. cssrlib-1.0.1/src/cssrlib/rtk.py +56 -0
  20. cssrlib-1.0.1/src/cssrlib/sbas.py +1073 -0
  21. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/test/test_eph.py +1 -1
  22. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/test/test_gnss.py +5 -2
  23. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/test/test_peph.py +26 -22
  24. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/test/test_rtk.py +8 -7
  25. {cssrlib-0.8.0 → cssrlib-1.0.1/src/cssrlib.egg-info}/PKG-INFO +14 -16
  26. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib.egg-info/SOURCES.txt +3 -1
  27. cssrlib-0.8.0/src/cssrlib/ephemeris.py +0 -332
  28. cssrlib-0.8.0/src/cssrlib/pntpos.py +0 -125
  29. cssrlib-0.8.0/src/cssrlib/pppigs.py +0 -926
  30. cssrlib-0.8.0/src/cssrlib/ppprtk.py +0 -416
  31. cssrlib-0.8.0/src/cssrlib/pppssr.py +0 -1045
  32. cssrlib-0.8.0/src/cssrlib/rawnav.py +0 -522
  33. cssrlib-0.8.0/src/cssrlib/rtk.py +0 -546
  34. {cssrlib-0.8.0 → cssrlib-1.0.1}/LICENSE +0 -0
  35. {cssrlib-0.8.0 → cssrlib-1.0.1}/MANIFEST.in +0 -0
  36. {cssrlib-0.8.0 → cssrlib-1.0.1}/pyproject.toml +0 -0
  37. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/__init__.py +0 -0
  38. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/data/30340780.21q +0 -0
  39. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/data/3034078M1.21O +0 -0
  40. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/data/SEPT078M.21P +0 -0
  41. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/data/SEPT078M1.21O +0 -0
  42. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/mlambda.py +0 -0
  43. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/plot.py +0 -0
  44. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/test/test_rnx.py +0 -0
  45. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib/tlesim.py +0 -0
  46. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib.egg-info/dependency_links.txt +0 -0
  47. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib.egg-info/not-zip-safe +0 -0
  48. {cssrlib-0.8.0 → cssrlib-1.0.1}/src/cssrlib.egg-info/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cssrlib
3
- Version: 0.8.0
4
- Summary: Compact SSR Library for PPP/PPP-RTK
3
+ Version: 1.0.1
4
+ Summary: Python Toolkit for PPP/PPP-RTK positioning
5
5
  Home-page: https://github.com/hirokawa/cssrlib
6
6
  Author: Rui Hirokawa
7
7
  Author-email: rui.hirokawa@gmail.com
@@ -30,7 +30,7 @@ It supports the following open format:
30
30
  ************************************************
31
31
  Click this button for a quick demo in Google Colab
32
32
 
33
- <a target="_blank" href="https://colab.research.google.com/github/rtklibexplorer/cssrlib/blob/new_sig/tutorials/cssrlib.ipynb">
33
+ <a target="_blank" href="https://colab.research.google.com/github/hirokawa/cssrlib/blob/main/tutorials/cssrlib.ipynb">
34
34
  <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
35
35
  </a>
36
36
 
@@ -38,17 +38,10 @@ Click this button for a quick demo in Google Colab
38
38
 
39
39
  Prerequisites
40
40
  =============
41
- Additional python packages are required as prerequisites and can be installed via the following commands
41
+ Additional python packages are required as prerequisites and can be installed via the following command
42
42
 
43
43
  ```
44
- pip install bitstruct galois crccheck
45
- pip install notebook numpy matplotlib
46
- ```
47
-
48
- Optionally, on linux, users can install the `cartopy` package
49
-
50
- ```
51
- pip install cartopy
44
+ pip install -r requirements.txt
52
45
  ```
53
46
 
54
47
  If the installation of `cartopy` fails, try installing `libgeos++-dev` first.
@@ -89,9 +82,14 @@ Run RTK sample.
89
82
  python test_rtk.py
90
83
  ```
91
84
 
92
- Other samples are also available in a separate repository [`cssrlib-data`](https://github.com/hirokawa/cssrlib-data) including :
85
+ Other samples with dataset are also available in a separate repository [`cssrlib-data`](https://github.com/hirokawa/cssrlib-data) including :
86
+
87
+ - Galileo-HAS PPP (SIS/IDD) processing example
88
+ - BDS-PPP processing example
89
+ - QZSS MADOCA-PPP processing example
90
+ - QZSS CLAS PPP-RTK processing example
91
+ - IGS (SP3+BIAS) PPP-AR processing example
92
+ - (experimental) PPP via SouthPAN (PVS) processing example
93
+ - Binary message parser for Septentrio receiver (Mosaic/PolaRX5)
93
94
 
94
- - Galileo-HAS decoder
95
- - BDS-PPP decoder
96
- - Jupyter-Notebook including samples for RTK/PPP-RTK.
97
95
 
@@ -15,7 +15,7 @@ It supports the following open format:
15
15
  ************************************************
16
16
  Click this button for a quick demo in Google Colab
17
17
 
18
- <a target="_blank" href="https://colab.research.google.com/github/rtklibexplorer/cssrlib/blob/new_sig/tutorials/cssrlib.ipynb">
18
+ <a target="_blank" href="https://colab.research.google.com/github/hirokawa/cssrlib/blob/main/tutorials/cssrlib.ipynb">
19
19
  <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
20
20
  </a>
21
21
 
@@ -23,17 +23,10 @@ Click this button for a quick demo in Google Colab
23
23
 
24
24
  Prerequisites
25
25
  =============
26
- Additional python packages are required as prerequisites and can be installed via the following commands
26
+ Additional python packages are required as prerequisites and can be installed via the following command
27
27
 
28
28
  ```
29
- pip install bitstruct galois crccheck
30
- pip install notebook numpy matplotlib
31
- ```
32
-
33
- Optionally, on linux, users can install the `cartopy` package
34
-
35
- ```
36
- pip install cartopy
29
+ pip install -r requirements.txt
37
30
  ```
38
31
 
39
32
  If the installation of `cartopy` fails, try installing `libgeos++-dev` first.
@@ -74,9 +67,14 @@ Run RTK sample.
74
67
  python test_rtk.py
75
68
  ```
76
69
 
77
- Other samples are also available in a separate repository [`cssrlib-data`](https://github.com/hirokawa/cssrlib-data) including :
70
+ Other samples with dataset are also available in a separate repository [`cssrlib-data`](https://github.com/hirokawa/cssrlib-data) including :
71
+
72
+ - Galileo-HAS PPP (SIS/IDD) processing example
73
+ - BDS-PPP processing example
74
+ - QZSS MADOCA-PPP processing example
75
+ - QZSS CLAS PPP-RTK processing example
76
+ - IGS (SP3+BIAS) PPP-AR processing example
77
+ - (experimental) PPP via SouthPAN (PVS) processing example
78
+ - Binary message parser for Septentrio receiver (Mosaic/PolaRX5)
78
79
 
79
- - Galileo-HAS decoder
80
- - BDS-PPP decoder
81
- - Jupyter-Notebook including samples for RTK/PPP-RTK.
82
80
 
@@ -1,9 +1,9 @@
1
1
  [metadata]
2
2
  name = cssrlib
3
- version = 0.8.0
3
+ version = 1.0.1
4
4
  author = Rui Hirokawa
5
5
  author_email = rui.hirokawa@gmail.com
6
- description = Compact SSR Library for PPP/PPP-RTK
6
+ description = Python Toolkit for PPP/PPP-RTK positioning
7
7
  long_description = file: README.md
8
8
  long_description_content_type = text/markdown
9
9
  url = https://github.com/hirokawa/cssrlib
@@ -19,6 +19,8 @@ class cssr_bds(cssr):
19
19
  self.nsig_max = 8
20
20
  self.iodp = -1
21
21
  self.iodp_p = -1
22
+ self.cb_blen = 12
23
+ self.cb_scl = 0.017
22
24
 
23
25
  def ssig2rsig(self, sys: sGNSS, utyp: uTYP, ssig):
24
26
  gps_tbl = {
@@ -156,47 +158,61 @@ class cssr_bds(cssr):
156
158
  self.add_gnss(mask_glo, 37, sGNSS.GLO)
157
159
 
158
160
  inet = 0
159
- self.lc[inet].dclk = np.ones(self.nsat_n)*np.nan
160
- self.lc[inet].dorb = np.ones((self.nsat_n, 3))*np.nan
161
- self.lc[inet].iode = np.zeros(self.nsat_n, dtype=int)
162
- self.lc[inet].iodc = np.zeros(self.nsat_n, dtype=int)
163
- self.lc[inet].iodc_c = np.zeros(self.nsat_n, dtype=int)
164
- self.lc[inet].cbias = np.ones((self.nsat_n, self.nsig_max))*np.nan
161
+ self.lc[inet].dclk = {}
162
+ self.lc[inet].dorb = {}
163
+ self.lc[inet].iode = {}
164
+ self.lc[inet].iodc = {}
165
+ self.lc[inet].iodc_c = {}
166
+ self.lc[inet].cbias = {}
165
167
  self.nsig_n = np.ones(self.nsat_n, dtype=int)*self.nsig_max
166
- self.sig_n = -1*np.ones((self.nsat_n, self.nsig_max), dtype=int)
167
- self.ura = np.zeros(self.nsat_n)
168
+ self.sig_n = {}
169
+ self.ura = {}
168
170
 
169
171
  # fallback for inconsistent clock update
170
- self.lc[inet].dclk_p = np.ones(self.nsat_n)*np.nan
171
- self.lc[inet].iodc_c_p = np.zeros(self.nsat_n, dtype=int)
172
+ self.lc[inet].dclk_p = {}
173
+ self.lc[inet].iodc_c_p = {}
172
174
 
173
175
  self.iodssr = head['iodssr']
174
176
 
175
177
  self.lc[0].cstat |= (1 << sCType.MASK)
176
- self.lc[0].t0[sCType.MASK] = self.time
178
+ # self.lc[0].t0[0][sCType.MASK] = self.time
177
179
  return i
178
180
 
179
181
  def decode_cssr_orb_sat(self, msg, i, inet, sat_n):
180
- slot, iodn, iodc, dx, dy, dz, ucls, uval = \
181
- bs.unpack_from('u9u10u3s15s13s13u3u3', msg, i)
182
- i += 69
182
+ slot, iodn, iodc = bs.unpack_from('u9u10u3', msg, i)
183
+ i += 22
184
+
185
+ dx, dy, dz = bs.unpack_from('s{:d}s{:d}s{:d}'.format(
186
+ self.dorb_blen[0], self.dorb_blen[1], self.dorb_blen[2]), msg, i)
187
+ i += self.dorb_blen[0] + self.dorb_blen[1] + self.dorb_blen[2]
188
+
189
+ ucls, uval = bs.unpack_from('u3u3', msg, i)
190
+ i += 6
191
+
183
192
  sys, prn = self.slot2prn(slot)
184
193
  if sys == uGNSS.NONE:
185
194
  return i
186
195
  sat = prn2sat(sys, prn)
187
196
  if sat not in sat_n:
188
197
  return i
189
- idx = np.where(sat == sat_n)[0][0]
190
198
 
191
199
  if (sys == uGNSS.GPS) or (sys == uGNSS.BDS):
192
200
  iodn = iodn & 0xff # IODC -> IODE
193
201
 
194
- self.lc[inet].iode[idx] = iodn
195
- self.lc[inet].iodc[idx] = iodc
196
- self.lc[inet].dorb[idx, 0] = self.sval(dx, 15, self.dorb_scl[0])
197
- self.lc[inet].dorb[idx, 1] = self.sval(dy, 13, self.dorb_scl[1])
198
- self.lc[inet].dorb[idx, 2] = self.sval(dz, 13, self.dorb_scl[2])
199
- self.ura[idx] = self.quality_idx(ucls, uval)
202
+ dorb = np.zeros(3)
203
+ dorb[0] = self.sval(dx, self.dorb_blen[0], self.dorb_scl[0])
204
+ dorb[1] = self.sval(dy, self.dorb_blen[1], self.dorb_scl[1])
205
+ dorb[2] = self.sval(dz, self.dorb_blen[2], self.dorb_scl[2])
206
+
207
+ self.lc[inet].iode[sat] = iodn
208
+ self.lc[inet].iodc[sat] = iodc
209
+ self.lc[inet].dorb[sat] = dorb
210
+ self.ura[sat] = self.quality_idx(ucls, uval)
211
+
212
+ if sat not in self.lc[inet].t0:
213
+ self.lc[inet].t0[sat] = {}
214
+
215
+ self.lc[inet].t0[sat][sCType.ORBIT] = self.time
200
216
  return i
201
217
 
202
218
  def decode_cssr_orb(self, msg, i, inet=0):
@@ -212,8 +228,8 @@ class cssr_bds(cssr):
212
228
 
213
229
  self.iodssr_c[sCType.ORBIT] = head['iodssr']
214
230
  self.lc[inet].cstat |= (1 << sCType.ORBIT)
215
- self.lc[inet].t0[sCType.ORBIT] = self.time
216
- i += 19
231
+
232
+ i += 19 # reserve
217
233
  return i
218
234
 
219
235
  def decode_cssr_cbias(self, msg, i, inet=0):
@@ -233,30 +249,39 @@ class cssr_bds(cssr):
233
249
  i += 13
234
250
  sys, prn = self.slot2prn(slot)
235
251
  sat = prn2sat(sys, prn)
236
- idx = np.where(sat == sat_n)[0]
237
- if len(idx) == 0:
252
+ if sat not in sat_n:
238
253
  continue
254
+ if sat not in self.lc[inet].t0:
255
+ self.lc[inet].t0[sat] = {}
256
+ self.lc[inet].t0[sat][sCType.CBIAS] = self.time
257
+
258
+ self.lc[inet].cbias[sat] = {}
239
259
  for j in range(0, nsig):
240
- sig, cb = bs.unpack_from('u4s12', msg, i)
241
- i += 16
242
- self.sig_n[idx, j] = sig
243
- self.lc[inet].cbias[idx, j] = self.sval(cb, 12, self.cb_scl)
260
+ sig, cb = bs.unpack_from(
261
+ 'u4s{:d}'.format(self.cb_blen), msg, i)
262
+ i += 4+self.cb_blen
263
+ sig_ = self.ssig2rsig(sys, uTYP.C, sig)
264
+ self.lc[inet].cbias[sat][sig_] = self.sval(
265
+ cb, self.cb_blen, self.cb_scl)
244
266
 
245
267
  self.iodssr_c[sCType.CBIAS] = head['iodssr']
246
268
  self.lc[inet].cstat |= (1 << sCType.CBIAS)
247
- self.lc[inet].t0[sCType.CBIAS] = self.time
269
+
248
270
  return i
249
271
 
250
- def decode_cssr_clk_sat(self, msg, i, inet, idx):
272
+ def decode_cssr_clk_sat(self, msg, i, inet, sat):
251
273
  """ decode clock correction for satellite """
252
- iodc, dclk = bs.unpack_from('u3s15', msg, i)
253
- i += 18
254
- if iodc != self.lc[inet].iodc_c[idx]:
255
- self.lc[inet].iodc_c_p[idx] = self.lc[inet].iodc_c[idx]
256
- self.lc[inet].dclk_p[idx] = self.lc[inet].dclk[idx]
257
- self.lc[inet].iodc_c[idx] = iodc
274
+ iodc, dclk = bs.unpack_from('u3s{:d}'.format(self.dclk_blen), msg, i)
275
+ i += 3+self.dclk_blen
276
+
277
+ if sat in self.lc[inet].iodc_c.keys() and \
278
+ iodc != self.lc[inet].iodc_c[sat]:
279
+ self.lc[inet].iodc_c_p[sat] = self.lc[inet].iodc_c[sat]
280
+ self.lc[inet].dclk_p[sat] = self.lc[inet].dclk[sat]
281
+ self.lc[inet].iodc_c[sat] = iodc
258
282
  # note: the sign of the clock correction reversed
259
- self.lc[inet].dclk[idx] = -self.sval(dclk, 15, self.dclk_scl)
283
+ self.lc[inet].dclk[sat] = - \
284
+ self.sval(dclk, self.dclk_blen, self.dclk_scl)
260
285
  return i
261
286
 
262
287
  def decode_cssr_clk(self, msg, i, inet=0):
@@ -273,11 +298,15 @@ class cssr_bds(cssr):
273
298
  for k in range(23):
274
299
  idx = st1*23+k
275
300
  if idx < self.nsat_n:
276
- i = self.decode_cssr_clk_sat(msg, i, inet, idx)
301
+ sat = self.sat_n[idx]
302
+ i = self.decode_cssr_clk_sat(msg, i, inet, sat)
303
+ if sat not in self.lc[inet].t0:
304
+ self.lc[inet].t0[sat] = {}
305
+ self.lc[inet].t0[sat][sCType.CLOCK] = self.time
277
306
 
278
307
  self.iodssr_c[sCType.CLOCK] = head['iodssr']
279
308
  self.lc[inet].cstat |= (1 << sCType.CLOCK)
280
- self.lc[inet].t0[sCType.CLOCK] = self.time
309
+
281
310
  i += 10
282
311
  return i
283
312
 
@@ -295,10 +324,11 @@ class cssr_bds(cssr):
295
324
  i += 6
296
325
  idx = st2*70+k
297
326
  if idx < self.nsat_n:
298
- self.ura[idx] = self.quality_idx(v['class'], v['val'])
327
+ sat = self.sat_n[idx]
328
+ self.ura[sat] = self.quality_idx(v['class'], v['val'])
299
329
 
300
330
  self.lc[0].cstat |= (1 << sCType.URA)
301
- self.lc[0].t0[sCType.URA] = self.time
331
+ # self.lc[0].t0[0][sCType.URA] = self.time
302
332
  return i
303
333
 
304
334
  def decode_cssr_comb1(self, msg, i, inet=0):
@@ -312,7 +342,8 @@ class cssr_bds(cssr):
312
342
  i += 36
313
343
  for k in range(numc):
314
344
  idx = slot_s+k
315
- i = self.decode_cssr_clk_sat(msg, i, inet, idx)
345
+ sat = self.sat_n[idx]
346
+ i = self.decode_cssr_clk_sat(msg, i, inet, sat)
316
347
 
317
348
  if numo > 0:
318
349
  tod, _, iodssr = bs.unpack_from('u17u4u2', msg, i)
@@ -335,8 +366,7 @@ class cssr_bds(cssr):
335
366
  i += 9
336
367
  sys, prn = self.slot2prn(slot)
337
368
  sat = prn2sat(sys, prn)
338
- idx = np.where(sat == sat_n)[0]
339
- i = self.decode_cssr_clk_sat(msg, i, inet, idx)
369
+ i = self.decode_cssr_clk_sat(msg, i, inet, sat)
340
370
 
341
371
  if numo > 0:
342
372
  tod, _, iodssr = bs.unpack_from('u17u4u2', msg, i)
@@ -75,13 +75,20 @@ class cssr_has(cssr):
75
75
  return head, i
76
76
 
77
77
  def decode_cssr(self, msg, i=0):
78
- if self.msgtype != 1: # only MT=1 defined
78
+ # Galileo HAS-SIS only defines MT=1, MT=4073 is CSSR message used in the
79
+ # Galileo HAS test dataset
80
+ #
81
+ if self.msgtype != 1 and self.msgtype != 4073:
79
82
  print(f"invalid MT={self.msgtype}")
80
83
  return False
81
84
  # time of hour
82
85
  # flags: mask,orbit,clock,clock subset,cbias,pbias,mask_id,iodset_id
83
- self.toh, flags, res, mask_id, self.iodssr = \
84
- bs.unpack_from('u12u6u4u5u5', msg, i)
86
+ try:
87
+ self.toh, flags, res, mask_id, self.iodssr = \
88
+ bs.unpack_from('u12u6u4u5u5', msg, i)
89
+ except:
90
+ print(f"invalid content={self.msgtype}")
91
+ return False
85
92
  i += 32
86
93
 
87
94
  if self.monlevel > 0 and self.fh is not None:
@@ -0,0 +1,176 @@
1
+ """
2
+ PVS (PPP via SouthPAN) correction data decoder
3
+
4
+ [1] Service Definition Document for Open Services, SBAS-STN-0001,
5
+ Revision 02, December 2022
6
+
7
+ [2] Service Definition Document for Data Access Services, SBAS-STN-0002,
8
+ Revision 01, November 2023
9
+
10
+ """
11
+
12
+ import numpy as np
13
+ import bitstruct as bs
14
+ from cssrlib.cssrlib import cssr, sCSSR, sCSSRTYPE, prn2sat, sCType
15
+ from cssrlib.cssrlib import sat2id
16
+ from cssrlib.gnss import uGNSS, rCST, gpst2time, timediff, timeadd, time2gpst
17
+ from binascii import unhexlify
18
+
19
+
20
+ def decode_sinca_line(line):
21
+ """ SINCA (SISNeT compression algorithm) decoder """
22
+ if line[0:4] != '*MSG':
23
+ return None
24
+ v = line.split(',')
25
+ s = v[3]
26
+ week, tow = int(v[1]), int(v[2])
27
+ t = gpst2time(week, tow)
28
+ for key in '|/':
29
+ if key in s:
30
+ while True:
31
+ pos = s.find(key)
32
+ if pos < 0:
33
+ break
34
+ c = s[pos-1]
35
+ k = 2 if key == '|' else 3
36
+ n = int(s[pos+1:pos+k], 16)
37
+ s = s.replace(s[pos-1:pos+k], c*n, 1)
38
+
39
+ sb = unhexlify(s.split('*')[0])
40
+ return t, sb
41
+
42
+
43
+ class cssr_pvs(cssr):
44
+ def __init__(self, foutname=None):
45
+ super().__init__(foutname)
46
+ self.MAXNET = 1
47
+ self.cssrmode = sCSSRTYPE.PVS_PPP
48
+ self.nsig_max = 0
49
+ self.sat_n = []
50
+
51
+ self.lc[0].dclk = {}
52
+ self.lc[0].ddft = {}
53
+ self.lc[0].dorb = {}
54
+ self.lc[0].dvel = {}
55
+ self.lc[0].iode = {}
56
+ self.lc[0].t0 = {}
57
+
58
+ self.tmax = {sCType.CLOCK: 120.0, sCType.ORBIT: 120.0}
59
+
60
+ # GPS LNAV, Galileo F/NAV
61
+ self.nav_mode = {uGNSS.GPS: 0, uGNSS.GAL: 1}
62
+
63
+ def slot2sat(self, slot):
64
+ sat = 0
65
+ if slot >= 1 and slot <= 32:
66
+ prn = slot
67
+ sat = prn2sat(uGNSS.GPS, prn)
68
+ elif slot >= 38 and slot <= 69:
69
+ prn = slot-37
70
+ sat = prn2sat(uGNSS.GLO, prn)
71
+ elif slot >= 75 and slot <= 110:
72
+ prn = slot-74
73
+ sat = prn2sat(uGNSS.GAL, prn)
74
+ elif slot >= 120 and slot <= 158:
75
+ prn = slot
76
+ sat = prn2sat(uGNSS.SBS, prn)
77
+ elif slot >= 159 and slot <= 195:
78
+ prn = slot-158
79
+ sat = prn2sat(uGNSS.BDS, prn)
80
+ return sat
81
+
82
+ def adjust_time_week(self, time, time0):
83
+ dt = timediff(time, time0)
84
+ if dt > rCST.HALFWEEK_SEC:
85
+ time = timeadd(time, -rCST.WEEK_SEC)
86
+ elif dt < -rCST.HALFWEEK_SEC:
87
+ time = timeadd(time, rCST.WEEK_SEC)
88
+ return time
89
+
90
+ def check_validity(self, time):
91
+ for sat in self.sat_n:
92
+ if timediff(time, self.lc[0].t0[sat][sCType.CLOCK]) > \
93
+ self.tmax[sCType.CLOCK]:
94
+ self.lc[0].dclk[sat] = 0.0
95
+ if timediff(time, self.lc[0].t0[sat][sCType.ORBIT]) > \
96
+ self.tmax[sCType.ORBIT]:
97
+ self.lc[0].iode[sat] = -1
98
+ self.lc[0].dorb[sat] = np.zeros(3)
99
+
100
+ def decode_cssr_orb(self, msg, i, inet=0):
101
+ """ Types 32 clock-ephemeris correction and covariance matrix """
102
+ slot, iodn = bs.unpack_from('u8u10', msg, i)
103
+ i += 18
104
+ dx, dy, dz, db = bs.unpack_from('s11s11s11s12', msg, i)
105
+ i += 45
106
+ dxd, dyd, dzd, dbd, t0 = bs.unpack_from('s8s8s8s9u13', msg, i)
107
+ i += 46
108
+
109
+ # i, C = self.decode_cov(msg, i)
110
+ i += 99
111
+ # dfrei, dRcorr = bs.unpack_from('u4u4', msg, i)
112
+ i += 8
113
+
114
+ sat = self.slot2sat(slot)
115
+
116
+ if sat == 0 or t0 % 2 == 0: # for DFMC SBAS only
117
+ return
118
+
119
+ if sat not in self.sat_n:
120
+ self.sat_n.append(sat)
121
+
122
+ dorb = np.zeros(3)
123
+ dvel = np.zeros(3)
124
+
125
+ dorb[0] = dx*0.0625
126
+ dorb[1] = dy*0.0625
127
+ dorb[2] = dz*0.0625
128
+
129
+ dclk = db*0.03125
130
+
131
+ dvel[0] = dxd*0.00048828
132
+ dvel[1] = dyd*0.00048828
133
+ dvel[2] = dzd*0.00048828
134
+
135
+ ddft = dbd*0.00024414
136
+
137
+ tow = self.tow0 + t0*16.0
138
+ self.time = self.adjust_time_week(
139
+ gpst2time(self.week, tow), self.time0)
140
+
141
+ self.lc[0].iode[sat] = iodn
142
+ self.lc[0].dorb[sat] = -dorb
143
+ self.lc[0].dclk[sat] = dclk
144
+ self.lc[0].dvel[sat] = -dvel
145
+ self.lc[0].ddft[sat] = ddft
146
+
147
+ self.iodssr = 0
148
+ self.lc[0].cstat |= (1 << sCType.CLOCK) | (1 << sCType.ORBIT)
149
+ self.lc[0].t0[sat] = {
150
+ sCType.CLOCK: self.time0, sCType.ORBIT: self.time0}
151
+
152
+ self.iodssr_c[sCType.CLOCK] = self.iodssr
153
+ self.iodssr_c[sCType.ORBIT] = self.iodssr
154
+
155
+ if self.monlevel > 0:
156
+ self.fh.write("{:.1f} {:3s} {:3d}\n"
157
+ .format(tow, sat2id(sat), iodn))
158
+
159
+ return i
160
+
161
+ def decode_cssr(self, msg, i=0):
162
+
163
+ _, mt = bs.unpack_from('u4u6', msg, i)
164
+ i += 10
165
+
166
+ if mt == 32:
167
+ self.subtype = sCSSR.ORBIT
168
+ i = self.decode_cssr_orb(msg, i)
169
+
170
+ if self.monlevel > 3:
171
+ if self.time != -1:
172
+ _, tow = time2gpst(self.time)
173
+ else:
174
+ tow = -1
175
+ self.fh.write("mt={:2d} tow={:6.1f}\n"
176
+ .format(mt, tow))