cssrlib 1.0.1__tar.gz → 1.2.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.
- {cssrlib-1.0.1 → cssrlib-1.2.0}/PKG-INFO +33 -18
- cssrlib-1.0.1/src/cssrlib.egg-info/PKG-INFO → cssrlib-1.2.0/README.md +20 -26
- cssrlib-1.2.0/pyproject.toml +27 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/setup.cfg +1 -1
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/__init__.py +1 -1
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/cssr_has.py +80 -2
- cssrlib-1.2.0/src/cssrlib/cssr_mdc.py +262 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/cssr_pvs.py +23 -24
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/cssrlib.py +72 -31
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/dgps.py +13 -3
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/ephemeris.py +20 -4
- cssrlib-1.2.0/src/cssrlib/ewss.py +1496 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/gnss.py +101 -19
- cssrlib-1.2.0/src/cssrlib/mlambda.py +379 -0
- cssrlib-1.2.0/src/cssrlib/osnma.py +977 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/peph.py +36 -54
- cssrlib-1.2.0/src/cssrlib/plot.py +185 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/pntpos.py +7 -6
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/ppp.py +10 -3
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/ppprtk.py +1 -1
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/pppssr.py +96 -18
- cssrlib-1.2.0/src/cssrlib/qznma.py +885 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/rawnav.py +712 -150
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/rinex.py +467 -129
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/rtcm.py +1055 -33
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/sbas.py +45 -37
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/test/test_peph.py +15 -5
- cssrlib-1.0.1/README.md → cssrlib-1.2.0/src/cssrlib.egg-info/PKG-INFO +41 -11
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib.egg-info/SOURCES.txt +5 -0
- cssrlib-1.2.0/src/cssrlib.egg-info/requires.txt +9 -0
- cssrlib-1.0.1/pyproject.toml +0 -6
- cssrlib-1.0.1/src/cssrlib/mlambda.py +0 -205
- cssrlib-1.0.1/src/cssrlib/plot.py +0 -87
- {cssrlib-1.0.1 → cssrlib-1.2.0}/LICENSE +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/MANIFEST.in +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/cssr_bds.py +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/data/30340780.21q +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/data/3034078M1.21O +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/data/SEPT078M.21P +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/data/SEPT078M1.21O +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/rtk.py +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/test/test_eph.py +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/test/test_gnss.py +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/test/test_rnx.py +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/test/test_rtk.py +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib/tlesim.py +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib.egg-info/dependency_links.txt +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib.egg-info/not-zip-safe +0 -0
- {cssrlib-1.0.1 → cssrlib-1.2.0}/src/cssrlib.egg-info/top_level.txt +0 -0
|
@@ -1,25 +1,31 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: cssrlib
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.2.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
|
|
7
|
-
Author-email: rui.hirokawa@gmail.com
|
|
8
|
-
Project-URL: Bug Tracker, https://github.com/hirokawa/cssrlib/issues
|
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
-
Classifier: Operating System :: OS Independent
|
|
7
|
+
Author-email: Rui Hirokawa <rui.hirokawa@gmail.com>
|
|
12
8
|
Requires-Python: >=3.10
|
|
13
9
|
Description-Content-Type: text/markdown
|
|
14
10
|
License-File: LICENSE
|
|
11
|
+
Requires-Dist: scipy
|
|
12
|
+
Requires-Dist: bitstruct
|
|
13
|
+
Requires-Dist: galois
|
|
14
|
+
Requires-Dist: crccheck
|
|
15
|
+
Requires-Dist: notebook
|
|
16
|
+
Requires-Dist: numpy
|
|
17
|
+
Requires-Dist: matplotlib
|
|
18
|
+
Requires-Dist: cartopy
|
|
19
|
+
Requires-Dist: pysolid
|
|
20
|
+
Dynamic: license-file
|
|
15
21
|
|
|
16
|
-
*************************
|
|
17
22
|
CSSRlib - Toolkit for PPP-RTK/RTK in Python using Compact SSR
|
|
18
|
-
|
|
23
|
+
=============
|
|
19
24
|
|
|
20
|
-
|
|
25
|
+
What is CSSRlib?
|
|
26
|
+
----------------
|
|
21
27
|
|
|
22
|
-
|
|
28
|
+
CSSRlib is a open toolkit in Python for high accuracy GNSS positioning. It supports SSR (State-Space Representation) based positioning for PPP (Precise Point Positioning) or PPP-RTK (Realtime Kinematic), while also supporting RTK. The goal of the CSSRlib toolkit is to provide an easy-to-understand open implementation to learn PPP/PPP-RTK positioning provided by satellite-based open PPP/PPP-RTK services such as QZSS CLAS, Galileo HAS, and BeiDou 3 PPP. It also supports ground based open service by IGS. The code is based on RTKlib.
|
|
23
29
|
|
|
24
30
|
It supports the following open format:
|
|
25
31
|
|
|
@@ -27,17 +33,15 @@ It supports the following open format:
|
|
|
27
33
|
- The PPP/PPP-RTK correction data in RTCM SSR, IGS SSR, Compact SSR, ...
|
|
28
34
|
- The precise orbit/clock data in SP3 format.
|
|
29
35
|
|
|
30
|
-
************************************************
|
|
31
36
|
Click this button for a quick demo in Google Colab
|
|
32
37
|
|
|
33
38
|
<a target="_blank" href="https://colab.research.google.com/github/hirokawa/cssrlib/blob/main/tutorials/cssrlib.ipynb">
|
|
34
39
|
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
|
|
35
40
|
</a>
|
|
36
41
|
|
|
37
|
-
************************************************
|
|
38
42
|
|
|
39
43
|
Prerequisites
|
|
40
|
-
|
|
44
|
+
-------------
|
|
41
45
|
Additional python packages are required as prerequisites and can be installed via the following command
|
|
42
46
|
|
|
43
47
|
```
|
|
@@ -50,8 +54,18 @@ If the installation of `cartopy` fails, try installing `libgeos++-dev` first.
|
|
|
50
54
|
sudo apt-get install libgeos++-dev
|
|
51
55
|
```
|
|
52
56
|
|
|
57
|
+
*NOTE*: the module `pysolid` is used for the computation of solid Earth tides. It contains a hard-coded leap second table with an expiration date, which is set to the next possible injection date of a leap second at the time of the last update. The table is frequently updated by the package maintainers. The following warning is issed when the expiration date is exceeded:
|
|
58
|
+
|
|
59
|
+
> Mild Warning -- time crossed leap second table boundaries. Boundary edge value used instead
|
|
60
|
+
|
|
61
|
+
If you encounter this warning when executing CSSRlib scripts, it can most likely be fixed by updating `pysolid` to the most recent version using
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
pip install -upgrade pysolid
|
|
65
|
+
```
|
|
66
|
+
|
|
53
67
|
Install
|
|
54
|
-
|
|
68
|
+
-------
|
|
55
69
|
|
|
56
70
|
You can install the official version of CSSRlib using pip
|
|
57
71
|
|
|
@@ -68,7 +82,7 @@ pip install .
|
|
|
68
82
|
in the root directory, where the ``setup.cfg`` file is located.
|
|
69
83
|
|
|
70
84
|
Testing
|
|
71
|
-
|
|
85
|
+
-------
|
|
72
86
|
|
|
73
87
|
Run orbit plot sample.
|
|
74
88
|
|
|
@@ -82,14 +96,15 @@ Run RTK sample.
|
|
|
82
96
|
python test_rtk.py
|
|
83
97
|
```
|
|
84
98
|
|
|
85
|
-
Other samples with dataset are also available in a separate repository [`cssrlib-data`](https://github.com/hirokawa/cssrlib-data) including
|
|
99
|
+
Other samples with dataset are also available in a separate repository [`cssrlib-data`](https://github.com/hirokawa/cssrlib-data) including:
|
|
86
100
|
|
|
87
101
|
- Galileo-HAS PPP (SIS/IDD) processing example
|
|
88
102
|
- BDS-PPP processing example
|
|
89
103
|
- QZSS MADOCA-PPP processing example
|
|
90
104
|
- QZSS CLAS PPP-RTK processing example
|
|
91
105
|
- IGS (SP3+BIAS) PPP-AR processing example
|
|
92
|
-
-
|
|
106
|
+
- PPP via SouthPAN (PVS) processing example
|
|
107
|
+
- JPL GDGPS (GPSHAS) processing example
|
|
93
108
|
- Binary message parser for Septentrio receiver (Mosaic/PolaRX5)
|
|
94
109
|
|
|
95
110
|
|
|
@@ -1,25 +1,10 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: cssrlib
|
|
3
|
-
Version: 1.0.1
|
|
4
|
-
Summary: Python Toolkit for PPP/PPP-RTK positioning
|
|
5
|
-
Home-page: https://github.com/hirokawa/cssrlib
|
|
6
|
-
Author: Rui Hirokawa
|
|
7
|
-
Author-email: rui.hirokawa@gmail.com
|
|
8
|
-
Project-URL: Bug Tracker, https://github.com/hirokawa/cssrlib/issues
|
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
-
Classifier: Operating System :: OS Independent
|
|
12
|
-
Requires-Python: >=3.10
|
|
13
|
-
Description-Content-Type: text/markdown
|
|
14
|
-
License-File: LICENSE
|
|
15
|
-
|
|
16
|
-
*************************
|
|
17
1
|
CSSRlib - Toolkit for PPP-RTK/RTK in Python using Compact SSR
|
|
18
|
-
|
|
2
|
+
=============
|
|
19
3
|
|
|
20
|
-
|
|
4
|
+
What is CSSRlib?
|
|
5
|
+
----------------
|
|
21
6
|
|
|
22
|
-
|
|
7
|
+
CSSRlib is a open toolkit in Python for high accuracy GNSS positioning. It supports SSR (State-Space Representation) based positioning for PPP (Precise Point Positioning) or PPP-RTK (Realtime Kinematic), while also supporting RTK. The goal of the CSSRlib toolkit is to provide an easy-to-understand open implementation to learn PPP/PPP-RTK positioning provided by satellite-based open PPP/PPP-RTK services such as QZSS CLAS, Galileo HAS, and BeiDou 3 PPP. It also supports ground based open service by IGS. The code is based on RTKlib.
|
|
23
8
|
|
|
24
9
|
It supports the following open format:
|
|
25
10
|
|
|
@@ -27,17 +12,15 @@ It supports the following open format:
|
|
|
27
12
|
- The PPP/PPP-RTK correction data in RTCM SSR, IGS SSR, Compact SSR, ...
|
|
28
13
|
- The precise orbit/clock data in SP3 format.
|
|
29
14
|
|
|
30
|
-
************************************************
|
|
31
15
|
Click this button for a quick demo in Google Colab
|
|
32
16
|
|
|
33
17
|
<a target="_blank" href="https://colab.research.google.com/github/hirokawa/cssrlib/blob/main/tutorials/cssrlib.ipynb">
|
|
34
18
|
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
|
|
35
19
|
</a>
|
|
36
20
|
|
|
37
|
-
************************************************
|
|
38
21
|
|
|
39
22
|
Prerequisites
|
|
40
|
-
|
|
23
|
+
-------------
|
|
41
24
|
Additional python packages are required as prerequisites and can be installed via the following command
|
|
42
25
|
|
|
43
26
|
```
|
|
@@ -50,8 +33,18 @@ If the installation of `cartopy` fails, try installing `libgeos++-dev` first.
|
|
|
50
33
|
sudo apt-get install libgeos++-dev
|
|
51
34
|
```
|
|
52
35
|
|
|
36
|
+
*NOTE*: the module `pysolid` is used for the computation of solid Earth tides. It contains a hard-coded leap second table with an expiration date, which is set to the next possible injection date of a leap second at the time of the last update. The table is frequently updated by the package maintainers. The following warning is issed when the expiration date is exceeded:
|
|
37
|
+
|
|
38
|
+
> Mild Warning -- time crossed leap second table boundaries. Boundary edge value used instead
|
|
39
|
+
|
|
40
|
+
If you encounter this warning when executing CSSRlib scripts, it can most likely be fixed by updating `pysolid` to the most recent version using
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
pip install -upgrade pysolid
|
|
44
|
+
```
|
|
45
|
+
|
|
53
46
|
Install
|
|
54
|
-
|
|
47
|
+
-------
|
|
55
48
|
|
|
56
49
|
You can install the official version of CSSRlib using pip
|
|
57
50
|
|
|
@@ -68,7 +61,7 @@ pip install .
|
|
|
68
61
|
in the root directory, where the ``setup.cfg`` file is located.
|
|
69
62
|
|
|
70
63
|
Testing
|
|
71
|
-
|
|
64
|
+
-------
|
|
72
65
|
|
|
73
66
|
Run orbit plot sample.
|
|
74
67
|
|
|
@@ -82,14 +75,15 @@ Run RTK sample.
|
|
|
82
75
|
python test_rtk.py
|
|
83
76
|
```
|
|
84
77
|
|
|
85
|
-
Other samples with dataset are also available in a separate repository [`cssrlib-data`](https://github.com/hirokawa/cssrlib-data) including
|
|
78
|
+
Other samples with dataset are also available in a separate repository [`cssrlib-data`](https://github.com/hirokawa/cssrlib-data) including:
|
|
86
79
|
|
|
87
80
|
- Galileo-HAS PPP (SIS/IDD) processing example
|
|
88
81
|
- BDS-PPP processing example
|
|
89
82
|
- QZSS MADOCA-PPP processing example
|
|
90
83
|
- QZSS CLAS PPP-RTK processing example
|
|
91
84
|
- IGS (SP3+BIAS) PPP-AR processing example
|
|
92
|
-
-
|
|
85
|
+
- PPP via SouthPAN (PVS) processing example
|
|
86
|
+
- JPL GDGPS (GPSHAS) processing example
|
|
93
87
|
- Binary message parser for Septentrio receiver (Mosaic/PolaRX5)
|
|
94
88
|
|
|
95
89
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools>=42",
|
|
4
|
+
"wheel"
|
|
5
|
+
]
|
|
6
|
+
build-backend = "setuptools.build_meta"
|
|
7
|
+
|
|
8
|
+
[project]
|
|
9
|
+
name = "cssrlib"
|
|
10
|
+
version = "1.2.0"
|
|
11
|
+
description = "Python Toolkit for PPP/PPP-RTK positioning"
|
|
12
|
+
authors = [
|
|
13
|
+
{name="Rui Hirokawa", email="rui.hirokawa@gmail.com"},
|
|
14
|
+
]
|
|
15
|
+
readme = "README.md"
|
|
16
|
+
requires-python = ">=3.10"
|
|
17
|
+
dependencies = [
|
|
18
|
+
"scipy",
|
|
19
|
+
"bitstruct",
|
|
20
|
+
"galois",
|
|
21
|
+
"crccheck",
|
|
22
|
+
"notebook",
|
|
23
|
+
"numpy",
|
|
24
|
+
"matplotlib",
|
|
25
|
+
"cartopy",
|
|
26
|
+
"pysolid",
|
|
27
|
+
]
|
|
@@ -11,6 +11,7 @@ import bitstruct as bs
|
|
|
11
11
|
import galois
|
|
12
12
|
from cssrlib.cssrlib import cssr, sCSSR, sCSSRTYPE
|
|
13
13
|
from cssrlib.gnss import gpst2time
|
|
14
|
+
from binascii import unhexlify
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class cssr_has(cssr):
|
|
@@ -27,8 +28,6 @@ class cssr_has(cssr):
|
|
|
27
28
|
self.pb_blen = 11
|
|
28
29
|
self.pb_scl = 0.01 # cycles
|
|
29
30
|
|
|
30
|
-
self.GF = galois.GF(256)
|
|
31
|
-
|
|
32
31
|
def sval(self, u, n, scl):
|
|
33
32
|
""" calculate signed value based on n-bit int, lsb """
|
|
34
33
|
invalid = -2**(n-1)
|
|
@@ -59,6 +58,7 @@ class cssr_has(cssr):
|
|
|
59
58
|
return i
|
|
60
59
|
|
|
61
60
|
def decode_head(self, msg, i, st=-1):
|
|
61
|
+
""" decode header part of HAS messages """
|
|
62
62
|
|
|
63
63
|
if st == sCSSR.MASK:
|
|
64
64
|
ui = 0
|
|
@@ -75,6 +75,8 @@ class cssr_has(cssr):
|
|
|
75
75
|
return head, i
|
|
76
76
|
|
|
77
77
|
def decode_cssr(self, msg, i=0):
|
|
78
|
+
""" decode HAS messages """
|
|
79
|
+
|
|
78
80
|
# Galileo HAS-SIS only defines MT=1, MT=4073 is CSSR message used in the
|
|
79
81
|
# Galileo HAS test dataset
|
|
80
82
|
#
|
|
@@ -127,7 +129,29 @@ class cssr_has(cssr):
|
|
|
127
129
|
if self.monlevel > 0 and self.fh is not None:
|
|
128
130
|
self.out_log()
|
|
129
131
|
|
|
132
|
+
|
|
133
|
+
class cnav_msg():
|
|
134
|
+
""" class to handle Galileo E6 (CNAV) message """
|
|
135
|
+
|
|
136
|
+
def __init__(self):
|
|
137
|
+
self.mid_decoded = []
|
|
138
|
+
self.mid_ = -1
|
|
139
|
+
self.ms_ = -1
|
|
140
|
+
self.rec = []
|
|
141
|
+
self.has_pages = np.zeros((255, 53), dtype=int)
|
|
142
|
+
self.gMat = None
|
|
143
|
+
self.GF = galois.GF(256)
|
|
144
|
+
|
|
145
|
+
self.icnt = 0
|
|
146
|
+
self.msgtype = -1
|
|
147
|
+
|
|
148
|
+
self.monlevel = 0
|
|
149
|
+
|
|
150
|
+
def load_gmat(self, file_gm):
|
|
151
|
+
self.gMat = np.genfromtxt(file_gm, dtype="u1", delimiter=",")
|
|
152
|
+
|
|
130
153
|
def decode_has_header(self, buff, i):
|
|
154
|
+
""" decode header of HAS pages (obsoleted) """
|
|
131
155
|
if bs.unpack_from('u24', buff, i)[0] == 0xaf3bc3:
|
|
132
156
|
return 0, 0, 0, 0, 0
|
|
133
157
|
|
|
@@ -146,3 +170,57 @@ class cssr_has(cssr):
|
|
|
146
170
|
HASmsg = np.array(Md).tobytes()
|
|
147
171
|
|
|
148
172
|
return HASmsg
|
|
173
|
+
|
|
174
|
+
def decode_cnav(self, tow, vi):
|
|
175
|
+
""" decode Galileo CNAV message """
|
|
176
|
+
|
|
177
|
+
HASmsg = None
|
|
178
|
+
|
|
179
|
+
for vn in vi:
|
|
180
|
+
buff = unhexlify(vn['nav'])
|
|
181
|
+
i = 14
|
|
182
|
+
if bs.unpack_from('u24', buff, i)[0] == 0xaf3bc3:
|
|
183
|
+
continue
|
|
184
|
+
hass, res = bs.unpack_from('u2u2', buff, i)
|
|
185
|
+
i += 4
|
|
186
|
+
if hass >= 2: # 0:test,1:operational,2:res,3:dnu
|
|
187
|
+
continue
|
|
188
|
+
mt, mid, ms, pid = bs.unpack_from('u2u5u5u8', buff, i)
|
|
189
|
+
|
|
190
|
+
self.msgtype = mt
|
|
191
|
+
ms += 1
|
|
192
|
+
i += 20
|
|
193
|
+
|
|
194
|
+
if self.mid_ == -1 and mid not in self.mid_decoded:
|
|
195
|
+
self.mid_ = mid
|
|
196
|
+
self.ms_ = ms
|
|
197
|
+
if mid == self.mid_ and pid-1 not in self.rec:
|
|
198
|
+
page = bs.unpack_from('u8'*53, buff, i)
|
|
199
|
+
self.rec += [pid-1]
|
|
200
|
+
self.has_pages[pid-1, :] = page
|
|
201
|
+
|
|
202
|
+
if self.monlevel >= 2:
|
|
203
|
+
print(f"{mt} {mid} {ms} {pid}")
|
|
204
|
+
|
|
205
|
+
if len(self.rec) >= self.ms_:
|
|
206
|
+
if self.monlevel >= 2:
|
|
207
|
+
print(" data collected mid={:2d} ms={:2d} tow={:.0f}"
|
|
208
|
+
.format(self.mid_, self.ms_, tow))
|
|
209
|
+
HASmsg = self.decode_has_page(
|
|
210
|
+
self.rec, self.has_pages, self.gMat, self.ms_)
|
|
211
|
+
self.rec = []
|
|
212
|
+
|
|
213
|
+
self.mid_decoded += [self.mid_]
|
|
214
|
+
self.mid_ = -1
|
|
215
|
+
if len(self.mid_decoded) > 10:
|
|
216
|
+
self.mid_decoded = self.mid_decoded[1:]
|
|
217
|
+
else:
|
|
218
|
+
self.icnt += 1
|
|
219
|
+
if self.icnt > 2*self.ms_ and self.mid_ != -1:
|
|
220
|
+
self.icnt = 0
|
|
221
|
+
if self.monlevel >= 2:
|
|
222
|
+
print(f" reset mid={self.mid_} ms={self.ms_} tow={tow}")
|
|
223
|
+
self.rec = []
|
|
224
|
+
self.mid_ = -1
|
|
225
|
+
|
|
226
|
+
return HASmsg
|
|
@@ -0,0 +1,262 @@
|
|
|
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-004), 2025
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
import bitstruct as bs
|
|
12
|
+
from cssrlib.cssrlib import cssr, sCSSRTYPE, sCSSR, local_corr, sCType
|
|
13
|
+
from cssrlib.gnss import gpst2time, uGNSS, prn2sat, rCST
|
|
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
|
+
|
|
42
|
+
self.cssrmode = sCSSRTYPE.QZS_MADOCA
|
|
43
|
+
self.buff = bytearray(250*10)
|
|
44
|
+
|
|
45
|
+
self.pnt = {}
|
|
46
|
+
self.ci = {}
|
|
47
|
+
|
|
48
|
+
self.area = -1
|
|
49
|
+
self.narea_t = {1: 8, 2: 16, 3: 5, 4: 1, 5: 8}
|
|
50
|
+
self.MAXNET = np.sum(list(self.narea_t.values()))
|
|
51
|
+
|
|
52
|
+
for inet in range(self.MAXNET+1):
|
|
53
|
+
self.lc.append(local_corr())
|
|
54
|
+
self.lc[inet].inet = inet
|
|
55
|
+
self.lc[inet].flg_trop = 0
|
|
56
|
+
self.lc[inet].flg_stec = 0
|
|
57
|
+
self.lc[inet].nsat_n = 0
|
|
58
|
+
self.lc[inet].t0 = {}
|
|
59
|
+
|
|
60
|
+
def find_grid_index(self, pos):
|
|
61
|
+
""" find region/area """
|
|
62
|
+
|
|
63
|
+
latd, lond = np.rad2deg(pos[0:2])
|
|
64
|
+
self.reg = self.area = -1
|
|
65
|
+
|
|
66
|
+
for reg in self.pnt.key():
|
|
67
|
+
for area in self.pnt[reg].key():
|
|
68
|
+
p = self.pnt[reg][area]
|
|
69
|
+
if p.sid == 0: # rectangle shape:
|
|
70
|
+
if p.latr-p.lats <= latd and latd <= p.latr+p.lats and \
|
|
71
|
+
p.lonr-p.lons <= lond and lond <= p.lonr+p.lons:
|
|
72
|
+
self.reg = reg
|
|
73
|
+
self.area = area
|
|
74
|
+
break
|
|
75
|
+
elif p.sid == 1: # circle
|
|
76
|
+
dn = (latd - p.latr)*rCST.D2R*rCST.RE_WGS84
|
|
77
|
+
de = (lond - p.lonr)*rCST.D2R * \
|
|
78
|
+
rCST.RE_WGS84*np.cos(p.lonr*rCST.D2R)
|
|
79
|
+
r = np.sqrt(dn**2+de**2)
|
|
80
|
+
if r <= p.rng:
|
|
81
|
+
self.reg = reg
|
|
82
|
+
self.area = area
|
|
83
|
+
break
|
|
84
|
+
|
|
85
|
+
inet = self.get_inet(self.reg, self.area)
|
|
86
|
+
return inet
|
|
87
|
+
|
|
88
|
+
def get_dpos(self, pos):
|
|
89
|
+
""" calculate position offset from reference """
|
|
90
|
+
if self.reg < 0 or self.area < 0:
|
|
91
|
+
print("get_dpos: region, area not defined.")
|
|
92
|
+
return 0, 0
|
|
93
|
+
|
|
94
|
+
latd, lond = np.rad2deg(pos[0:2])
|
|
95
|
+
p = self.pnt[self.reg][self.area]
|
|
96
|
+
dlat = latd - p.latr
|
|
97
|
+
dlon = lond - p.lonr
|
|
98
|
+
|
|
99
|
+
return dlat, dlon
|
|
100
|
+
|
|
101
|
+
def get_stec(self, dlat=0.0, dlon=0.0):
|
|
102
|
+
""" calculate STEC correction by interporation """
|
|
103
|
+
if self.inet < 0:
|
|
104
|
+
print("get_stec: region, area not defined.")
|
|
105
|
+
return 0.0
|
|
106
|
+
|
|
107
|
+
p = self.lc[self.inet]
|
|
108
|
+
# if p.inet_ref != self.iodssr:
|
|
109
|
+
# return 0.0
|
|
110
|
+
stec = np.zeros(self.nsat_n)
|
|
111
|
+
|
|
112
|
+
for i, sat in enumerate(self.sat_n):
|
|
113
|
+
stec[i] = [1, dlat, dlon, dlat*dlon, dlat**2, dlon**2]@p.ci[sat]
|
|
114
|
+
|
|
115
|
+
return stec
|
|
116
|
+
|
|
117
|
+
def decode_mdc_stec_area(self, buff, i=0):
|
|
118
|
+
""" decoder for MT1 - STEC Coverage Message """
|
|
119
|
+
tow, uid, mi, iodssr = bs.unpack_from('u20u4u1u4', buff, i)
|
|
120
|
+
i += 29
|
|
121
|
+
self.tow0 = tow//3600*3600
|
|
122
|
+
reg, alrt, len_, narea = bs.unpack_from('u8u1u16u5', buff, i)
|
|
123
|
+
i += 30
|
|
124
|
+
if reg not in self.pnt:
|
|
125
|
+
self.pnt[reg] = {}
|
|
126
|
+
|
|
127
|
+
for k in range(narea):
|
|
128
|
+
area, sid = bs.unpack_from('u5u1', buff, i)
|
|
129
|
+
i += 6
|
|
130
|
+
|
|
131
|
+
if sid == 0: # rectangle shape
|
|
132
|
+
latr, lonr, lats, lons = bs.unpack_from('s11u12u8u8', buff, i)
|
|
133
|
+
if self.monlevel > 2:
|
|
134
|
+
print(f"{reg} {area:2d} {sid} {latr*0.1:5.1f} "
|
|
135
|
+
f"{lonr*0.1:5.1f} {lats*0.1:3.1f} {lons*0.1:3.1f}")
|
|
136
|
+
self.pnt[reg][area] = areaInfo(
|
|
137
|
+
sid, latr*0.1, lonr*0.1, lats*0.1, lons*0.1)
|
|
138
|
+
else: # circle range
|
|
139
|
+
latr, lonr, rng = bs.unpack_from('s15u16u8', buff, i)
|
|
140
|
+
if self.monlevel > 2:
|
|
141
|
+
print(f"{reg} {area:2d} {sid} {latr*0.01:6.2f} "
|
|
142
|
+
f"{lonr*0.01:6.2f} {rng*10}")
|
|
143
|
+
self.pnt[reg][area] = areaInfo(
|
|
144
|
+
sid, latr*0.01, lonr*0.01, rng*10.0)
|
|
145
|
+
i += 39
|
|
146
|
+
return i
|
|
147
|
+
|
|
148
|
+
def get_inet(self, reg, area):
|
|
149
|
+
""" region, area to inet conversion """
|
|
150
|
+
|
|
151
|
+
inet = 0
|
|
152
|
+
for r in self.narea_t.keys():
|
|
153
|
+
if r >= reg:
|
|
154
|
+
break
|
|
155
|
+
inet += self.narea_t[r]
|
|
156
|
+
|
|
157
|
+
inet += area
|
|
158
|
+
|
|
159
|
+
return inet
|
|
160
|
+
|
|
161
|
+
def decode_mdc_stec_corr(self, buff, i=0):
|
|
162
|
+
""" decoder for MT2 - STEC Correction Message """
|
|
163
|
+
dtow, uid, mi, iodssr = bs.unpack_from('u12u4u1u4', buff, i)
|
|
164
|
+
i += 21
|
|
165
|
+
reg, area, stype_ = bs.unpack_from('u8u5u2', buff, i)
|
|
166
|
+
i += 15
|
|
167
|
+
|
|
168
|
+
nsat = bs.unpack_from('u5u5u5u5u5', buff, i)
|
|
169
|
+
i += 25
|
|
170
|
+
# gps, glo, gal, bds, qzss
|
|
171
|
+
sys_t = [uGNSS.GPS, uGNSS.GLO, uGNSS.GAL, uGNSS.BDS, uGNSS.QZS]
|
|
172
|
+
|
|
173
|
+
inet = self.get_inet(reg, area)
|
|
174
|
+
|
|
175
|
+
self.lc[inet].nsat_n = np.sum(nsat)
|
|
176
|
+
ci = {}
|
|
177
|
+
qi = {}
|
|
178
|
+
stype = {}
|
|
179
|
+
sat_ = []
|
|
180
|
+
j = 0
|
|
181
|
+
for gnss in range(5):
|
|
182
|
+
sys = sys_t[gnss]
|
|
183
|
+
for k in range(nsat[gnss]):
|
|
184
|
+
c01 = c10 = c11 = c02 = c20 = 0.0
|
|
185
|
+
|
|
186
|
+
prn, qi_, c00 = bs.unpack_from('u6u6s14', buff, i)
|
|
187
|
+
i += 26
|
|
188
|
+
|
|
189
|
+
if sys == uGNSS.QZS:
|
|
190
|
+
prn += 192
|
|
191
|
+
sat = prn2sat(sys, prn)
|
|
192
|
+
qi[sat] = qi_
|
|
193
|
+
stype[sat] = stype_
|
|
194
|
+
|
|
195
|
+
if stype_ > 0:
|
|
196
|
+
c01, c10 = bs.unpack_from('s12s12', buff, i)
|
|
197
|
+
i += 24
|
|
198
|
+
if stype_ > 1:
|
|
199
|
+
c11 = bs.unpack_from('s10', buff, i)[0]
|
|
200
|
+
i += 10
|
|
201
|
+
if stype_ > 2:
|
|
202
|
+
c02, c20 = bs.unpack_from('s8s8', buff, i)
|
|
203
|
+
i += 16
|
|
204
|
+
|
|
205
|
+
sat_ += [sat]
|
|
206
|
+
ci[sat] = np.array(
|
|
207
|
+
[c00*0.05, c01*0.02, c10*0.02, c11*0.02,
|
|
208
|
+
c02*5e-3, c20*5e-3])
|
|
209
|
+
j += 1
|
|
210
|
+
|
|
211
|
+
self.lc[inet].stype = stype
|
|
212
|
+
self.lc[inet].sat_n = sat_
|
|
213
|
+
self.lc[inet].ci = ci
|
|
214
|
+
self.lc[inet].stec_quality = qi
|
|
215
|
+
|
|
216
|
+
t0 = gpst2time(self.week, self.tow0+dtow)
|
|
217
|
+
self.set_t0(inet, 0, sCType.STEC, t0)
|
|
218
|
+
self.lc[inet].cstat |= (1 << sCType.STEC)
|
|
219
|
+
|
|
220
|
+
self.lc[inet].inet_ref = iodssr
|
|
221
|
+
|
|
222
|
+
return i
|
|
223
|
+
|
|
224
|
+
def decode_cssr(self, msg, i=0):
|
|
225
|
+
"""decode Compact SSR message with MADOCA-PPP extension """
|
|
226
|
+
df = {'msgtype': 4073}
|
|
227
|
+
while df['msgtype'] in [1, 2, 4073]:
|
|
228
|
+
df = bs.unpack_from_dict('u12u4', ['msgtype', 'subtype'], msg, i)
|
|
229
|
+
i += 16
|
|
230
|
+
if df['msgtype'] not in [1, 2, 4073]:
|
|
231
|
+
return -1
|
|
232
|
+
|
|
233
|
+
self.subtype = df['subtype']
|
|
234
|
+
if df['msgtype'] == 4073: # Compact SSR
|
|
235
|
+
if self.subtype == sCSSR.MASK:
|
|
236
|
+
i = self.decode_cssr_mask(msg, i)
|
|
237
|
+
elif self.subtype == sCSSR.ORBIT: # orbit
|
|
238
|
+
i = self.decode_cssr_orb(msg, i)
|
|
239
|
+
elif self.subtype == sCSSR.CLOCK: # clock
|
|
240
|
+
i = self.decode_cssr_clk(msg, i)
|
|
241
|
+
elif self.subtype == sCSSR.CBIAS: # cbias
|
|
242
|
+
i = self.decode_cssr_cbias(msg, i)
|
|
243
|
+
elif self.subtype == sCSSR.PBIAS: # pbias
|
|
244
|
+
i = self.decode_cssr_pbias(msg, i)
|
|
245
|
+
elif self.subtype == sCSSR.BIAS: # bias
|
|
246
|
+
i = self.decode_cssr_bias(msg, i)
|
|
247
|
+
elif self.subtype == sCSSR.URA: # ura
|
|
248
|
+
i = self.decode_cssr_ura(msg, i)
|
|
249
|
+
elif df['msgtype'] in [1, 2] and df['subtype'] == 0:
|
|
250
|
+
if df['msgtype'] == 1: # MADOCA MT1
|
|
251
|
+
i = self.decode_mdc_stec_area(msg, i)
|
|
252
|
+
elif df['msgtype'] == 2: # MADOCA MT2
|
|
253
|
+
i = self.decode_mdc_stec_corr(msg, i)
|
|
254
|
+
|
|
255
|
+
if i <= 0:
|
|
256
|
+
return 0
|
|
257
|
+
if self.monlevel >= 2:
|
|
258
|
+
print(f"tow={int(self.tow):6d} msgtype={df['msgtype']:4d} "
|
|
259
|
+
f"subtype={self.subtype:2d} inet={self.inet:2d}")
|
|
260
|
+
|
|
261
|
+
if self.monlevel > 0 and self.fh is not None:
|
|
262
|
+
self.out_log()
|