1
0

Added pyrate as a direct dependency.

This commit is contained in:
2022-07-11 23:07:33 +02:00
parent 8c4532dad4
commit c99d517f6f
230 changed files with 21114 additions and 0 deletions

20
pyrate/doc/Makefile Normal file
View File

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?= -W --keep-going
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

35
pyrate/doc/make.bat Normal file
View File

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

View File

@ -0,0 +1,10 @@
Act
---
.. automodule:: pyrate.act
.. toctree::
:maxdepth: 2
:caption: Subpackages:
control/control

View File

@ -0,0 +1,8 @@
Anti windup LQR
---------------
.. automodule:: pyrate.act.control.anti_windup_lqr
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Anti windup PID
---------------
.. automodule:: pyrate.act.control.anti_windup_pid
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,13 @@
Control
-------
.. automodule:: pyrate.act.control
.. toctree::
:maxdepth: 2
:caption: Modules:
pid
anti_windup_pid
lqr
anti_windup_lqr

View File

@ -0,0 +1,8 @@
LQR
---
.. automodule:: pyrate.act.control.lqr
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
PID
---
.. automodule:: pyrate.act.control.pid
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,11 @@
Charts
------
The charts package enables users to read and write charts based on different file formats and databases.
.. toctree::
:maxdepth: 2
:caption: Modules:
database
s57_files

View File

@ -0,0 +1,7 @@
Database
--------
.. automodule:: pyrate.common.charts.db
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Raw Files
---------
.. automodule:: pyrate.common.charts.s57_files
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,13 @@
Common
------
.. automodule:: pyrate.common
.. toctree::
:maxdepth: 2
:caption: Subpackages:
charts/charts
math/math
raster_datasets/raster_datasets
testing/testing

View File

@ -0,0 +1,7 @@
Gaussian
--------
.. automodule:: pyrate.common.math.gaussian
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,10 @@
Math
----
The math package contains useful abstractions for common mathematical objects.
.. toctree::
:maxdepth: 2
:caption: Modules:
gaussian

View File

@ -0,0 +1,7 @@
Geographical Datasets
---------------------
.. automodule:: pyrate.common.raster_datasets.geo_datasets
:members:
:undoc-members:
:show-inheritance:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 KiB

View File

@ -0,0 +1,12 @@
Raster Datasets
---------------
.. automodule:: pyrate.common.raster_datasets
.. toctree::
:maxdepth: 2
:caption: Modules:
geo_datasets
transformer_base
transformers_concrete

View File

@ -0,0 +1,7 @@
Transformer Base Classes
------------------------
.. automodule:: pyrate.common.raster_datasets.transformer_base
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Concrete Transformers
---------------------
.. automodule:: pyrate.common.raster_datasets.transformers_concrete
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Dynamic System
--------------
.. automodule:: pyrate.common.testing.strategies.dynamic_system
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Geometry
--------
.. automodule:: pyrate.common.testing.strategies.geometry
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,11 @@
Strategies
----------
.. automodule:: pyrate.common.testing.strategies
.. toctree::
:maxdepth: 2
:caption: Modules:
dynamic_system
geometry

View File

@ -0,0 +1,13 @@
Testing
-------
.. automodule:: pyrate.common.testing
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 2
:caption: Modules:
strategies

122
pyrate/doc/source/conf.py Normal file
View File

@ -0,0 +1,122 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
from os.path import abspath
from os.path import dirname
from os.path import join
import sys
sys.path.insert(0, abspath(join(dirname(__file__), "../../"))) # for scripts/
import pyrate # noqa: E402
# -- Project information -----------------------------------------------------
project = "Pyrate"
copyright = pyrate.__author__
author = pyrate.__author__
# The version info for the project, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = pyrate.__version__.split("-")[0]
# The full version, including alpha/beta/rc tags
release = pyrate.__version__
# -- General configuration ---------------------------------------------------
primary_domain = "py"
# If this is True, todo and todolist produce output, else they produce nothing.
# The default is False.
todo_include_todos = True
language = "en"
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"sphinx_markdown_builder",
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.mathjax",
"sphinx.ext.viewcode",
"sphinx.ext.napoleon",
"sphinx.ext.autosummary",
"sphinx.ext.doctest",
"sphinx.ext.inheritance_diagram",
"sphinx_rtd_theme",
"sphinxcontrib.programoutput",
]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
source_suffix = [".rst"]
intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"shapely": ("https://shapely.readthedocs.io/en/stable", None),
"numpy": ("https://numpy.org/doc/stable", None),
"scipy": ("https://docs.scipy.org/doc/scipy", None),
"matplotlib": ("https://matplotlib.org/stable", None),
"pandas": ("https://pandas.pydata.org/pandas-docs/stable", None),
"h5py": ("https://docs.h5py.org/en/stable", None),
"tables": ("https://www.pytables.org", None),
"pyproj": ("https://pyproj4.github.io/pyproj/stable", None),
"rasterio": ("https://rasterio.readthedocs.io/en/stable", None),
"geopy": ("https://geopy.readthedocs.io/en/stable", None),
"cartopy": ("https://scitools.org.uk/cartopy/docs/latest", None),
"pytest": ("https://docs.pytest.org/en/stable", None),
"pytest-cov": ("https://pytest-cov.readthedocs.io/en/stable", None),
"hypothesis": ("https://hypothesis.readthedocs.io/en/latest", None),
}
nitpicky = False
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes or:
# - https://sphinx-themes.org/
# - https://www.writethedocs.org/guide/tools/sphinx-themes/
html_theme = "sphinx_rtd_theme"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = [] # '_static'
html_favicon = "../../resources/logo.svg"
html_logo = "../../resources/logo.svg"
html_sidebars = {"**": ["globaltoc.html", "relations.html", "sourcelink.html", "searchbox.html"]}
# -- Options for LaTeX output ---------------------------------------------
latex_engine = "pdflatex"
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
"papersize": "a4paper",
# The font size ('10pt', '11pt' or '12pt').
# 'pointsize': '10pt',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [("index", "pyrate.tex", f"{project} Documentation", author, "manual")]

View File

@ -0,0 +1,12 @@
Contribution
============
A long-term goal of this project is to provide a stable foundation of algorithms and data structures to enable a reliable and autonomous operation of a surface vehicle.
To achieve this goal, every addition or change to the software needs to be reviewed by the team and follow a set of rules as defined by our CI pipeline.
This obviously includes writing tests and documentation as needed.
To contribute to the project, feel free to create a new branch with a meaningful name and start your work from there.
If you feel that your work is ready to be merged into the master branch of the project, it is time to open a merge request.
If you are new to the Python programming language, you can find a good overview of Pythonic idioms `here <http://web.archive.org/web/20170316131252id_/http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html>`_.
We use `Google-style <https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html>`_ docstrings within the code and `Sphinx <https://www.sphinx-doc.org/en/master/>`_ to generate the documentation you are currently reading.

View File

@ -0,0 +1,30 @@
Welcome to Pyrate!
==================
This project offers algorithms targeted towards autonomous surface vehicles implemented in the Python 3.6+ programming language.
The functionality included in the Pyrate Python package enables the perception and processing of environmental features, planning of strategies and trajectories as well as action taking.
Pyrate is therefore divided into multiple distinct subpackages *sense*, *plan* and *act*, as well as the *common* package for additional features such as file I/O and mathematical abstractions.
The sense subpackage includes algorithms for computer vision, single and multi target state estimation, data smoothing and more.
In the plan subpackage, the perceived state of the agent and its environment is processed to compute trajectories for long- and short-term navigation as well as strategic decisions.
This also includes methods for gradient based and gradient free optimization methods are included.
Finally, the act subpackage contains state controllers to carry out planned behavior.
.. image:: ../../resources/project_structure.png
This project aims at providing the algorithmic backend for the ROS driven on-board systems and simulations.
Models of the robot's mechanics, electronics and its environment shall be developed within their own respective repository.
Furthermore technical specifications, maps and so on go into a separate project repository as well.
This ensures a clean separation of distinct requirements for quality assurance and responsibilities that distinguish these projects.
.. toctree::
:hidden:
installation
sense/sense
plan/plan
act/act
common/common
scripts/scripts
contribution
quality_assurance

View File

