gnsskit 0.4.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.
- gnsskit-0.4.0/LICENSE +21 -0
- gnsskit-0.4.0/PKG-INFO +72 -0
- gnsskit-0.4.0/README.md +42 -0
- gnsskit-0.4.0/pyproject.toml +64 -0
- gnsskit-0.4.0/pyproject.toml.orig +43 -0
- gnsskit-0.4.0/src/gnsskit/__init__.py +76 -0
- gnsskit-0.4.0/src/gnsskit/kinematic/__init__.py +5 -0
- gnsskit-0.4.0/src/gnsskit/kinematic/trajectory.py +84 -0
- gnsskit-0.4.0/src/gnsskit/ppp/__init__.py +16 -0
- gnsskit-0.4.0/src/gnsskit/py.typed +0 -0
- gnsskit-0.4.0/src/gnsskit/refsys.py +308 -0
- gnsskit-0.4.0/src/gnsskit/rinex.py +467 -0
- gnsskit-0.4.0/src/gnsskit/rtklib/__init__.py +17 -0
- gnsskit-0.4.0/src/gnsskit/rtklib/config.py +313 -0
- gnsskit-0.4.0/src/gnsskit/rtklib/pos.py +158 -0
- gnsskit-0.4.0/src/gnsskit/rtklib/runner.py +146 -0
- gnsskit-0.4.0/src/gnsskit/static/__init__.py +31 -0
- gnsskit-0.4.0/src/gnsskit/static/baseline.py +323 -0
- gnsskit-0.4.0/src/gnsskit/static/closure.py +79 -0
- gnsskit-0.4.0/src/gnsskit/static/network.py +448 -0
- gnsskit-0.4.0/src/gnsskit/static/solve.py +54 -0
gnsskit-0.4.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023-2026 Francesco Ioli
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
gnsskit-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gnsskit
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: RTKLIB-based GNSS post-processing toolkit: RINEX tools, RTKLIB wrappers, static baselines and network adjustment, kinematic trajectories
|
|
5
|
+
Keywords: gnss,gps,rtklib,ppk,surveying,least-squares
|
|
6
|
+
Author: Francesco Ioli
|
|
7
|
+
Author-email: Francesco Ioli <francesco.ioli@polimi.it>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Dist: numpy
|
|
20
|
+
Requires-Dist: pandas>=2
|
|
21
|
+
Requires-Dist: scipy ; extra == 'network'
|
|
22
|
+
Requires-Dist: pyproj ; extra == 'network'
|
|
23
|
+
Requires-Dist: matplotlib ; extra == 'plot'
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Project-URL: Repository, https://github.com/franioli/gnsskit
|
|
26
|
+
Project-URL: Issues, https://github.com/franioli/gnsskit/issues
|
|
27
|
+
Provides-Extra: network
|
|
28
|
+
Provides-Extra: plot
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# gnsskit
|
|
32
|
+
|
|
33
|
+
Shared tools for post-processing GNSS data with [RTKLIB](https://www.rtklib.com/) `rnx2rtkp`, used by
|
|
34
|
+
[djippk](https://github.com/franioli/djippk) (drone PPK) and [stopgo](https://github.com/franioli/stopgo)
|
|
35
|
+
(stop-and-go surveys).
|
|
36
|
+
|
|
37
|
+
- **RTKLIB wrappers** (`gnsskit.rtklib`): `RtkConfig`, a typed, immutable set of `rnx2rtkp` options
|
|
38
|
+
(`from_file`, `updated`, `with_options`, `with_base_llh`, `write`); `run_rnx2rtkp` and `find_rnx2rtkp`;
|
|
39
|
+
`read_pos` (llh, xyz and enu `.pos` files).
|
|
40
|
+
- **RINEX** (`gnsskit.rinex`): `rinex_span`, `header_llh`, `trim_rinex`; inspection with `obs_summary`
|
|
41
|
+
(span, sampling, gaps, satellites), `read_visibility` and `plot_visibility` (RTKPLOT-style satellite
|
|
42
|
+
visibility, needs the `plot` extra).
|
|
43
|
+
- **Static** (`gnsskit.static`): `solve_static` (one solution over a time window), `process_baseline`
|
|
44
|
+
(static baselines with covariance), baseline IO and `loop_closures` (misclosure of every triangle of baselines); least-squares adjustment of a redundant baseline
|
|
45
|
+
network in `gnsskit.static.network` (needs the `network` extra).
|
|
46
|
+
- **Kinematic** (`gnsskit.kinematic`): trajectory interpolation and averaging.
|
|
47
|
+
- **Reference systems** (`gnsskit.refsys`): GPST/UTC, ellipsoids, ECEF/geodetic conversions and
|
|
48
|
+
`ENUFrame`, a local east-north-up frame at a point (points, vectors and covariances, both ways).
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
pip install gnsskit # library
|
|
54
|
+
pip install "gnsskit[network]" # + network adjustment (scipy, pyproj)
|
|
55
|
+
pip install "gnsskit[network,plot]" # + satellite visibility plots (matplotlib)
|
|
56
|
+
pip install git+https://github.com/franioli/gnsskit # development version
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`rnx2rtkp` is not installed by pip. Build the [demo5 fork](https://github.com/rtklibexplorer/RTKLIB) and put it on
|
|
60
|
+
your `PATH`; if it is missing, `run_rnx2rtkp` raises an error with instructions. Developed with `rnx2rtkp ver.EX 2.5.1`.
|
|
61
|
+
|
|
62
|
+
## Example
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from gnsskit import RtkConfig, read_pos, run_rnx2rtkp
|
|
66
|
+
|
|
67
|
+
config = RtkConfig(posmode="static", navsys="GEC", solformat="llh").with_base_llh(46.2, 9.8, 2300.0)
|
|
68
|
+
pos_file = run_rnx2rtkp(rover_obs, base_obs, [nav], config, "out.pos")
|
|
69
|
+
pos = read_pos(pos_file)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
See [example/](https://github.com/franioli/gnsskit/tree/main/example) for complete static, kinematic and network adjustment examples.
|
gnsskit-0.4.0/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# gnsskit
|
|
2
|
+
|
|
3
|
+
Shared tools for post-processing GNSS data with [RTKLIB](https://www.rtklib.com/) `rnx2rtkp`, used by
|
|
4
|
+
[djippk](https://github.com/franioli/djippk) (drone PPK) and [stopgo](https://github.com/franioli/stopgo)
|
|
5
|
+
(stop-and-go surveys).
|
|
6
|
+
|
|
7
|
+
- **RTKLIB wrappers** (`gnsskit.rtklib`): `RtkConfig`, a typed, immutable set of `rnx2rtkp` options
|
|
8
|
+
(`from_file`, `updated`, `with_options`, `with_base_llh`, `write`); `run_rnx2rtkp` and `find_rnx2rtkp`;
|
|
9
|
+
`read_pos` (llh, xyz and enu `.pos` files).
|
|
10
|
+
- **RINEX** (`gnsskit.rinex`): `rinex_span`, `header_llh`, `trim_rinex`; inspection with `obs_summary`
|
|
11
|
+
(span, sampling, gaps, satellites), `read_visibility` and `plot_visibility` (RTKPLOT-style satellite
|
|
12
|
+
visibility, needs the `plot` extra).
|
|
13
|
+
- **Static** (`gnsskit.static`): `solve_static` (one solution over a time window), `process_baseline`
|
|
14
|
+
(static baselines with covariance), baseline IO and `loop_closures` (misclosure of every triangle of baselines); least-squares adjustment of a redundant baseline
|
|
15
|
+
network in `gnsskit.static.network` (needs the `network` extra).
|
|
16
|
+
- **Kinematic** (`gnsskit.kinematic`): trajectory interpolation and averaging.
|
|
17
|
+
- **Reference systems** (`gnsskit.refsys`): GPST/UTC, ellipsoids, ECEF/geodetic conversions and
|
|
18
|
+
`ENUFrame`, a local east-north-up frame at a point (points, vectors and covariances, both ways).
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
pip install gnsskit # library
|
|
24
|
+
pip install "gnsskit[network]" # + network adjustment (scipy, pyproj)
|
|
25
|
+
pip install "gnsskit[network,plot]" # + satellite visibility plots (matplotlib)
|
|
26
|
+
pip install git+https://github.com/franioli/gnsskit # development version
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`rnx2rtkp` is not installed by pip. Build the [demo5 fork](https://github.com/rtklibexplorer/RTKLIB) and put it on
|
|
30
|
+
your `PATH`; if it is missing, `run_rnx2rtkp` raises an error with instructions. Developed with `rnx2rtkp ver.EX 2.5.1`.
|
|
31
|
+
|
|
32
|
+
## Example
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from gnsskit import RtkConfig, read_pos, run_rnx2rtkp
|
|
36
|
+
|
|
37
|
+
config = RtkConfig(posmode="static", navsys="GEC", solformat="llh").with_base_llh(46.2, 9.8, 2300.0)
|
|
38
|
+
pos_file = run_rnx2rtkp(rover_obs, base_obs, [nav], config, "out.pos")
|
|
39
|
+
pos = read_pos(pos_file)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
See [example/](https://github.com/franioli/gnsskit/tree/main/example) for complete static, kinematic and network adjustment examples.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "gnsskit"
|
|
3
|
+
version = "0.4.0"
|
|
4
|
+
description = "RTKLIB-based GNSS post-processing toolkit: RINEX tools, RTKLIB wrappers, static baselines and network adjustment, kinematic trajectories"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
keywords = [
|
|
9
|
+
"gnss",
|
|
10
|
+
"gps",
|
|
11
|
+
"rtklib",
|
|
12
|
+
"ppk",
|
|
13
|
+
"surveying",
|
|
14
|
+
"least-squares",
|
|
15
|
+
]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Science/Research",
|
|
19
|
+
"Topic :: Scientific/Engineering :: GIS",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Typing :: Typed",
|
|
26
|
+
]
|
|
27
|
+
requires-python = ">=3.10"
|
|
28
|
+
dependencies = [
|
|
29
|
+
"numpy",
|
|
30
|
+
"pandas>=2",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[[project.authors]]
|
|
34
|
+
name = "Francesco Ioli"
|
|
35
|
+
email = "francesco.ioli@polimi.it"
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
network = [
|
|
39
|
+
"scipy",
|
|
40
|
+
"pyproj",
|
|
41
|
+
]
|
|
42
|
+
plot = ["matplotlib"]
|
|
43
|
+
|
|
44
|
+
[project.urls]
|
|
45
|
+
Repository = "https://github.com/franioli/gnsskit"
|
|
46
|
+
Issues = "https://github.com/franioli/gnsskit/issues"
|
|
47
|
+
|
|
48
|
+
[dependency-groups]
|
|
49
|
+
dev = [
|
|
50
|
+
"pytest",
|
|
51
|
+
"scipy",
|
|
52
|
+
"pyproj",
|
|
53
|
+
"matplotlib",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[build-system]
|
|
57
|
+
requires = ["uv_build>=0.12.23,<0.13.0"]
|
|
58
|
+
build-backend = "uv_build"
|
|
59
|
+
|
|
60
|
+
[tool.pytest.ini_options]
|
|
61
|
+
testpaths = ["tests"]
|
|
62
|
+
|
|
63
|
+
[tool.ruff]
|
|
64
|
+
line-length = 100
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "gnsskit"
|
|
3
|
+
version = "0.4.0"
|
|
4
|
+
description = "RTKLIB-based GNSS post-processing toolkit: RINEX tools, RTKLIB wrappers, static baselines and network adjustment, kinematic trajectories"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
authors = [{ name = "Francesco Ioli", email = "francesco.ioli@polimi.it" }]
|
|
9
|
+
keywords = ["gnss", "gps", "rtklib", "ppk", "surveying", "least-squares"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 3 - Alpha",
|
|
12
|
+
"Intended Audience :: Science/Research",
|
|
13
|
+
"Topic :: Scientific/Engineering :: GIS",
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.10",
|
|
16
|
+
"Programming Language :: Python :: 3.11",
|
|
17
|
+
"Programming Language :: Python :: 3.12",
|
|
18
|
+
"Programming Language :: Python :: 3.13",
|
|
19
|
+
"Typing :: Typed",
|
|
20
|
+
]
|
|
21
|
+
requires-python = ">=3.10"
|
|
22
|
+
dependencies = ["numpy", "pandas>=2"]
|
|
23
|
+
|
|
24
|
+
[project.optional-dependencies]
|
|
25
|
+
network = ["scipy", "pyproj"]
|
|
26
|
+
plot = ["matplotlib"]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Repository = "https://github.com/franioli/gnsskit"
|
|
30
|
+
Issues = "https://github.com/franioli/gnsskit/issues"
|
|
31
|
+
|
|
32
|
+
[dependency-groups]
|
|
33
|
+
dev = ["pytest", "scipy", "pyproj", "matplotlib"]
|
|
34
|
+
|
|
35
|
+
[build-system]
|
|
36
|
+
requires = ["uv_build>=0.12.23,<0.13.0"]
|
|
37
|
+
build-backend = "uv_build"
|
|
38
|
+
|
|
39
|
+
[tool.pytest.ini_options]
|
|
40
|
+
testpaths = ["tests"]
|
|
41
|
+
|
|
42
|
+
[tool.ruff]
|
|
43
|
+
line-length = 100
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Shared RTKLIB-based GNSS post-processing tools."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import version
|
|
4
|
+
|
|
5
|
+
from .kinematic import interpolate
|
|
6
|
+
from .refsys import (
|
|
7
|
+
GPS_EPOCH,
|
|
8
|
+
GPST_UTC_OFFSET_S,
|
|
9
|
+
GRS80,
|
|
10
|
+
WGS84,
|
|
11
|
+
Ellipsoid,
|
|
12
|
+
ENUFrame,
|
|
13
|
+
enu_diff,
|
|
14
|
+
gpst_to_local,
|
|
15
|
+
utc_to_gpst,
|
|
16
|
+
)
|
|
17
|
+
from .rinex import (
|
|
18
|
+
find_rinex_obs,
|
|
19
|
+
header_llh,
|
|
20
|
+
obs_summary,
|
|
21
|
+
plot_visibility,
|
|
22
|
+
read_visibility,
|
|
23
|
+
rinex_span,
|
|
24
|
+
satellite_stats,
|
|
25
|
+
signal_stats,
|
|
26
|
+
trim_rinex,
|
|
27
|
+
)
|
|
28
|
+
from .rtklib import (
|
|
29
|
+
RtkConfig,
|
|
30
|
+
navsys_mask,
|
|
31
|
+
read_header,
|
|
32
|
+
read_pos,
|
|
33
|
+
read_ref_pos,
|
|
34
|
+
run_rnx2rtkp,
|
|
35
|
+
)
|
|
36
|
+
from .static import (
|
|
37
|
+
baselines_to_df,
|
|
38
|
+
df_to_baselines,
|
|
39
|
+
loop_closures,
|
|
40
|
+
process_baseline,
|
|
41
|
+
solve_static,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
__version__ = version("gnsskit")
|
|
45
|
+
__all__ = [
|
|
46
|
+
"GPST_UTC_OFFSET_S",
|
|
47
|
+
"GPS_EPOCH",
|
|
48
|
+
"GRS80",
|
|
49
|
+
"WGS84",
|
|
50
|
+
"ENUFrame",
|
|
51
|
+
"Ellipsoid",
|
|
52
|
+
"RtkConfig",
|
|
53
|
+
"baselines_to_df",
|
|
54
|
+
"df_to_baselines",
|
|
55
|
+
"enu_diff",
|
|
56
|
+
"find_rinex_obs",
|
|
57
|
+
"gpst_to_local",
|
|
58
|
+
"header_llh",
|
|
59
|
+
"interpolate",
|
|
60
|
+
"loop_closures",
|
|
61
|
+
"navsys_mask",
|
|
62
|
+
"obs_summary",
|
|
63
|
+
"plot_visibility",
|
|
64
|
+
"process_baseline",
|
|
65
|
+
"read_header",
|
|
66
|
+
"read_pos",
|
|
67
|
+
"read_ref_pos",
|
|
68
|
+
"read_visibility",
|
|
69
|
+
"rinex_span",
|
|
70
|
+
"run_rnx2rtkp",
|
|
71
|
+
"satellite_stats",
|
|
72
|
+
"signal_stats",
|
|
73
|
+
"solve_static",
|
|
74
|
+
"trim_rinex",
|
|
75
|
+
"utc_to_gpst",
|
|
76
|
+
]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Sampling a kinematic trajectory (`read_pos` output): at given times or inside windows."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
from ..refsys import GPS_EPOCH, enu_diff
|
|
9
|
+
from ..rtklib.pos import POS_COORD_COLS, POS_SD_COLS
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def interpolate(pos: pd.DataFrame, gps_s: np.ndarray) -> pd.DataFrame:
|
|
13
|
+
"""Linear interpolation of the trajectory at the given times.
|
|
14
|
+
|
|
15
|
+
Q is the worse of the two neighbouring epochs, ns the smaller. Times outside the
|
|
16
|
+
trajectory are not allowed.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
pos: Trajectory from `read_pos`, with at least two epochs.
|
|
20
|
+
gps_s: Times to interpolate at, seconds since the GPS epoch.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
DataFrame in the format of `pos`, one row per requested time.
|
|
24
|
+
"""
|
|
25
|
+
fmt = pos.attrs["format"]
|
|
26
|
+
t = pos["gps_s"].to_numpy()
|
|
27
|
+
idx = np.searchsorted(t, gps_s).clip(1, len(pos) - 1)
|
|
28
|
+
lo, hi = idx - 1, idx
|
|
29
|
+
q, ratio = pos["Q"].to_numpy(), pos["ratio"].to_numpy()
|
|
30
|
+
cols = POS_COORD_COLS[fmt] + POS_SD_COLS[fmt]
|
|
31
|
+
out = pd.DataFrame({c: np.interp(gps_s, t, pos[c]) for c in cols})
|
|
32
|
+
out["Q"] = np.maximum(q[lo], q[hi])
|
|
33
|
+
out["ns"] = np.minimum(pos["ns"].to_numpy()[lo], pos["ns"].to_numpy()[hi])
|
|
34
|
+
out["ratio"] = np.where(q[lo] == 1, ratio[lo], ratio[hi])
|
|
35
|
+
out["age"] = 0.0
|
|
36
|
+
out["gps_s"] = gps_s
|
|
37
|
+
out["t"] = GPS_EPOCH + pd.to_timedelta(gps_s, unit="s")
|
|
38
|
+
out.attrs["format"] = fmt
|
|
39
|
+
return out
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def average(
|
|
43
|
+
pos: pd.DataFrame, start: pd.Timestamp, end: pd.Timestamp, fix_only: bool = True
|
|
44
|
+
) -> dict[str, float | int | bool]:
|
|
45
|
+
"""Mean position of the llh epochs in [start, end] with the scatter in E, N, U.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
pos: llh trajectory from `read_pos`.
|
|
49
|
+
start: Window start, GPST.
|
|
50
|
+
end: Window end, GPST.
|
|
51
|
+
fix_only: Average the fixed epochs (Q == 1) only.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Dict with n_epochs, fix_pct, n_used and, if any epoch is used, fixed, lat, lon, h
|
|
55
|
+
[deg, deg, m] and sd_e, sd_n, sd_u [m] (sample standard deviations).
|
|
56
|
+
|
|
57
|
+
Raises:
|
|
58
|
+
ValueError: If `pos` is not in llh format.
|
|
59
|
+
"""
|
|
60
|
+
if pos.attrs.get("format") != "llh":
|
|
61
|
+
raise ValueError("average needs a llh trajectory (out-solformat=llh)")
|
|
62
|
+
seg = pos[(pos.t >= start) & (pos.t <= end)]
|
|
63
|
+
n_all = len(seg)
|
|
64
|
+
row: dict[str, float | int | bool] = {
|
|
65
|
+
"n_epochs": n_all,
|
|
66
|
+
"fix_pct": 100.0 * (seg.Q == 1).sum() / n_all if n_all else 0.0,
|
|
67
|
+
}
|
|
68
|
+
if fix_only:
|
|
69
|
+
seg = seg[seg.Q == 1]
|
|
70
|
+
row["n_used"] = len(seg)
|
|
71
|
+
if len(seg):
|
|
72
|
+
lat, lon, h = seg.lat.mean(), seg.lon.mean(), seg.h.mean()
|
|
73
|
+
e, n, u = enu_diff(seg.lat, seg.lon, seg.h, lat, lon, h).T
|
|
74
|
+
ddof = 1 if len(seg) > 1 else 0
|
|
75
|
+
row |= {
|
|
76
|
+
"fixed": bool((seg.Q == 1).all()),
|
|
77
|
+
"lat": lat,
|
|
78
|
+
"lon": lon,
|
|
79
|
+
"h": h,
|
|
80
|
+
"sd_e": e.std(ddof=ddof),
|
|
81
|
+
"sd_n": n.std(ddof=ddof),
|
|
82
|
+
"sd_u": u.std(ddof=ddof),
|
|
83
|
+
}
|
|
84
|
+
return row
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Precise Point Positioning (PPP) with RTKLIB. Placeholder: nothing is implemented yet.
|
|
2
|
+
|
|
3
|
+
Planned scope:
|
|
4
|
+
- single-receiver static and kinematic solutions with rnx2rtkp (`posmode` "ppp-static",
|
|
5
|
+
"ppp-kine" or "ppp-fixed"), reusing `gnsskit.rtklib` for configuration, running and
|
|
6
|
+
reading the .pos output;
|
|
7
|
+
- helpers for the precise products PPP needs: SP3 orbits, CLK clocks, ANTEX antenna
|
|
8
|
+
models (satellite and receiver), and optionally DCB/OSB biases and ocean loading;
|
|
9
|
+
- a PPP preset of `RtkConfig` (dual-frequency iono-free, `sateph="precise"`,
|
|
10
|
+
`tropopt="est-ztd"`).
|
|
11
|
+
|
|
12
|
+
To do before the first function:
|
|
13
|
+
- add "ppp-kine", "ppp-static" and "ppp-fixed" to `PosMode` in `gnsskit.rtklib.config`.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
__all__: list[str] = []
|
|
File without changes
|