This software package provides an implementation of a harmonic transformation that maps any compact, multiply connected planar domain onto the unit disk; each of the holes that the original domain may have are collapsed onto distinct points inside its image.
This transformation has been employed for addressing the navigation problem of a single planar robot operating in arbitrarily shaped workspaces in 1.1, 1.2.
If you end up using this transformation and/or this software package, please cite the aforementioned paper as follows:
P. Vlantis, C. Vrohidis, C. P. Bechlioulis and K. J. Kyriakopoulos, "Robot Navigation in Complex Workspaces Using Harmonic Maps," 2018 IEEE International Conference on Robotics and Automation (ICRA), 2018, pp. 1726-1731, doi: 10.1109/ICRA.2018.8460695.
In general, this package provides the following two distinct outputs:
- a shared library implemented in C++,
- a python wrapper of the aforementioned library.
All these outputs depend on the following libraries, which must be installed on the system in order to build them:
The recommended ways to build each of these outputs are described in the following subsections.
In order to build the shared library from the contained C++ source code using CMake, execute the following steps:
-
Create sub-directory
build/cpp/
inside this package's root directory. -
Inside
build/cpp
, execute the following shell command:cmake -DCMAKE_INSTALL_PREFIX=prefix ../.. && make && make install
where
prefix
is a placeholder for the path to the directory where the library and C++ headers will be installed at (defaults to/usr/local/
on GNU/Linux systems).
After executing these steps, the library and header files should be installed as follows:
prefix/
├── include
│ └── hntf2d
│ └── ...
└── lib
└── libhntf2d.so
A python wrapper for the C++ implementation is also provided using Cython.
In order to build the python wrapper, the following procedure should be executed:
-
Download a customized version of the software package eigency located at 2.4 by executing the following shell command inside this package's root directory:
git submodule update --init --remote --recursive
-
Install the following dependencies:
numpy
cython
This can be done by executing the following shell commands:
python3 -m pip install cython numpy
-
Build and install
eigency
. This can be done by executing the following shell command inside the directorycy/eigency
:python3 setup.py build_ext --inplace python3 setup.py install
-
Finally, build and install the wrapper. This can be done by executing the following shell command inside the root directory (ignore errors reported by the first command about not finding the shared library):
python3 setup.py build_ext --inplace python3 setup.py install
After completing the aforementioned procedure, the usability of this package can be tested by executing the following shell command:
python3 examples/cy/box.py
A version of the C++ library has been compiled with Matlab 2018a 64bit into Mex files, which have been packed and are available for download from this repository's releases.
import hntf2d.map
import hntf2d.utils
import numpy
hm = hntf2d.map.HarmonicMap2D()
# XXX: All boundaries must be closed curves
# Add a box-shaped outer boundary:
# XXX: Outer boundary must be counter-clock-wise oriented.
t = numpy.linspace(-1., +1., 101)[:100]
outer_boundary = numpy.zeros((400, 2))
# Outer boundary: line segment ((-1, -1) -> (1, -1))
outer_boundary[:100, 0] = t[:]
outer_boundary[:100, 1] = -1
# Outer boundary: line segment ((1, -1) -> (1, 1))
outer_boundary[100:200, 0] = 1
outer_boundary[100:200, 1] = t[:]
# Outer boundary: line segment ((1, 1) -> (-1, 1))
outer_boundary[200:300, 0] = t[::-1]
outer_boundary[200:300, 1] = 1
# Outer boundary: line segment ((-1, 1) -> (-1, -1))
outer_boundary[300:400, 0] = -1
outer_boundary[300:400, 1] = t[::-1]
# Outer boundary: first and last vertices must be equal
outer_boundary[-1, :] = outer_boundary[0, :]
hm.boundary_append(outer_boundary)
# Add a box-shaped inner boundary:
# XXX: Inner boundaries must be clock-wise oriented.
t = numpy.linspace(-1., +1., 21)[:20]
inner_boundary = numpy.zeros((80, 2))
# Inner boundary: line segment ((-0.1, -0.1) -> (-0.1, 0.1))
inner_boundary[:20, 0] = -0.1
inner_boundary[:20, 1] = t[:]
# Outer boundary: line segment ((-0.1, 0.1) -> (0.1, 0.1))
inner_boundary[20:40, 0] = t[:]
inner_boundary[20:40, 1] = 0.1
# Outer boundary: line segment ((0.1, 0.1) -> (0.1, -0.1))
inner_boundary[40:60, 0] = 0.1
inner_boundary[40:60, 1] = t[::-1]
# Outer boundary: line segment ((0.1, -0.1) -> (-0.1, -0.1))
inner_boundary[60:80, 0] = t[::-1]
inner_boundary[60:80, 1] = -0.1
# Outer boundary: first and last vertices must be equal
inner_boundary[-1, :] = inner_boundary[0, :]
hm.boundary_append(inner_boundary)
# Print the registered boundaries (1st it the outer, followed by inner ones).
hm.print_boundaries()
# Map the center of each segment belonging to the outer boundary to
# the unit circle:
uo, vo = hntf2d.utils.poly2circle(outer_boundary).T
hm.solve(uo, vo)
print(hm.map(0., 0.5))
print(hm.jacob(0., 0.5))
In order to develop this package in a Guix shell with all the necessary dependencies, the following manifest file can be used.
(use-modules (gnu packages)
(guix packages)
((gnu packages cmake) :prefix gnu:)
((gnu packages llvm) :prefix gnu:)
((gnu packages algebra) :prefix gnu:)
((gnu packages python) :prefix gnu:)
((gnu packages python-xyz) :prefix gnu:)
((gnu packages xml) :prefix gnu:))
(packages->manifest (list gnu:cmake
gnu:clang
gnu:python-scikit-build
gnu:eigen
gnu:tinyxml2
gnu:python
gnu:python-cython
gnu:python-numpy
gnu:python-setuptools-scm))
guix shell -m manifest.scm
- Papers:
- Software Packages: