cssrlib 1.0.0__tar.gz → 1.1.0__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 (44) hide show
  1. {cssrlib-1.0.0/src/cssrlib.egg-info → cssrlib-1.1.0}/PKG-INFO +3 -10
  2. {cssrlib-1.0.0 → cssrlib-1.1.0}/README.md +2 -9
  3. {cssrlib-1.0.0 → cssrlib-1.1.0}/setup.cfg +1 -1
  4. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/cssr_bds.py +25 -13
  5. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/cssr_has.py +10 -3
  6. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/cssrlib.py +33 -20
  7. cssrlib-1.1.0/src/cssrlib/dgps.py +289 -0
  8. cssrlib-1.1.0/src/cssrlib/ephemeris.py +894 -0
  9. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/gnss.py +100 -41
  10. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/peph.py +28 -15
  11. cssrlib-1.1.0/src/cssrlib/pntpos.py +546 -0
  12. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/pppssr.py +43 -14
  13. cssrlib-1.1.0/src/cssrlib/rawnav.py +1662 -0
  14. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/rinex.py +168 -49
  15. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/rtcm.py +110 -79
  16. cssrlib-1.1.0/src/cssrlib/sbas.py +1073 -0
  17. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/test/test_peph.py +14 -15
  18. {cssrlib-1.0.0 → cssrlib-1.1.0/src/cssrlib.egg-info}/PKG-INFO +3 -10
  19. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib.egg-info/SOURCES.txt +2 -0
  20. cssrlib-1.0.0/src/cssrlib/ephemeris.py +0 -435
  21. cssrlib-1.0.0/src/cssrlib/pntpos.py +0 -125
  22. cssrlib-1.0.0/src/cssrlib/rawnav.py +0 -522
  23. {cssrlib-1.0.0 → cssrlib-1.1.0}/LICENSE +0 -0
  24. {cssrlib-1.0.0 → cssrlib-1.1.0}/MANIFEST.in +0 -0
  25. {cssrlib-1.0.0 → cssrlib-1.1.0}/pyproject.toml +0 -0
  26. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/__init__.py +0 -0
  27. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/cssr_pvs.py +0 -0
  28. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/data/30340780.21q +0 -0
  29. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/data/3034078M1.21O +0 -0
  30. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/data/SEPT078M.21P +0 -0
  31. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/data/SEPT078M1.21O +0 -0
  32. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/mlambda.py +0 -0
  33. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/plot.py +0 -0
  34. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/ppp.py +0 -0
  35. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/ppprtk.py +0 -0
  36. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/rtk.py +0 -0
  37. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/test/test_eph.py +0 -0
  38. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/test/test_gnss.py +0 -0
  39. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/test/test_rnx.py +0 -0
  40. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/test/test_rtk.py +0 -0
  41. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib/tlesim.py +0 -0
  42. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib.egg-info/dependency_links.txt +0 -0
  43. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib.egg-info/not-zip-safe +0 -0
  44. {cssrlib-1.0.0 → cssrlib-1.1.0}/src/cssrlib.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cssrlib
3
- Version: 1.0.0
3
+ Version: 1.1.0
4
4
  Summary: Python Toolkit for PPP/PPP-RTK positioning
5
5
  Home-page: https://github.com/hirokawa/cssrlib
6
6
  Author: Rui Hirokawa
@@ -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 pysolid
45
- pip install notebook numpy matplotlib
46
- ```
47
-
48
- Optionally, on linux, users can install the `cartopy` package and the `PySolid` package
49
-
50
- ```
51
- pip install cartopy pysolid
44
+ pip install -r requirements.txt
52
45
  ```
53
46
 
54
47
  If the installation of `cartopy` fails, try installing `libgeos++-dev` first.
@@ -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 pysolid
30
- pip install notebook numpy matplotlib
31
- ```
32
-
33
- Optionally, on linux, users can install the `cartopy` package and the `PySolid` package
34
-
35
- ```
36
- pip install cartopy pysolid
29
+ pip install -r requirements.txt
37
30
  ```
38
31
 
39
32
  If the installation of `cartopy` fails, try installing `libgeos++-dev` first.
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = cssrlib
3
- version = 1.0.0
3
+ version = 1.1.0
4
4
  author = Rui Hirokawa
5
5
  author_email = rui.hirokawa@gmail.com
6
6
  description = Python Toolkit for PPP/PPP-RTK positioning
@@ -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 = {
@@ -177,9 +179,16 @@ class cssr_bds(cssr):
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
@@ -191,9 +200,9 @@ class cssr_bds(cssr):
191
200
  iodn = iodn & 0xff # IODC -> IODE
192
201
 
193
202
  dorb = np.zeros(3)
194
- dorb[0] = self.sval(dx, 15, self.dorb_scl[0])
195
- dorb[1] = self.sval(dy, 13, self.dorb_scl[1])
196
- dorb[2] = self.sval(dz, 13, self.dorb_scl[2])
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])
197
206
 
198
207
  self.lc[inet].iode[sat] = iodn
199
208
  self.lc[inet].iodc[sat] = iodc
@@ -220,7 +229,7 @@ class cssr_bds(cssr):
220
229
  self.iodssr_c[sCType.ORBIT] = head['iodssr']
221
230
  self.lc[inet].cstat |= (1 << sCType.ORBIT)
222
231
 
223
- i += 19
232
+ i += 19 # reserve
224
233
  return i
225
234
 
226
235
  def decode_cssr_cbias(self, msg, i, inet=0):
@@ -248,10 +257,12 @@ class cssr_bds(cssr):
248
257
 
249
258
  self.lc[inet].cbias[sat] = {}
250
259
  for j in range(0, nsig):
251
- sig, cb = bs.unpack_from('u4s12', msg, i)
252
- i += 16
260
+ sig, cb = bs.unpack_from(
261
+ 'u4s{:d}'.format(self.cb_blen), msg, i)
262
+ i += 4+self.cb_blen
253
263
  sig_ = self.ssig2rsig(sys, uTYP.C, sig)
254
- self.lc[inet].cbias[sat][sig_] = self.sval(cb, 12, self.cb_scl)
264
+ self.lc[inet].cbias[sat][sig_] = self.sval(
265
+ cb, self.cb_blen, self.cb_scl)
255
266
 
256
267
  self.iodssr_c[sCType.CBIAS] = head['iodssr']
257
268
  self.lc[inet].cstat |= (1 << sCType.CBIAS)
@@ -260,8 +271,8 @@ class cssr_bds(cssr):
260
271
 
261
272
  def decode_cssr_clk_sat(self, msg, i, inet, sat):
262
273
  """ decode clock correction for satellite """
263
- iodc, dclk = bs.unpack_from('u3s15', msg, i)
264
- i += 18
274
+ iodc, dclk = bs.unpack_from('u3s{:d}'.format(self.dclk_blen), msg, i)
275
+ i += 3+self.dclk_blen
265
276
 
266
277
  if sat in self.lc[inet].iodc_c.keys() and \
267
278
  iodc != self.lc[inet].iodc_c[sat]:
@@ -269,7 +280,8 @@ class cssr_bds(cssr):
269
280
  self.lc[inet].dclk_p[sat] = self.lc[inet].dclk[sat]
270
281
  self.lc[inet].iodc_c[sat] = iodc
271
282
  # note: the sign of the clock correction reversed
272
- self.lc[inet].dclk[sat] = -self.sval(dclk, 15, self.dclk_scl)
283
+ self.lc[inet].dclk[sat] = - \
284
+ self.sval(dclk, self.dclk_blen, self.dclk_scl)
273
285
  return i
274
286
 
275
287
  def decode_cssr_clk(self, msg, i, inet=0):
@@ -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:
@@ -18,6 +18,10 @@ class sCSSRTYPE(IntEnum):
18
18
  IGS_SSR = 5
19
19
  RTCM3_SSR = 6
20
20
  PVS_PPP = 7 # PPP via SouthPAN
21
+ SBAS_L1 = 8 # L1 SBAS
22
+ SBAS_L5 = 9 # L5 SBAS (DFMC)
23
+ DGPS = 10 # DGPS (QZSS SLAS)
24
+ STDPOS = 11
21
25
 
22
26
 
23
27
  class sGNSS(IntEnum):
@@ -61,7 +65,7 @@ class sCType(IntEnum):
61
65
  TROP = 6
62
66
  URA = 7
63
67
  AUTH = 8
64
- HCLOCK = 8
68
+ HCLOCK = 9
65
69
  VTEC = 10
