Skip to content

Commit

Permalink
Merge pull request #39 from hirokawa/devel
Browse files Browse the repository at this point in the history
Prepare for v1.0.0
  • Loading branch information
hirokawa committed Jan 1, 2024
2 parents 5228e89 + 017fe86 commit dad0ca5
Show file tree
Hide file tree
Showing 20 changed files with 2,403 additions and 3,123 deletions.
74 changes: 74 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),


# [1.0.0] 2024-01-01

### Added
New integrated class structure (PPPOS) for PPP/PPP-RTK/RTK processing

Support for RTCM3 (Galileo HAS IDD)

Decoder for Septentrio receiver

Parser for RTCM3, L5 SBAS

Experimental support for PPP via SouthPAN (PVS)

New solid Earth tides model using PySolid (2010 IERS Conventions)

### Changed

Improved documentation

Sign of SSR satellite signal code/phase bias align with RTCM 3 convention

PPPIGS was integrated into PPPOS and removed

### Fixed

Link for cssrlib-data

### Deprecated
### Removed
Function based PPP/PPP-RTK/RTK processing
### Security

# [0.8.0] 2023-09-09

### Added
New signal structure

Support for open PPP services: Galileo HAS (SIS), BDS PPP, QZSS MADOCA-PPP

Support for IGS (SP3+BIAS)

Parser for SP3, ANTEX, BIAS files

Support for PPP-AR

Jupyter notebook with examples

### Changed

Improved documentation

Added link for Google Colab

### Fixed
### Deprecated
### Removed
### Security

# [0.3.0] 2022-03-01

### Added
Initial version for PPP-RTK (QZSS CLAS) and RTK

### Changed
### Fixed
### Deprecated
### Removed
### Security
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ It supports the following open format:
************************************************
Click this button for a quick demo in Google Colab


<a target="_blank" href="https://colab.research.google.com/github/hirokawa/cssrlib/blob/main/tutorials/cssrlib.ipynb">
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
</a>
Expand All @@ -27,14 +26,14 @@ Prerequisites
Additional python packages are required as prerequisites and can be installed via the following commands

```
pip install bitstruct galois crccheck
pip install bitstruct galois crccheck pysolid
pip install notebook numpy matplotlib
```

Optionally, on linux, users can install the `cartopy` package
Optionally, on linux, users can install the `cartopy` package and the `PySolid` package

```
pip install cartopy
pip install cartopy pysolid
```

If the installation of `cartopy` fails, try installing `libgeos++-dev` first.
Expand Down Expand Up @@ -75,9 +74,14 @@ Run RTK sample.
python test_rtk.py
```

Other samples are also available in a separate repository [`cssrlib-data`](https://github.com/hirokawa/cssrlib-data) including :
Other samples with dataset are also available in a separate repository [`cssrlib-data`](https://github.com/hirokawa/cssrlib-data) including :

- Galileo-HAS PPP (SIS/IDD) processing example
- BDS-PPP processing example
- QZSS MADOCA-PPP processing example
- QZSS CLAS PPP-RTK processing example
- IGS (SP3+BIAS) PPP-AR processing example
- (experimental) PPP via SouthPAN (PVS) processing example
- Binary message parser for Septentrio receiver (Mosaic/PolaRX5)

- Galileo-HAS decoder
- BDS-PPP decoder
- Jupyter-Notebook including samples for RTK/PPP-RTK.

3 changes: 1 addition & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
[metadata]
name = cssrlib
version = 0.8.0
author = Rui Hirokawa
author_email = rui.hirokawa@gmail.com
description = Compact SSR Library for PPP/PPP-RTK
description = Python Toolkit for PPP/PPP-RTK positioning
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/hirokawa/cssrlib
Expand Down
92 changes: 55 additions & 37 deletions src/cssrlib/cssr_bds.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,24 +156,24 @@ def decode_cssr_mask(self, msg, i):
self.add_gnss(mask_glo, 37, sGNSS.GLO)

inet = 0
self.lc[inet].dclk = np.ones(self.nsat_n)*np.nan
self.lc[inet].dorb = np.ones((self.nsat_n, 3))*np.nan
self.lc[inet].iode = np.zeros(self.nsat_n, dtype=int)
self.lc[inet].iodc = np.zeros(self.nsat_n, dtype=int)
self.lc[inet].iodc_c = np.zeros(self.nsat_n, dtype=int)
self.lc[inet].cbias = np.ones((self.nsat_n, self.nsig_max))*np.nan
self.lc[inet].dclk = {}
self.lc[inet].dorb = {}
self.lc[inet].iode = {}
self.lc[inet].iodc = {}
self.lc[inet].iodc_c = {}
self.lc[inet].cbias = {}
self.nsig_n = np.ones(self.nsat_n, dtype=int)*self.nsig_max
self.sig_n = -1*np.ones((self.nsat_n, self.nsig_max), dtype=int)
self.ura = np.zeros(self.nsat_n)
self.sig_n = {}
self.ura = {}

# fallback for inconsistent clock update
self.lc[inet].dclk_p = np.ones(self.nsat_n)*np.nan
self.lc[inet].iodc_c_p = np.zeros(self.nsat_n, dtype=int)
self.lc[inet].dclk_p = {}
self.lc[inet].iodc_c_p = {}

self.iodssr = head['iodssr']

self.lc[0].cstat |= (1 << sCType.MASK)
self.lc[0].t0[sCType.MASK] = self.time
# self.lc[0].t0[0][sCType.MASK] = self.time
return i

def decode_cssr_orb_sat(self, msg, i, inet, sat_n):
Expand All @@ -186,17 +186,24 @@ def decode_cssr_orb_sat(self, msg, i, inet, sat_n):
sat = prn2sat(sys, prn)
if sat not in sat_n:
return i
idx = np.where(sat == sat_n)[0][0]

if (sys == uGNSS.GPS) or (sys == uGNSS.BDS):
iodn = iodn & 0xff # IODC -> IODE

self.lc[inet].iode[idx] = iodn
self.lc[inet].iodc[idx] = iodc
self.lc[inet].dorb[idx, 0] = self.sval(dx, 15, self.dorb_scl[0])
self.lc[inet].dorb[idx, 1] = self.sval(dy, 13, self.dorb_scl[1])
self.lc[inet].dorb[idx, 2] = self.sval(dz, 13, self.dorb_scl[2])
self.ura[idx] = self.quality_idx(ucls, uval)
dorb = np.zeros(3)
dorb[0] = self.sval(dx, 15, self.dorb_scl[0])
dorb[1] = self.sval(dy, 13, self.dorb_scl[1])
dorb[2] = self.sval(dz, 13, self.dorb_scl[2])

self.lc[inet].iode[sat] = iodn
self.lc[inet].iodc[sat] = iodc
self.lc[inet].dorb[sat] = dorb
self.ura[sat] = self.quality_idx(ucls, uval)

if sat not in self.lc[inet].t0:
self.lc[inet].t0[sat] = {}

self.lc[inet].t0[sat][sCType.ORBIT] = self.time
return i

def decode_cssr_orb(self, msg, i, inet=0):
Expand All @@ -212,7 +219,7 @@ def decode_cssr_orb(self, msg, i, inet=0):

self.iodssr_c[sCType.ORBIT] = head['iodssr']
self.lc[inet].cstat |= (1 << sCType.ORBIT)
self.lc[inet].t0[sCType.ORBIT] = self.time

i += 19
return i

Expand All @@ -233,30 +240,36 @@ def decode_cssr_cbias(self, msg, i, inet=0):
i += 13
sys, prn = self.slot2prn(slot)
sat = prn2sat(sys, prn)
idx = np.where(sat == sat_n)[0]
if len(idx) == 0:
if sat not in sat_n:
continue
if sat not in self.lc[inet].t0:
self.lc[inet].t0[sat] = {}
self.lc[inet].t0[sat][sCType.CBIAS] = self.time

self.lc[inet].cbias[sat] = {}
for j in range(0, nsig):
sig, cb = bs.unpack_from('u4s12', msg, i)
i += 16
self.sig_n[idx, j] = sig
self.lc[inet].cbias[idx, j] = self.sval(cb, 12, self.cb_scl)
sig_ = self.ssig2rsig(sys, uTYP.C, sig)
self.lc[inet].cbias[sat][sig_] = self.sval(cb, 12, self.cb_scl)

self.iodssr_c[sCType.CBIAS] = head['iodssr']
self.lc[inet].cstat |= (1 << sCType.CBIAS)
self.lc[inet].t0[sCType.CBIAS] = self.time

return i

def decode_cssr_clk_sat(self, msg, i, inet, idx):
def decode_cssr_clk_sat(self, msg, i, inet, sat):
""" decode clock correction for satellite """
iodc, dclk = bs.unpack_from('u3s15', msg, i)
i += 18
if iodc != self.lc[inet].iodc_c[idx]:
self.lc[inet].iodc_c_p[idx] = self.lc[inet].iodc_c[idx]
self.lc[inet].dclk_p[idx] = self.lc[inet].dclk[idx]
self.lc[inet].iodc_c[idx] = iodc

if sat in self.lc[inet].iodc_c.keys() and \
iodc != self.lc[inet].iodc_c[sat]:
self.lc[inet].iodc_c_p[sat] = self.lc[inet].iodc_c[sat]
self.lc[inet].dclk_p[sat] = self.lc[inet].dclk[sat]
self.lc[inet].iodc_c[sat] = iodc
# note: the sign of the clock correction reversed
self.lc[inet].dclk[idx] = -self.sval(dclk, 15, self.dclk_scl)
self.lc[inet].dclk[sat] = -self.sval(dclk, 15, self.dclk_scl)
return i

def decode_cssr_clk(self, msg, i, inet=0):
Expand All @@ -273,11 +286,15 @@ def decode_cssr_clk(self, msg, i, inet=0):
for k in range(23):
idx = st1*23+k
if idx < self.nsat_n:
i = self.decode_cssr_clk_sat(msg, i, inet, idx)
sat = self.sat_n[idx]
i = self.decode_cssr_clk_sat(msg, i, inet, sat)
if sat not in self.lc[inet].t0:
self.lc[inet].t0[sat] = {}
self.lc[inet].t0[sat][sCType.CLOCK] = self.time

self.iodssr_c[sCType.CLOCK] = head['iodssr']
self.lc[inet].cstat |= (1 << sCType.CLOCK)
self.lc[inet].t0[sCType.CLOCK] = self.time

i += 10
return i

Expand All @@ -295,10 +312,11 @@ def decode_cssr_ura(self, msg, i):
i += 6
idx = st2*70+k
if idx < self.nsat_n:
self.ura[idx] = self.quality_idx(v['class'], v['val'])
sat = self.sat_n[idx]
self.ura[sat] = self.quality_idx(v['class'], v['val'])

self.lc[0].cstat |= (1 << sCType.URA)
self.lc[0].t0[sCType.URA] = self.time
# self.lc[0].t0[0][sCType.URA] = self.time
return i

def decode_cssr_comb1(self, msg, i, inet=0):
Expand All @@ -312,7 +330,8 @@ def decode_cssr_comb1(self, msg, i, inet=0):
i += 36
for k in range(numc):
idx = slot_s+k
i = self.decode_cssr_clk_sat(msg, i, inet, idx)
sat = self.sat_n[idx]
i = self.decode_cssr_clk_sat(msg, i, inet, sat)

if numo > 0:
tod, _, iodssr = bs.unpack_from('u17u4u2', msg, i)
Expand All @@ -335,8 +354,7 @@ def decode_cssr_comb2(self, msg, i, inet=0):
i += 9
sys, prn = self.slot2prn(slot)
sat = prn2sat(sys, prn)
idx = np.where(sat == sat_n)[0]
i = self.decode_cssr_clk_sat(msg, i, inet, idx)
i = self.decode_cssr_clk_sat(msg, i, inet, sat)

if numo > 0:
tod, _, iodssr = bs.unpack_from('u17u4u2', msg, i)
Expand Down

0 comments on commit dad0ca5

Please sign in to comment.