@ -0,0 +1,93 @@
Installation
============
This section leads you through the process of setting up your machine to be able to contribute and use the Pyrate package.
Creating a virtualenv
---------------------
.. note:: This step is not necessary but recommended
To encapsulate Pyrate, its specific dependencies and the rest of the STDA Python workspace, it can be a good decision to first set up a *virtualenv*.
A *virtualenv* behaves in a similar way yo the Python installation your distribution probably is already shipped with, but keeps all the installed packages in a separate space.
This way you do not run into incompatibilities if you participate in multiple projects at the same time.
A new *virtualenv* named *stda-env* is created with the following command within your current working directory.
.. code-block:: bash
python -m venv stda-env
To actually use this newly created environment, you need to activate the environment.
To do this you can switch into the project directory and execute :code:`source PathToEnvironment/stda-env/bin/activate`.
This causes your current shell to switch from the system wide Python installation to the *virtualenv*.
For ease of use, you can append one of the following lines to your `~/.bashrc`.
.. code-block:: bash
# Always activate the environment when a new shell is created
source PathToEnvironment/stda-env/bin/activate
# Create a new command that activates the environment by hand
alias activate-stda="source PathToEnvironment/stda-env/bin/activate"
To return from the virtualenv to using the system's Python interpreter, simply use the command :code:`deactivate`.
Setting up Pyrate
-----------------
To install Pyrate and its dependencies to your Linux-based Python 3.10+ environment, simply do the following.
Afterwards Pyrate's functionality will be available to you either globally or, if you followed the instructions above, with your *virtuelenv* activated.
.. code-block:: bash
# Dependencies that are not installed via pip
sudo add-apt-repository ppa:antiprism/ppa
sudo apt install python3-pip g++ python3-dev python3-gdal libgdal-dev libsqlite3-mod-spatialite antiprism
pip install wheel
# Clone the repository and change into the created directory
git clone git@gitlab.sailingteam.hg.tu-darmstadt.de:informatik/pyrate.git
cd pyrate
# To install, choose either option A (static) or B (editable)
# A: Install a static version of Pyrate
pip install .
# B: If you want to contribute to Pyrate, you need to install in editable mode
pip install -e .
You can check that everything worked by executing :code:`python3 -c "import pyrate"`.
If no :code:`ImportError` or alike pops up, the installation has succeeded.
Building the docs
-----------------
The documentation you are currently reading can easily be build for the locally installed branch using `Sphinx <https://www.sphinx-doc.org/>`__.
The most recent version from the ``master`` branch is also available `online <https://informatik.pages.sailingteam.hg.tu-darmstadt.de/pyrate/>`__.
Three formats are currently supported.
After you have built any of them with the below instructions, open these files to view the documentation:
- HTML (multiple linked pages): open ``doc/build/html/index.html`` in a web browser
- PDF (single document): open ``doc/build/latex/pyrate.pdf`` in a PDF viewer
- Markdown (multiple linked pages, limited functionality): open ``doc/build/markdown/index.md``
.. code-block:: bash
# install the extra Python dependencies
pip install .[docs]
# install the `dot` program to render inheritance diagrams (else they will appear as gibberish text)
sudo apt install graphviz
# change into the documentation directory
cd doc
# compile the docs into one or more of the below formats
make html
make latexpdf # requires pdflatex
make markdown
On Windows, `make.bat` can be used in place of `make` (untested, possibly requires installing additional dependencies).

View File