66
70
  MAX = 11
67
71
 
@@ -206,11 +210,12 @@ class local_corr:
206
210
  self.inet = -1
207
211
  self.inet_ref = -1
208
212
  self.ng = -1
209
- self.pbias = None
210
- self.cbias = None
213
+ self.pbias = {}
214
+ self.cbias = {}
211
215
  self.iode = None
212
216
  self.dorb = None
213
217
  self.dclk = None
218
+ self.hclk = None
214
219
  self.stec = None
215
220
  self.trph = None
216
221
  self.trpw = None
@@ -218,10 +223,14 @@ class local_corr:
218
223
  self.ct = None
219
224
  self.quality_trp = None
220
225
  self.quality_stec = None
221
- self.t0 = []
222
- for _ in range(sCType.MAX):
223
- self.t0.append(gtime_t())
226
+ self.sat_n = []
227
+ self.t0 = {}
224
228
  self.cstat = 0 # status for receiving CSSR message
229
+ self.t0s = {}
230
+ sc_t = [sCType.CLOCK, sCType.ORBIT, sCType.CBIAS, sCType.PBIAS,
231
+ sCType.HCLOCK]
232
+ for sc in sc_t:
233
+ self.t0s[sc] = gtime_t()
225
234
 
226
235
 
227
236
  class cssr:
@@ -272,7 +281,7 @@ class cssr:
272
281
  self.lc = []
273
282
  self.fcnt = -1
274
283
  self.flg_net = False
275
- self.time = -1
284
+ self.time = gtime_t()
276
285
  self.nsig_max = 0
277
286
  self.ngrid = 0
278
287
  self.grid_index = []
@@ -440,9 +449,15 @@ class cssr:
440
449
  return False
441
450
 
442
451
  def set_t0(self, inet=0, sat=0, ctype=0, t=gtime_t()):
443
- """ set reference time for correcion to check validity time """
452
+ """ set reference time for correction to check validity time """
453
+ sc_t = [sCType.CLOCK, sCType.ORBIT, sCType.CBIAS, sCType.PBIAS,
454
+ sCType.HCLOCK]
455
+
444
456
  if sat not in self.lc[inet].t0:
445
457
  self.lc[inet].t0[sat] = {}
458
+ for sc in sc_t:
459
+ self.lc[inet].t0[sat][sc] = gtime_t()
460
+
446
461
  self.lc[inet].t0[sat][ctype] = t
447
462
 
448
463
  def quality_idx(self, cl, val):
@@ -682,7 +697,6 @@ class cssr:
682
697
  self.lc[inet].cbias = {}
683
698
  for k in range(nsat):
684
699
  sat = self.sat_n[k]
685
- sys, _ = sat2prn(sat)
686
700
  self.lc[inet].cbias[sat] = {}
687
701
  for j in range(len(self.sig_n[sat])):
688
702
  rsig = self.sig_n[sat][j].toTyp(uTYP.C)
@@ -703,7 +717,6 @@ class cssr:
703
717
  self.lc[inet].di = {}
704
718
  for k in range(nsat):
705
719
  sat = self.sat_n[k]
706
- sys, _ = sat2prn(sat)
707
720
  self.lc[inet].pbias[sat] = {}
708
721
  self.lc[inet].di[sat] = {}
709
722
  for j in range(len(self.sig_n[sat])):
@@ -904,8 +917,8 @@ class cssr:
904
917
  def decode_cssr_comb(self, msg, i, inet=0):
905
918
  """decode MT4073,11 Orbit,Clock Combined Correction message """
906
919
  head, i = self.decode_head(msg, i)
907
- # if self.iodssr != head['iodssr']:
908
- # return -1
920
+ if self.iodssr != head['iodssr']:
921
+ return -1
909
922
  dfm = bs.unpack_from_dict('b1b1b1', ['orb', 'clk', 'net'], msg, i)
910
923
  i += 3
911
924
  self.flg_net = dfm['net']
@@ -1122,7 +1135,7 @@ class cssr:
1122
1135
 
1123
1136
  if self.subtype == sCSSR.CLOCK:
1124
1137
  self.fh.write(" {:s}\t{:s}\n".format("SatID", "dclk [m]"))
