Skip to content

Commit

Permalink
enable lanelet2 python3 binding (#1)
Browse files Browse the repository at this point in the history
* delete meta-package and add puginxml cmake module

* add python package files

* make it work with python3

* get setup.py working

* clean up

* clean up

* minor update

* update dependencies

* track the original readme

* update

* ~_~ add the missing setup ignored by the original .gitignore file

* add pip3 and setuptools install command

* update

* fix import error

* more robust import

* add needed package and cmake module

* update readme

* minor update

* ignore generated files

* fix linking issue
  • Loading branch information
yuzhangbit authored Jan 14, 2019
1 parent 0c44805 commit 164f4f1
Show file tree
Hide file tree
Showing 16 changed files with 335 additions and 82 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
*.pyc
setup.py
CMakeLists.txt.user

dist/
build/
lanelet2.egg-info/
74 changes: 74 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
cmake_minimum_required(VERSION 3.5.1)
project(lanelet2)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-backtrace-limit=0")
# by setting this, we don't need to install the generated c++ library to /usr/local
# LINKED_LIBRARIES will be installed by side with the python api binding libraries
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

find_package(Boost REQUIRED COMPONENTS python-py35 serialization system filesystem)
find_package(PythonLibs 3.5 REQUIRED) # sets ${PYTHON_INCLUDE_DIRS}
find_package(Eigen3 QUIET)
if(NOT EIGEN3_FOUND)
find_package(PkgConfig REQUIRED)
pkg_check_modules(EIGEN3 REQUIRED eigen3)
set(EIGEN3_INCLUDE_DIR ${EIGEN3_INCLUDE_DIRS})
endif()
find_package(GeographicLib REQUIRED)
find_package(PugiXML REQUIRED)

include_directories(
lanelet2_core/include
lanelet2_io/include
lanelet2_projection/include
lanelet2_routing/include
lanelet2_traffic_rules/include
${Boost_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIR}
${GeographicLib_INCLUDE_DIRS}
${PugiXML_INCLUDE_DIRS}
)

set(MODUELS core io projection routing traffic_rules geometry)

set(LINKED_LIBRARIES "")
# build the c++ libraries first
foreach(SUBMODULE ${MODUELS})
if (NOT SUBMODULE STREQUAL "geometry")
set(LIBRARY_NAME ${PROJECT_NAME}_${SUBMODULE})
set(SRCS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}_${SUBMODULE}/src)
file(GLOB ${SUBMODULE}_SRC ${SRCS_DIR}/*.cpp)
add_library(${LIBRARY_NAME} SHARED
${${SUBMODULE}_SRC}
)
target_include_directories(${LIBRARY_NAME}
PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}_${SUBMODULE}/include/${PROJECT_NAME}_${SUBMODULE}>)
target_link_libraries(${LIBRARY_NAME}
${Boost_LIBRARIES}
${PYTHON_LIBRARY}
${GeographicLib_LIBRARIES}
${PugiXML_LIBRARIES}
)
list(APPEND LINKED_LIBRARIES ${LIBRARY_NAME})
endif()
endforeach()


# build each python api binding submodule
foreach(SUBMODULE ${MODUELS})
set(API_LIBRARY_NAME "${PROJECT_NAME}_${SUBMODULE}_pyapi")
add_library(${API_LIBRARY_NAME} SHARED
lanelet2_python/python_api/${SUBMODULE}.cpp # binding codes
)
target_compile_definitions(${API_LIBRARY_NAME} PRIVATE -DPYTHON_API_MODULE_NAME=lib${API_LIBRARY_NAME})
#target_compile_options(${API_LIBRARY_NAME} PRIVATE -Wl,-rpath='$ORIGIN')
target_link_libraries(${API_LIBRARY_NAME}
${Boost_LIBRARIES}
${PYTHON_LIBRARY}
${LINKED_LIBRARIES}
)
endforeach()
127 changes: 51 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,96 +1,71 @@
# Lanelet2

![build](https://www.mrt.kit.edu/z/gitlab/lanelet2/pipeline.svg) ![coverage](https://www.mrt.kit.edu/z/gitlab/lanelet2/coverage.svg)
# lanelet2_standalone

## Overview

Lanelet2 is a C++ library for handling map data in the context of automated driving. It is designed to utilize high-definition map data in order to efficiently handle the challenges posed to a vehicle in complex traffic scenarios. Flexibility and extensibility are some of the core principles to handle the upcoming challenges of future maps.

Features:
- **2D and 3D** support
- **Consistent modification**: if one point is modified, all owning objects see the change
- Supports **lane changes**, routing through areas, etc.
- **Separated routing** for pedestrians, vehicles, bikes, etc.
- Many **customization points** to add new traffic rules, routing costs, parsers, etc.
- **Simple convenience functions** for common tasks when handling maps
- **Accurate Projection** between the lat/lon geographic world and local metric coordinates
- **IO Interface** for reading and writing e.g. _osm_ data formats
- **Python2** bindings for the whole C++ interface
- **Boost Geometry** support for all thinkable kinds of geometry calculations on map primitives
- Released under the [**BSD 3-Clause license**](LICENSE)

![](lanelet2_core/doc/images/lanelet2_example_image.png)

Lanelet2 is the successor of the old [liblanelet](https://github.com/phbender/liblanelet/tree/master/libLanelet) that was developed in 2013. If you know Lanelet1, you might be interested in [reading this](lanelet2_core/doc/Lanelet1Compability.md).

## Documentation

You can find more documentation in the individual packages and in doxygen comments. Here is an overview on the most important topics:
- [Here](lanelet2_core/doc/LaneletPrimitives.md) is more information on the basic primitives that make up a Lanelet2 map.
- [Read here](lanelet2_core/doc/Architecture.md) for a primer on the **software architecture** of lanelet2.
- There is also some [documentation](lanelet2_core/doc/GeometryPrimer.md) on the geometry calculations you can do with lanelet2 primitives.
- If you are interested in Lanelet2's **projections**, you will find more [here](lanelet2_projection/doc/Map_Projections_Coordinate_Systems.md).
- To get more information on how to create valid maps, see [here](lanelet2_maps/README.md).
This is a standalone lanelet2 **python3** package for the [Lanelet2](https://github.com/fzi-forschungszentrum-informatik/Lanelet2) library, which **does not** require the ROS and catkin.

## Installation
Lanelet2 uses [Catkin](https://catkin-tools.readthedocs.io/en/latest/index.html) for building and is targeted towards Linux.
pylanelet2 uses cmake and setuptools for building and packaging and is targeted towards Linux.

At least C++14 is required.

### Tested Configuration
* `Ubuntu 16.04 LTS`
* `python3.5`

### Dependencies
* `Boost` (from 1.58)
* `Boost` (from 1.58, for lanelet2_io)
* `eigen3`
* [`mrt_cmake_modules`](https://github.com/KIT-MRT/mrt_cmake_modules), a CMake helper library
* `pugixml` (for lanelet2_io)
* `boost-python/python2` (for lanelet2_python)
* `boost-python/python3`
* `geographiclib` (for lanelet2_projection)

For Ubuntu (assuming you the ROS package repository [installed](http://wiki.ros.org/ROS/Installation)):
For Ubuntu:
```shell
sudo apt-get install libboost-dev libeigen3-dev libgeographic-dev libpugixml-dev libpython-dev libboost-python-dev python-catkin-tools
sudo apt-get install -y cmake libboost-all-dev libeigen3-dev libgeographic-dev libpugixml-dev libpython-dev libboost-python-dev libpython3-all-dev python3-pip python3-setuptools
```

### Building
As usual with Catkin, you have to crate a workspace and clone all required packages there. Then you can build:
### Installing
In the repo root folder,
```shell
mkdir catkin_ws && cd catkin_ws && mkdir src
catkin init
cd src
git clone https://github.com/KIT-MRT/mrt_cmake_modules.git
git clone https://github.com/fzi-forschungszentrum-informatik/lanelet2.git
cd ..
catkin build
sudo python3 setup.py install
```

## Examples
Examples and common use cases in both C++ and Python can be found [here](lanelet2_examples/README.md).

## Packages
* **lanelet2** is the meta-package for the whole lanelet2 framework
* **lanelet2_core** implements the basic library with all the primitives, geometry calculations and the LanletMap object
* **lanelet2_io** is responsible for reading and writing lanelet maps
* **lanelet2_traffic_rules** provides support to interpret the traffic rules encoded in a map
* **lanelet2_projection** for projecting maps from WGS84 (lat/lon) to local metric coordinates
* **lanelet2_routing** implements the routing graph for routing or reachable set or queries as well as collision checking
* **lanelet2_maps** provides example maps and functionality to visualize and modify them easily in JOSM
* **lanelet2_python** implements the python interface for lanelet2
* **lanelet2_validation** provides checks to ensure a valid lanelet2 map
* **lanelet2_examples** contains tutorials for working with Lanelet2 in C++ and Python

## Citation

If you are using Lanelet2 for scientific research, we would be pleased if you would cite our [publication](http://www.mrt.kit.edu/z/publ/download/2018/Poggenhans2018Lanelet2.pdf):
```latex
@inproceedings{poggenhans2018lanelet2,
title = {Lanelet2: A High-Definition Map Framework for the Future of Automated Driving},
author = {Poggenhans, Fabian and Pauls, Jan-Hendrik and Janosovits, Johannes and Orf, Stefan and Naumann, Maximilian and Kuhnt, Florian and Mayr, Matthias},
booktitle = {Proc.\ IEEE Intell.\ Trans.\ Syst.\ Conf.},
year = {2018},
address = {Hawaii, USA},
owner = {poggenhans},
month = {November},
Url={http://www.mrt.kit.edu/z/publ/download/2018/Poggenhans2018Lanelet2.pdf}
}
or
```bash
/path/to/your/python3 setup.py install
```

## Usage
### Example
```python
#!/usr/bin/env python
import lanelet2
from lanelet2 import core, io, projection, geometry, routing, traffic_rules
# or
from lanelet2.core import Lanelet, LineString3d, Point2d, Point3d, getId, LaneletMap, BoundingBox2d, BasicPoint2d
p = Point3d(getId(), 1, 100, 1000)
print(p)
assert p.x == 0
p.id = getId()
```

**Note:
Importing submodules from the raw `liblanelet2_core_pyapi.so` library like below is not supported.**
If you do this,
```python
from lanelet2.liblanelet2_core_pyapi import AttributeMap # not supported!!!
```
you will get an error as below:
```
>>> from lanelet2.liblanelet2_core_pyapi import AttributeMap
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'lanelet2.liblanelet2_core_pyapi'
```
Instead, you can use
```python
from lanelet2 import core
# use core.AttributeMap
# or
from lanelet2.core import AttributeMap
```
, which is more elegant.
94 changes: 94 additions & 0 deletions README.md.origin
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Lanelet2

![build](https://www.mrt.kit.edu/z/gitlab/lanelet2/pipeline.svg) ![coverage](https://www.mrt.kit.edu/z/gitlab/lanelet2/coverage.svg)

## Overview

Lanelet2 is a C++ library for handling map data in the context of automated driving. It is designed to utilize high-definition map data in order to efficiently handle the challenges posed to a vehicle in complex traffic scenarios. Flexibility and extensibility are some of the core principles to handle the upcoming challenges of future maps.

Features:
- **2D and 3D** support
- **Consistent modification**: if one point is modified, all owning objects see the change
- Supports **lane changes**, routing through areas, etc.
- **Separated routing** for pedestrians, vehicles, bikes, etc.
- Many **customization points** to add new traffic rules, routing costs, parsers, etc.
- **Simple convenience functions** for common tasks when handling maps
- **Accurate Projection** between the lat/lon geographic world and local metric coordinates
- **IO Interface** for reading and writing e.g. _osm_ data formats
- **Python2** bindings for the whole C++ interface
- **Boost Geometry** support for all thinkable kinds of geometry calculations on map primitives
- Released under the [**BSD 3-Clause license**](LICENSE)

![](lanelet2_core/doc/images/lanelet2_example_image.png)

Lanelet2 is the successor of the old [liblanelet](https://github.com/phbender/liblanelet/tree/master/libLanelet) that was developed in 2013. If you know Lanelet1, you might be interested in [reading this](lanelet2_core/doc/Lanelet1Compability.md).

## Documentation

You can find more documentation in the individual packages and in doxygen comments. Here is an overview on the most important topics:
- [Here](lanelet2_core/doc/LaneletPrimitives.md) is more information on the basic primitives that make up a Lanelet2 map.
- [Read here](lanelet2_core/doc/Architecture.md) for a primer on the **software architecture** of lanelet2.
- There is also some [documentation](lanelet2_core/doc/GeometryPrimer.md) on the geometry calculations you can do with lanelet2 primitives.
- If you are interested in Lanelet2's **projections**, you will find more [here](lanelet2_projection/doc/Map_Projections_Coordinate_Systems.md).
- To get more information on how to create valid maps, see [here](lanelet2_maps/README.md).

## Installation
Lanelet2 uses [Catkin](https://catkin-tools.readthedocs.io/en/latest/index.html) for building and is targeted towards Linux.

At least C++14 is required.

### Dependencies
* `Boost` (from 1.58)
* `eigen3`
* [`mrt_cmake_modules`](https://github.com/KIT-MRT/mrt_cmake_modules), a CMake helper library
* `pugixml` (for lanelet2_io)
* `boost-python/python2` (for lanelet2_python)
* `geographiclib` (for lanelet2_projection)

For Ubuntu (assuming you the ROS package repository [installed](http://wiki.ros.org/ROS/Installation)):
```shell
sudo apt-get install libboost-dev libeigen3-dev libgeographic-dev libpugixml-dev libpython-dev libboost-python-dev python-catkin-tools
```

### Building
As usual with Catkin, you have to crate a workspace and clone all required packages there. Then you can build:
```shell
mkdir catkin_ws && cd catkin_ws && mkdir src
catkin init
cd src
git clone https://github.com/KIT-MRT/mrt_cmake_modules.git
git clone https://github.com/fzi-forschungszentrum-informatik/lanelet2.git
cd ..
catkin build
```

## Examples
Examples and common use cases in both C++ and Python can be found [here](lanelet2_examples/README.md).

## Packages
* **lanelet2** is the meta-package for the whole lanelet2 framework
* **lanelet2_core** implements the basic library with all the primitives, geometry calculations and the LanletMap object
* **lanelet2_io** is responsible for reading and writing lanelet maps
* **lanelet2_traffic_rules** provides support to interpret the traffic rules encoded in a map
* **lanelet2_projection** for projecting maps from WGS84 (lat/lon) to local metric coordinates
* **lanelet2_routing** implements the routing graph for routing or reachable set or queries as well as collision checking
* **lanelet2_maps** provides example maps and functionality to visualize and modify them easily in JOSM
* **lanelet2_python** implements the python interface for lanelet2
* **lanelet2_validation** provides checks to ensure a valid lanelet2 map
* **lanelet2_examples** contains tutorials for working with Lanelet2 in C++ and Python

## Citation

If you are using Lanelet2 for scientific research, we would be pleased if you would cite our [publication](http://www.mrt.kit.edu/z/publ/download/2018/Poggenhans2018Lanelet2.pdf):
```latex
@inproceedings{poggenhans2018lanelet2,
title = {Lanelet2: A High-Definition Map Framework for the Future of Automated Driving},
author = {Poggenhans, Fabian and Pauls, Jan-Hendrik and Janosovits, Johannes and Orf, Stefan and Naumann, Maximilian and Kuhnt, Florian and Mayr, Matthias},
booktitle = {Proc.\ IEEE Intell.\ Trans.\ Syst.\ Conf.},
year = {2018},
address = {Hawaii, USA},
owner = {poggenhans},
month = {November},
Url={http://www.mrt.kit.edu/z/publ/download/2018/Poggenhans2018Lanelet2.pdf}
}
```
21 changes: 21 additions & 0 deletions cmake/FindGeographicLib.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Look for GeographicLib
#
# Set
# GEOGRAPHICLIB_FOUND = TRUE
# GeographicLib_INCLUDE_DIRS = /usr/local/include
# GeographicLib_LIBRARIES = /usr/local/lib/libGeographic.so
# GeographicLib_LIBRARY_DIRS = /usr/local/lib

find_package(PkgConfig)
find_path(GeographicLib_INCLUDE_DIR GeographicLib/Config.h
PATH_SUFFIXES GeographicLib
)
set(GeographicLib_INCLUDE_DIRS ${GeographicLib_INCLUDE_DIR})

find_library(GeographicLib_LIBRARIES
NAMES Geographic
)

include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (GeographicLib DEFAULT_MSG GeographicLib_LIBRARIES GeographicLib_INCLUDE_DIRS)
mark_as_advanced (GeographicLib_LIBRARIES GeographicLib_INCLUDE_DIRS)
11 changes: 11 additions & 0 deletions cmake/FindPugiXML.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
find_library(PugiXML_LIBRARIES
NAMES pugixml)
find_path(PugiXML_INCLUDE_DIRS
NAMES pugixml.hpp
PATH_SUFFIXES pugixml)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(pugixml DEFAULT_MSG
PugiXML_LIBRARIES
PugiXML_INCLUDE_DIRS)
message(STATUS "PugiXML include DIRS: " ${PugiXML_INCLUDE_DIRS} ", PugiXML library: " ${PugiXML_LIBRARIES})
7 changes: 4 additions & 3 deletions lanelet2_examples/scripts/tutorial.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
import lanelet2
import tempfile
import os
from lanelet2.liblanelet2_core_pyapi import AttributeMap, TrafficLight, Lanelet, LineString3d, Point2d, Point3d, getId, \
from lanelet2.core import AttributeMap, TrafficLight, Lanelet, LineString3d, Point2d, Point3d, getId, \
LaneletMap, BoundingBox2d, BasicPoint2d
from lanelet2.projection import UtmProjector
from lanelet2 import geometry

example_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../lanelet2_maps/res/mapping_example.osm")

Expand All @@ -29,10 +30,10 @@ def part1primitives():
p.id = getId()
p.attributes["key"] = "value"
assert "key" in p.attributes
assert p.attributes["key"] == "value"
assert p.attributes["key"] == "v"

# the 2d/3d mechanics work too
p2d = lanelet2.geometry.to2D(p)
p2d = geometry.to2D(p)

# all (common) geometry calculations are available as well:
p2 = Point3d(getId(), 1, 0, 0)
Expand Down
4 changes: 2 additions & 2 deletions lanelet2_python/python_api/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ struct AttributeFromPythonStr {
boost::python::converter::registry::push_back(&convertible, &construct, boost::python::type_id<Attribute>());
}

static void* convertible(PyObject* objPtr) { return PyString_Check(objPtr) ? objPtr : nullptr; } // NOLINT
static void* convertible(PyObject* objPtr) { return PyUnicode_Check(objPtr) ? objPtr : nullptr; } // NOLINT

static void construct(PyObject* objPtr, boost::python::converter::rvalue_from_python_stage1_data* data) {
const char* value = PyString_AsString(objPtr);
const char* value = PyUnicode_AS_DATA(objPtr);
if (value == nullptr) {
boost::python::throw_error_already_set();
}
Expand Down
Loading

0 comments on commit 164f4f1

Please sign in to comment.