@ -0,0 +1,215 @@
Geometry
========
The geometry package provides a foundation for planning methods by implementing
several commonly used geometric objects, e.g. locations, polygons, and routes.
Each of them comes in a polar coordinates (i.e. latitude & longitude) and
cartesian coordinates (i.e. local x- & y-axis on a tangent plane) variant.
The cartesian ones are based on `Shapely <https://shapely.readthedocs.io/en/stable/project.html>`_
and the polar ones try to mimic their interface and functionality.
All coordinates are referenced to the widely used
`world geodetic system (WGS84) <https://de.wikipedia.org/wiki/World_Geodetic_System_1984>`__.
In this inheritance diagram, :class:`~shapely.BaseGeometry` as well as classes inheriting directly from it
are provided by *Shapely*.
It shows that all geometric objects of *Pyrate* inherit from :class:`~pyrate.plan.geometry.geospatial.Geospatial`:
.. inheritance-diagram::
pyrate.plan.geometry.location.CartesianLocation
pyrate.plan.geometry.location.PolarLocation
pyrate.plan.geometry.polygon.CartesianPolygon
pyrate.plan.geometry.polygon.PolarPolygon
pyrate.plan.geometry.route.CartesianRoute
pyrate.plan.geometry.route.PolarRoute
:parts: 1
:top-classes: pyrate.plan.geometry.geospatial.Geospatial
See :ref:`geometry-plotting` on how to easily plot geometries like points, polygons and routes.
See :ref:`design-decisions-local-projections` on how the implementation of the projections
between local and global coordinate systems has developed.
.. toctree::
:maxdepth: 2
:caption: Modules:
geospatial
location
polygon
route
helpers
.. _geometry-plotting:
Geometry Plotting
-----------------
There are many possibilities to visualize geometries with Python. For simplicity, we chose to not provide
direct visualization methods, but support `GeoJSON <https://geojson.org>`_. This format can be read very
easily by many programs, including the website `geojson.io <https://geojson.io>`_. You can simply
copy-paste it into there or use the convenient command-line tool `geojsonio <https://github.com/mapbox/geojsonio-cli>`_.
However, when objects become very large, other tools like `QGIS Desktop <https://www.qgis.org>`_ may be more appropriate.
The code below gives and example of how the
*GeoJSON* representation can be obtained. After that, a few interesting references are given.
Also, see :meth:`~pyrate.plan.geometry.geospatial.Geospatial.to_geo_json`.
.. code-block:: python
from geojson import dumps, Feature
from pyrate.plan.geometry import PolarPolygon
# create a geometry object
some_geometry = PolarPolygon(...)
# then simply dump it to standard out
print(some_geometry.to_geo_json())
# or more general
print(dumps(Feature(geometry=some_geometry)))
.. code-block:: bash
echo '{"type": "Point", "coordinates": [30, 10]}' | geojsonio
geojsonio some_gemetry.json
# see https://github.com/mapbox/geojsonio-cli#examples for more examples
This works for
- :class:`~pyrate.plan.geometry.location.PolarLocation`,
- :class:`~pyrate.plan.geometry.location.CartesianLocation`,
- :class:`~pyrate.plan.geometry.polygon.PolarPolygon`,
- :class:`~pyrate.plan.geometry.polygon.CartesianPolygon`,
- :class:`~pyrate.plan.geometry.route.PolarRoute`,
- :class:`~pyrate.plan.geometry.route.CartesianRoute`,
- and any object that provides a ``__geo_interface__`` attribute/property.
Further References
~~~~~~~~~~~~~~~~~~
- The original `Gitlab issue #54 <https://gitlab.sailingteam.hg.tu-darmstadt.de/informatik/pyrate/-/issues/54>`_ that collected initial ideas
- `Interaktive Visualisierung von Geodaten in Jupyter Notebooks (Lightning Talk, FOSSGIS 2017) <https://tib.flowcenter.de/mfc/medialink/3/de387967965b98c17bd5dd552ac86e899179084e8c1b5aa6d578f5ad72c5eea5ea/Interaktive_Visualisierung_von_Geodaten_in_Jupyter_Notebooks_Lightning_Talk_2.pdf>`_
- Examples in the *Folium* library: `Quickstart - GeoJSON/TopoJSON Overlays <https://python-visualization.github.io/folium/quickstart.html#GeoJSON/TopoJSON-Overlays>`_
.. _design-decisions-local-projections:
Design decisions on the local projections
-----------------------------------------
This section documents our arguments for and against `Universal Transverse Mercator (UTM) <https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system>`_ vs
`local tangent plane coordinates <https://en.wikipedia.org/wiki/Local_tangent_plane_coordinates>`_ based on freely chosen reference points,
as means of `horizontal position representation <https://en.wikipedia.org/wiki/Horizontal_position_representation>`_.
A third approach would be to provide both.
This discussion was copied and adapted from the `issue #40 <https://gitlab.sailingteam.hg.tu-darmstadt.de/informatik/pyrate/-/issues/40>`_, which initially collected this discussion.
Overview of the arguments
~~~~~~~~~~~~~~~~~~~~~~~~~
Firstly, the three approaches are presented with the arguments for using them.
Pro UTM
.......
1. A worldwide standard for navigation
2. Data easy to import/export to other teams/projects (can be important e.g. for the WRSC competition). However, WGS84 coordinates will probably suffice.
3. UTM locations can be pre-computed while arbitrary projections constantly change. Example from DB (pseudo-SQL): ``SELECT obstacle WHERE obstacle.zone IN {boat_zone, boat_zone + 1, boat_zone - 1, ...}``. Compared to *local* where the PolarLocation is transformed into local coordinates, distance computed and then decided whether to use or drop.
4. UTM errors are guaranteed to be +-1m per 1km within a single zone, see for reference e.g. `here <https://www.e-education.psu.edu/natureofgeoinfo/c2_p22.html>`_.
5. UTM makes tiling the map easy. This might help to choose which obstacles to include while planning. However, a single UTM zone is also quite large.
6. Slicing can be done once, offline.
Pro local
.........
1. Better precision around boat position/obstacles close to the boat. If we also use the Traverse Mercator projection like UTM, we might even get better resolution. However, this might come at some increased computational cost since it cannot be easily done offline/beforehand.
2. No tiling needed, select obstacles that are within a range of boat, and clip the non-relevant parts (already implemented in the *spatialite* database with polar coordinates)
3. Do special cases due to UTM zones not being entirely uniform
4. Could, in theory, allow for different projections for different needs (preserve the visual shape, preserve the area, etc.), though it might be too complicated and not worth the effort
5. Works exactly the same, no matter where on the globe something is
Pro for both and therefore neutral
..................................
1. Tested and documented packages for UTM (`utm <https://pypi.org/project/utm/>`_) and for arbitrary local transformations exist (`pyproj <https://pypi.org/project/pyproj/>`_)
2. Slicing Polygons provided by shapely (either ``island.intersect(Point(x, y).buffer(radius))`` or ``island.intersect(Polygon([(0, 0), (max, 0), (max, max), (0, max)]))``)
3. Both approaches would provide sufficiently precise approximations of the earth surface for our needs
About implementing both
.......................
1. Would have the best of both worlds
2. How would this complicate the implementation? (Too much, and it would spark discussions and incompatibilities.)
Decision
~~~~~~~~
In the end, the main argument against UTM zones was the handling of the cases near zone borders and that there are some irregularities in the UTM zones that might complicate things.
However, using local projections was feared to have a huge performance impact on embedded computes, so we performed a benchmark of a basic implementation.
The results when benchmarking in the scenario tested below confirmed that using local projections was feasible on our embedded computers.
Thus, the local transformation approach was selected.
.. _benchmarking-db-and-local-projections:
Benchmarking results of the custom local transformation approach
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The performance was initially tested on a *Raspberry Pi 4B* with 2GB RAM and a *SandDisk Extreme 64GB (Class 3)*.
A *Raspberry Pi* was chosen as it will likely be the actual computer being used in many challenges.
The OS was *Raspberry Pi OS (32-bit)* with version *May 2020* and the variant "with desktop and recommended software".
The overall performance was concluded to be very acceptable.
The benchmarking was performed with the chart database from the `data repository <https://gitlab.sailingteam.hg.tu-darmstadt.de/informatik/data>`__
on `commit 0abe9269026de87b7265f664d10a0b9599314313 <https://gitlab.sailingteam.hg.tu-darmstadt.de/informatik/data/-/commit/0abe9269026de87b7265f664d10a0b9599314313>`__.
It contained the entirety of North America as was available from the (US) NOAA.
The benchmark script (and *Pyrate* code) was from `commit 0ae4c33e361369321b10d677067deeb07ed27493 <https://gitlab.sailingteam.hg.tu-darmstadt.de/informatik/pyrate/-/commit/0ae4c33e361369321b10d677067deeb07ed27493>`__.
See :ref:`script-benchmark_db_and_projections` for details on what is actually tested.
The following tests were carried out on an Intel(R) Core(TM) i5-6300U with a SATA SSD and plenty of RAM.
Results with realistic parameters: radius 100km
...............................................
.. code-block:: bash
user@ubuntu:~/sailing/pyrate $ python scripts/benchmark_db_and_projections.py ../data/charts/noaa_vector/all_combined_simplified_25m.sqlite --iterations 10 --radius 100
Information on the setting:
number of rows/polygons in database: 648828
sum of vertices of all rows/polygons of in database: 13727653
extracted number of polygons: 6266
extracted total number of vertices: 120179
Executed "query_database" 10 times:
average: 2.977373 seconds
std dev: 0.042802 seconds
variance: 0.001832 seconds
Executed "project_to_cartesian_and_back" 10 times:
average: 1.465923 seconds
std dev: 0.033850 seconds
variance: 0.001146 seconds
Results with stress testing parameters: radius 999km
....................................................
.. code-block:: bash
user@ubuntu:~/sailing/pyrate $ python scripts/benchmark_db_and_projections.py ../data/charts/noaa_vector/all_combined_simplified_25m.sqlite --iterations 10 --radius 999
Information on the setting:
number of rows/polygons in database: 648828
sum of vertices of all rows/polygons of in database: 13727653
extracted number of polygons: 90539
extracted total number of vertices: 2131078
Executed "query_database" 10 times:
average: 34.120787 seconds
std dev: 0.499919 seconds
variance: 0.249919 seconds
Executed "project_to_cartesian_and_back" 10 times:
average: 23.383787 seconds
std dev: 0.224816 seconds
variance: 0.050542 seconds
Notes and conclusions
.....................
Comparing the results with radius 100km and 999km, we can see that ``_project_to_cartesian_and_back()`` grows very linearly, as expected: 12 μs/vertex (100km) vs. 11 μs/vertex (999km).
The ``_query_database()`` benchmark runs even better (sub linear in the number of vertices): 24 μs/vertex (100km) vs. 16 μs/vertex (999km).
Also note, that having a lot of polygons outside of the relevant area seems to be non-problematic.
Here, the spatial index really shines, as ``_query_database()`` took *a lot* longer before its introduction.
About 66% of the time when projecting is spent reassembling the polygon after it was converted, so that's probably something we can improve if we eventually need to.
Also, one could reduce the fidelity of the features by using stronger simplification or reduce the query radius.
Memory seems to not be a problem either. No precise measurements were made though.