1125
- for k, sat_ in enumerate(self.lc[0].dclk.keys()):
1138
+ for sat_ in self.lc[0].dclk.keys():
1126
1139
  if np.isnan(self.lc[0].dclk[sat_]):
1127
1140
  continue
1128
1141
  self.fh.write(" {:s}\t{:8.4f}\n"
@@ -1133,7 +1146,7 @@ class cssr:
1133
1146
  self.fh.write(" {:s}\t{:s}\t{:s}\t{:s}\t{:s}\n"
1134
1147
  .format("SatID", "IODE", "Radial[m]",
1135
1148
  "Along[m]", "Cross[m]"))
1136
- for k, sat_ in enumerate(self.lc[0].dorb.keys()):
1149
+ for sat_ in self.lc[0].dorb.keys():
1137
1150
  if np.isnan(self.lc[0].dorb[sat_][0]):
1138
1151
  continue
1139
1152
  self.fh.write(" {:s}\t{:3d}\t{:6.3f}\t{:6.3f}\t{:6.3f}\n"
@@ -1147,12 +1160,12 @@ class cssr:
1147
1160
  self.fh.write(" {:s}\t{:s}\t{:s}\t{:s}\t{:s}\t{:s}\n"
1148
1161
  .format("SatID", "IODE", "Radial[m]",
1149
1162
  "Along[m]", "Cross[m]", "dclk[m]"))
1150
- for k, sat_ in enumerate(self.lc[0].dorb.keys()):
1163
+ for sat_ in self.lc[0].dorb.keys():
1151
1164
  if np.isnan(self.lc[0].dorb[sat_][0]) or \
1152
1165
  np.isnan(self.lc[0].dclk[sat_]):
1153
1166
  continue
1154
1167
  self.fh.write(
1155
- " {:s}\t{:3d}\t{:6.3f}\t{:6.3f}\t{:6.3f}\t{:6.3f}\n"
1168
+ " {:s}\t{:3d}\t{:6.3f}\t{:6.3f}\t{:6.3f}\t{:8.4f}\n"
1156
1169
  .format(sat2id(sat_),
1157
1170
  self.lc[0].iode[sat_],
1158
1171
  self.lc[0].dorb[sat_][0],
@@ -1163,9 +1176,9 @@ class cssr:
1163
1176
  elif self.subtype == sCSSR.CBIAS:
1164
1177
  self.fh.write(" {:s}\t{:s}\t{:s}\t{:s}\n"
1165
1178
  .format("SatID", "SigID", "Code Bias[m]", "..."))
1166
- for k, sat_ in enumerate(self.lc[0].cbias.keys()):
1179
+ for sat_ in self.lc[0].cbias.keys():
1167
1180
  self.fh.write(" {:s}\t".format(sat2id(sat_)))
1168
- for sig_ in range(self.lc[0].cbias[sat_].keys()):
1181
+ for sig_ in self.lc[0].cbias[sat_].keys():
1169
1182
  self.fh.write("{:s}\t{:5.2f}\t"
1170
1183
  .format(sig_.str(),
1171
1184
  self.lc[0].cbias[sat_][sig_]))
@@ -1174,9 +1187,9 @@ class cssr:
1174
1187
  elif self.subtype == sCSSR.PBIAS:
1175
1188
  self.fh.write(" {:s}\t{:s}\t{:s}\t{:s}\n"
1176
1189
  .format("SatID", "SigID", "Phase Bias[m]", "..."))
1177
- for k, sat_ in enumerate(self.lc[0].pbias.keys()):
1190
+ for sat_ in self.lc[0].pbias.keys():
1178
1191
  self.fh.write(" {:s}\t".format(sat2id(sat_)))
1179
- for sig_ in range(self.lc[0].pbias[sat_].keys()):
1192
+ for sig_ in self.lc[0].pbias[sat_].keys():
1180
1193
  self.fh.write("{:s}\t{:5.2f}\t"
1181
1194
  .format(sig_.str(),
1182
1195
  self.lc[0].pbias[sat_][sig_]))
@@ -0,0 +1,289 @@
1
+ """
2
+ DGPS (QZSS SLAS) correction data decoder
3
+
4
+ [1] Quasi-Zenith Satellite System Interface Specification
5
+ Sub-meter Level Augmentation Service (IS-QZSS-L1S-006), 2023
6
+
7
+ """
8
+
9
+ import numpy as np
10
+ import bitstruct as bs
11
+ from cssrlib.cssrlib import cssr, sCSSRTYPE, prn2sat, sCType
12
+ from cssrlib.gnss import uGNSS, rCST, timediff, time2str, \
13
+ ecef2pos
14
+
15
+
16
+ def vardgps(el, nav):
17
+ """ measurement error varianvce for DGPS [1] """
18
+ c_el = np.cos(el)
19
+ pos = ecef2pos(nav.x[0:3])
20
+ Fpp = 1/np.sqrt(1-(rCST.RE_WGS84*c_el/(rCST.RE_WGS84+pos[2]))**2)
21
+ s_iono = Fpp*0.004*(nav.baseline+2*100*0.07)
22
+ s_mp = 0.13+0.53*np.exp(-el/0.1745)
23
+ v_air = 0.11**2 + s_mp**2
24
+ v_pr = (0.16+0.107*np.exp(-el/0.271))**2/1+0.08**2
25
+ v_sig = v_pr + v_air + s_iono**2
26
+ return v_sig
27
+
28
+
29
+ class dgpsDec(cssr):
30
+ MAX_ST = 64
31
+ MAX_SAT = 23
32
+
33
+ def __init__(self, foutname=None):
34
+ super().__init__(foutname)
35
+ self.MAXNET = 1
36
+ self.cssrmode = sCSSRTYPE.DGPS
37
+ self.nsig_max = 0
38
+ self.sat_n = []
39
+
40
+ self.sat = []
41
+
42
+ self.lc[0].dclk = {}
43
+ self.lc[0].ddft = {}
44
+ self.lc[0].dorb = {}
45
+ self.lc[0].dvel = {}
46
+ self.lc[0].iode = {}
47
+ self.lc[0].t0 = {}
48
+
49
+ self.tmax = {sCType.CLOCK: 120.0, sCType.ORBIT: 120.0}
50
+
51
+ # GPS/QZS LNAV, Galileo F/NAV
52
+ self.nav_mode = {uGNSS.GPS: 0, uGNSS.GAL: 1, uGNSS.QZS: 0,
53
+ uGNSS.GLO: 0, uGNSS.BDS: 0}
54
+
55
+ self.iodp = -1
56
+ self.iodi = -1
57
+ self.iodm = -1
58
+ self.iodg = -1
59
+
60
+ self.iodssr = -1
61
+ self.iodp_c = {}
62
+
63
+ self.baselen = 0 # baseline length [km]
64
+
65
+ self.posr = np.zeros((self.MAX_ST, 3))
66
+ self.posr[0, :] = [43.150, 141.220, 50]
67
+ self.posr[1, :] = [38.270, 140.740, 200]
68
+ self.posr[3, :] = [36.580, 140.550, 150]
69
+ self.posr[5, :] = [36.400, 136.410, 50]
70
+ self.posr[6, :] = [34.710, 135.040, 200]
71
+ self.posr[7, :] = [34.350, 132.450, 50]
72
+ self.posr[8, :] = [33.600, 130.230, 50]
73
+ self.posr[9, :] = [30.550, 130.940, 100]
74
+ self.posr[10, :] = [28.420, 129.690, 50]
75
+ self.posr[11, :] = [26.150, 127.690, 100]
76
+ self.posr[12, :] = [24.730, 125.350, 100]
77
+ self.posr[13, :] = [24.370, 124.130, 100]
78
+ self.posr[14, :] = [27.090, 142.190, 100]
79
+
80
+ self.mlen = {uGNSS.GPS: 64, uGNSS.QZS: 9, uGNSS.GLO: 36, uGNSS.GAL: 36,
81
+ uGNSS.BDS: 36}
82
+ self.prn_ofst = {uGNSS.GPS: 0, uGNSS.QZS: 192, uGNSS.GLO: 0,
83
+ uGNSS.GAL: 0, uGNSS.BDS: 0}
84
+
85
+ def sval(self, u, n, scl):
86
+ """ calculate signed value based on n-bit int, lsb """
87
+ invalid = 2**(n-1)-1
88
+ y = np.nan if u == invalid else u*scl
89
+ return y
90
+
91
+ def check_validity(self, time):
92
+ for sat in self.sat_n:
93
+ if timediff(time, self.lc[0].t0[sat][sCType.CLOCK]) > \
94
+ self.tmax[sCType.CLOCK]:
95
+ self.lc[0].dclk[sat] = 0.0
96
+ if timediff(time, self.lc[0].t0[sat][sCType.ORBIT]) > \
97
+ self.tmax[sCType.ORBIT]:
98
+ self.lc[0].iode[sat] = -1
99
+ self.lc[0].dorb[sat] = np.zeros(3)
100
+
101
+ def decode_mt43(self, msg, i):
102
+ """ decode DC report by JMA (TBD) """
103
+ # i = self.dcr.decode_jma(msg)
104
+ return i
105
+
106
+ def decode_mt44(self, msg, i):
107
+ """ decode DC report by other organization (TBD) """
108
+ # i = self.dcr.decode_ews(msg)
109
+ return i
110
+
111
+ def decode_mt47(self, msg, i):
112
+ """ decode location of reference station """
113
+ i = 14
114
+ for k in range(5):
115
+ code, lat, lon, alt = bs.unpack_from('u6s15s15u6', msg, i)
116
+ if code == 63:
117
+ continue
118
+ self.posr[code, 0] = lat*0.005
119
+ self.posr[code, 1] = lon*0.005+115
120
+ self.posr[code, 2] = alt*50.0-100
121
+
122
+ i += 42
123
+ return 0
124
+
125
+ def decode_mt48(self, msg, i):
126
+ """ decode satellite mask """
127
+ self.iodssr_p = self.iodp
128
+ self.sat_n_p = self.sat_n
129
+
130
+ i = 14
131
+ self.nsat = 0
132
+ v = bs.unpack_from('u2u64u9u36u36u36', msg, i)
133
+
134
+ self.sat_n = []
135
+ self.iodp = v[0]
136
+ sys_t = [uGNSS.GPS, uGNSS.QZS, uGNSS.GLO, uGNSS.GAL, uGNSS.BDS]
137
+ for k, sys in enumerate(sys_t):
138
+ prn, nsat_s = self.decode_mask(v[k+1], self.mlen[sys])
139
+ for j in range(nsat_s):
140
+ self.sat_n.append(prn2sat(sys, prn[j]+self.prn_ofst[sys]))
141
+ self.nsat += nsat_s
142
+
143
+ self.iodssr = self.iodp
144
+
145
+ self.lc[0].cstat |= (1 << sCType.MASK)
146
+ self.set_t0(ctype=sCType.MASK, t=self.time)
147
+
148
+ self.sat = self.sat_n
149
+
150
+ return i
151
+
152
+ def decode_mt49(self, msg, i):
153
+ """ decode issue of data """
154
+ iodp = bs.unpack_from('u2', msg, 223)[0]
155
+ if iodp != self.iodp:
156
+ return -1
157
+ i = 14
158
+ iodi, mask = bs.unpack_from('u2u23', msg, i)
159
+ i += 25
160
+
161
+ self.iodn = {}
162
+
163
+ self.iodi = iodi # issue of data
164
+ for k in range(23):
165
+ if (mask >> (23-k-1)) & 1 == 0 or k >= self.nsat:
166
+ continue
167
+ iodn = bs.unpack_from('u8', msg, i)[0]
168
+ i += 8
169
+
170
+ sat = self.sat[k]
171
+ self.iodn[sat] = iodn
172
+
173
+ return i
174
+
175
+ def decode_mt50(self, msg, i):
176
+ """ decode DGPS correction """
177
+ iodp, iodi, code, h, mask_s = bs.unpack_from('u2u2u6u1u23', msg, i)
178
+ i += 34
179
+ if iodp != self.iodp or iodi != self.iodi or h == 1:
180
+ return i
181
+
182
+ nsat = 0
183
+ inet = code+1
184
+
185
+ self.lc[inet].iode = {}
186
+ self.lc[inet].dclk = {}
187
+ self.lc[inet].dorb = {}
188
+ self.lc[inet].sat_n = []
189
+
190
+ for k in range(23):
191
+ if k >= self.nsat:
192
+ continue
193
+ sat = self.sat[k]
194
+ self.lc[inet].dorb[sat] = np.zeros(3)
195
+
196
+ if (mask_s >> (23-k-1)) & 1 == 0:
197
+ # self.lc[inet].iode[sat] = -1
198
+ # self.lc[inet].dclk[sat] = 0.0
199
+ continue
200
+
201
+ prc = bs.unpack_from('s12', msg, i)[0]*0.04
202
+ i += 12
203
+
204
+ self.lc[inet].sat_n.append(sat)
205
+ self.lc[inet].iode[sat] = self.iodn[sat]
206
+ self.lc[inet].dclk[sat] = prc
207
+
208
+ self.set_t0(ctype=sCType.CLOCK, sat=sat, inet=inet, t=self.time)
209
+ self.set_t0(ctype=sCType.ORBIT, sat=sat, inet=inet, t=self.time)
210
+
211
+ nsat += 1
212
+ if nsat > 14:
213
+ break
214
+
215
+ self.iodp_c[inet] = iodp
216
+
217
+ self.lc[0].cstat |= (1 << sCType.CLOCK)
218
+ self.lc[0].cstat |= (1 << sCType.ORBIT)
219
+
220
+ return i
221
+
222
+ def decode_mt51(self, msg, i):
223
+ """ decode satellite health """
224
+ v = bs.unpack_from('u64u9u36u36u36', msg, i)
225
+ i += 181
226
+ self.svh[uGNSS.GPS] = v[0]
227
+ self.svh[uGNSS.QZS] = v[1]
228
+ self.svh[uGNSS.GLO] = v[2]
229
+ self.svh[uGNSS.GAL] = v[3]
230
+ self.svh[uGNSS.BDS] = v[4]
231
+ return i
232
+
233
+ def decode_cssr(self, msg, i=0):
234
+ """ decode DGPS messages """
235
+
236
+ _, mt = bs.unpack_from('u8u6', msg, i)
237
+ i += 14
238
+
239
+ self.msgtype = mt
240
+
241
+ if mt == 43: # DC report (JMA)
242
+ i = self.decode_mt43(msg, i)
243
+ elif mt == 44: # DC report (other source)
244
+ i = self.decode_mt44(msg, i)
245
+ elif mt == 47: #
246
+ i = self.decode_mt47(msg, i)
247
+ elif mt == 48: #
248
+ i = self.decode_mt48(msg, i)
249
+ elif mt == 49: #
250
+ i = self.decode_mt49(msg, i)
251
+ elif mt == 50: #
252
+ i = self.decode_mt50(msg, i)
253
+ elif mt == 51: #
254
+ i = self.decode_mt51(msg, i)
255
+ elif mt == 63: # Null
256
+ None
257
+
258
+ if self.monlevel > 3:
259
+ self.fh.write("{:s} mt={:2d} \n".format(time2str(self.time), mt))
260
+
261
+ def get_station(self, r):
262
+ """ get the nearest referece station """
263
+ pos = ecef2pos(r)
264
+ c_lat = np.cos(pos[0])
265
+ idx = np.where(self.posr[:, 0]**2+self.posr[:, 1]**2 > 0)[0]
266
+ if len(idx) == 0:
267
+ return -1, -1
268
+ dpos = np.deg2rad(self.posr[idx, 0:2])-pos[0:2]
269
+ rng = np.sqrt(dpos[:, 0]**2+(dpos[:, 1]*c_lat)**2)*rCST.RE_WGS84
270
+ kmin = np.argmin(rng)
271
+ refid = idx[kmin]
272
+ return refid, rng[kmin]
273
+
274
+ def set_dgps_corr(self, rr):
275
+ """ get DGPS correction """
276
+ if self.iodp < 0 or self.iodi < 0:
277
+ return -1
278
+ refid, rmin = self.get_station(rr)
279
+ baselen = rmin*1e-3 # baseline length [km]
280
+ self.inet = refid+1
281
+ if len(self.lc[self.inet].sat_n) > 0:
282
+ self.sat_n = self.lc[self.inet].sat_n
283
+ self.iodssr_c[sCType.ORBIT] = self.iodp_c[self.inet]
284
+ self.iodssr_c[sCType.CLOCK] = self.iodp_c[self.inet]
285
+ self.lc[0].t0 = self.lc[self.inet].t0
286
+ self.lc[0].iode = self.lc[self.inet].iode
287
+ self.lc[0].dclk = self.lc[self.inet].dclk
288
+ self.lc[0].dorb = self.lc[self.inet].dorb
289
+ return baselen