View File

@ -0,0 +1,7 @@
Geospatial
----------
.. automodule:: pyrate.plan.geometry.geospatial
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Geometry Helpers
----------------
.. automodule:: pyrate.plan.geometry.helpers
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Location
--------
.. automodule:: pyrate.plan.geometry.location
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Polygon
-------
.. automodule:: pyrate.plan.geometry.polygon
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Route
-----
.. automodule:: pyrate.plan.geometry.route
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Earth Graph Generation
----------------------
.. automodule:: pyrate.plan.graph.generate
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Geo-referenced Graph Implementation
-----------------------------------
.. automodule:: pyrate.plan.graph.geo_graph
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Graph Implementation
--------------------
.. automodule:: pyrate.plan.graph.graph
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,16 @@
Graph
=====
.. automodule:: pyrate.plan.graph
.. inheritance-diagram:: pyrate.plan.graph.graph.NavigationGraph pyrate.plan.graph.geo_graph.GeoNavigationGraph
:parts: 1
:top-classes: pyrate.plan.graph.graph.NavigationGraph
.. toctree::
:maxdepth: 2
:caption: Modules:
graph
geo_graph
generate

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

View File

@ -0,0 +1,11 @@
Plan
----
.. automodule:: pyrate.plan
.. toctree::
:maxdepth: 2
:caption: Subpackages:
geometry/geometry
graph/graph_overview

View File

@ -0,0 +1,62 @@
Quality Assurance
=================
This section shows you how to test the software locally on your machine and ensure that your contributions follow our common coding standards.
Note that with every contribution pushed to the Gitlab server the routines that are described here are automatically executed for you.
The results are then visible in `the repository's CI/CD section <https://gitlab.sailingteam.hg.tu-darmstadt.de/informatik/pyrate/-/pipelines>`__ and in the specific merge request view.
`The Software section of the Wiki <https://gitlab.sailingteam.hg.tu-darmstadt.de/team/wiki/-/wikis/Software/Home%20%F0%9F%92%BB>`__ also holds further information on our `styleguide <https://gitlab.sailingteam.hg.tu-darmstadt.de/team/wiki/-/wikis/Software/Quality-Assurance/Styleguide>`__, `documentation <https://gitlab.sailingteam.hg.tu-darmstadt.de/team/wiki/-/wikis/Software/Quality-Assurance/Documentation>`__ and `testing <https://gitlab.sailingteam.hg.tu-darmstadt.de/team/wiki/-/wikis/Software/Quality-Assurance/Testing>`__.
Coding Style
------------
A common style when collaborating on a big project is crucial to keep everything maintainable and easy to understand in the long run.
To make sure you are following the rules we employ a number of programs that help us to analyse the source automatically.
Since Python is an interpreted language, we do not have a compiler that ensures that everything we write will make sense at runtime.
Linting and enforcing coding conventions thereby can have a very important role in keeping our software reliable.
To get reports on the code you have written you can use the following commands in the packages root directory.
.. code-block:: bash
flake8
mypy pyrate tests scripts
pylint -j 0 pyrate tests scripts
Testing
-------
Tests can be run by simply executing :code:`pytest` within the repositories root directory.
This will also result in coverage statistics being printed, which are a good indicator whether your tests are covering all the lines of your code.
Again, since Python is not compiled, this can be very useful.
Nevertheless, make sure that your tests ideally go beyond mere execution of code and assert its correctness.
Besides statement coverage, we also collect branch coverage (see `here <https://coverage.readthedocs.io/en/stable/branch.html>`__).
We require that all contributions achieve 100% statement coverage and 90% branch coverage.
Two parts of the library are special when it comes to testing:
Both the tests around :code:`pyrate.common.charts.SpatialiteDatabase` and around :code:`pyrate.common.charts.S57ChartHandler` are only exercised if the required dependencies are met and if not running on a CI server.
If the dependencies cannot be found, the tests will be marked as skipped.
This allows for easier development as less dependencies are actually required for running the tests, but the CI server will still check these modules for you.
Hypothesis Testing and Speed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Many tests use the `Hypothesis property based testing framework <https://hypothesis.readthedocs.io/en/latest/>`__.
Everyone is encouraged to do so too, and there are already some handy example generators in ``tests/strategies/``.
The settings (along with some more general setup) are declared in ``tests/__init__.py``.
However, a few tests take a lot of time to process, like for example the tests that use the very slow cartesian route example generation.
Therefore, it might be required to reduce the number of tests, as is done in ``tests/plan/geometry/primitives/test_polygons.py`` using the ``@settings()`` decorator.
Timings for (all) individual tests can be obtained by running pytest with ``--durations=0`` (see `the pytest docs <https://docs.pytest.org/en/stable/usage.html#profiling-test-execution-duration>`__).
You may want to temporarily add this argument to the ``addopts`` option in the section ``[tool.pytest.ini_options]`` in ``pyproject.toml``.
Downstream CI Pipeline Triggers
-------------------------------
Other projects like *ros-nodes* depend on *Pyrate*: They are *downstream* projects, as changes in *Pyrate* flow down the "stream of dependencies" to them.
To ensure that changes here in the upstream *Pyrate* project do not break such downstream projects (or just to remind us to fix stuff over there too),
the pipeline of this repository triggers the ones of downstream projects.
This is configured in a special ``Deploy``-stage job called ``Trigger Downstream Pipelines`` at the bottom of the ``.gitlab-ci.yml`` file (in this upstream project!).
The capabilities are documented in `the official GitLab docs on "Multi-project pipelines" <https://docs.gitlab.com/ee/ci/multi_project_pipelines.html>`__.

View File

@ -0,0 +1,52 @@
.. _scripts-reference:
API Reference
-------------
``s57_charts_to_db.py``
~~~~~~~~~~~~~~~~~~~~~~~
.. automodule:: scripts.s57_charts_to_db
:members:
:undoc-members:
``benchmark_db_and_projections.py``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. automodule:: scripts.benchmark_db_and_projections
:members:
:undoc-members:
``create_earth_graph.py``
~~~~~~~~~~~~~~~~~~~~~~~~~
.. automodule:: scripts.create_earth_graph
:members:
:undoc-members:
``earth_graph_frequency_statistics.py``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. automodule:: scripts.earth_graph_frequency_statistics
:members:
:undoc-members:
``visualize_earth_graph.py``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. automodule:: scripts.visualize_earth_graph
:members:
:undoc-members:
``benchmark_graph_neighbor_search.py``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. automodule:: scripts.benchmark_graph_neighbor_search
:members:
:undoc-members:

View File

@ -0,0 +1,81 @@
Scripts
=======
*Pyrate* contains a few scripts in the directory `pyrate/scripts/`.
They are mainly meant for actually applying the algorithms to real-world data and to also serve as some examples for the library code.
Requirements
------------
Most script documentation assumes the typical Sailing Team directory layout as described in
`the installation guide <https://gitlab.sailingteam.hg.tu-darmstadt.de/informatik/pyrate/-/wikis/Installation>`_.
To execute these programs, you need the datasets that you want to work with (if any).
Therefore, you will probably want to download the data repository as described
`here <https://gitlab.sailingteam.hg.tu-darmstadt.de/informatik/data/-/blob/master/README.md#installation>`_,
if you haven't already.
Usage
-----
This section just lists the parameters of the scrips. See :ref:`scripts-reference` for more complete explanations.
.. _script-s57_charts_to_db:
``s57_charts_to_db.py``
~~~~~~~~~~~~~~~~~~~~~~~
.. command-output:: ../../scripts/s57_charts_to_db.py --help
.. _script-benchmark_db_and_projections:
``benchmark_db_and_projections.py``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. command-output:: ../../scripts/benchmark_db_and_projections.py --help
.. _script-create_earth_graph:
``create_earth_graph.py``
~~~~~~~~~~~~~~~~~~~~~~~~~
.. command-output:: ../../scripts/create_earth_graph.py --help
.. _script-earth_graph_frequency_statistics:
``earth_graph_frequency_statistics.py``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. command-output:: ../../scripts/earth_graph_frequency_statistics.py --help
.. _script-visualize_earth_graph:
``visualize_earth_graph.py``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. command-output:: ../../scripts/visualize_earth_graph.py --help
.. _script-benchmark_graph_neighbor_search:
``benchmark_graph_neighbor_search.py``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. command-output:: ../../scripts/benchmark_graph_neighbor_search.py --help
Reference
---------
This section above just lists the usage of the scrips.
The complete API reference can be found below:
.. toctree::
:maxdepth: 2
reference

View File

@ -0,0 +1,7 @@
Extended Kalman Filter
----------------------
.. automodule:: pyrate.sense.filters.extended
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Extended Gaussian Mixture PHD Filter
------------------------------------
.. automodule:: pyrate.sense.filters.extended_gmphd
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,16 @@
Filters
-------
The filters package provides single and multi target tracking capabilities based on Bayesian methods.
A prime example for such a filter is the so called Kalman filter and its derivatives for nonlinear estimation.
Additionally, the gaussian mixture probability hypothesis density (PHD) filter is provided.
.. toctree::
:maxdepth: 2
:caption: Modules:
kalman
extended
unscented
gmphd
extended_gmphd

View File

@ -0,0 +1,7 @@
Gaussian Mixture PHD Filter
---------------------------
.. automodule:: pyrate.sense.filters.gmphd
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Kalman Filter
-------------
.. automodule:: pyrate.sense.filters.kalman
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
Unscented Kalman Filter
-----------------------
.. automodule:: pyrate.sense.filters.unscented
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,9 @@
Sense
-----
.. toctree::
:maxdepth: 2
:caption: Subpackages:
filters/filters
smoothers/smoothers

View File

@ -0,0 +1,7 @@
Extended RTS Smoother
---------------------
.. automodule:: pyrate.sense.smoothers.extended
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,7 @@
RTS Smoother
------------
.. automodule:: pyrate.sense.smoothers.rts
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,13 @@
Smoothers
---------
Smoothing is the problem of state estimation, where not only previous measurements but also future observations are part of a single estimate.
A popular example for smoothing is the so called Rauch-Tung-Striebel (RTS) smoother, which is based on the Kalman filter and its derivatives for nonlinear estimation.
.. toctree::
:maxdepth: 2
:caption: Modules:
rts
extended
unscented

View File

@ -0,0 +1,7 @@
Unscented RTS Smoother
----------------------
.. automodule:: pyrate.sense.smoothers.unscented
:members:
:undoc-members:
:show-inheritance: