Skip to content

Commit

Permalink
feat: add lanelet2 divider tool
Browse files Browse the repository at this point in the history
Signed-off-by: Barış Zeren <[email protected]>
  • Loading branch information
StepTurtle committed Oct 4, 2024
1 parent 2185b71 commit 3cbbf6e
Show file tree
Hide file tree
Showing 21 changed files with 784 additions and 0 deletions.
152 changes: 152 additions & 0 deletions map/autoware_lanelet2_divider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# autoware_lanalet2_divider

This is a lanelet2 tile generator tool for Autoware dynamic lanelet2 map loading feature.

Working principal of this tool is sequentally:
- Take the inputs from the user
- Generate square grids according to the input MGRS grid
- Filter generated square grids with the input lanelet2_map.osm
- Generate map tiles from filtered grids and input lanelet2_map.osm with Osmium Tool

- [autoware_lanalet2_divider](#autoware_lanalet2_divider)
- [System Requirements](#system-requirements)
- [Inputs](#inputs)
- [MGRS Grid](#mgrs-grid)
- [Grid Edge Size](#grid-edge-size)
- [Input Lanelet2 Map Path](#input-lanelet2-map-path)
- [Outputs](#outputs)
- [lanelet2_map.osm Folder](#lanelet2_maposm-folder)
- [lanelet2_map_metadata.yaml](#lanelet2_map_metadatayaml)
- [config.json Files](#configjson-files)
- [output_layers.gpkg](#output_layersgpkg)
- [Installation](#installation)
- [Poetry](#poetry)
- [Osmium Tool](#osmium-tool)
- [autoware_lanalet2_divider Python Dependencies](#autoware_lanalet2_divider-python-dependencies)
- [Running](#running)
- [Example Data](#example-data)
- [Yildiz Technical University Original Lanelet2 Map](#yildiz-technical-university-original-lanelet2-map)
- [Yildiz Technical University Extended Lanelet2 Map (Synthetic)](#yildiz-technical-university-extended-lanelet2-map-synthetic)
- [Params](#params)

## System Requirements

- [Python](https://www.python.org/) (tested with 3.10)
- [Poetry package](https://python-poetry.org/docs/)
- [Osmium Tool](https://github.com/osmcode/osmium-tool)

## Inputs

### MGRS Grid

100 kilometer MGRS grid that the input lanelet2_map is in. This is needed for generating the grids inside of the
MGRS grid and filtering them.

### Grid Edge Size

This determines the vertice length of the generated map tiles. Map tiles are generated with squares and the edges of
those squares are determined by the user's input.

### Input Lanelet2 Map Path

The full path of the input `lanelet2_map.osm`. This file won't be corrupted.

## Outputs

### lanelet2_map.osm Folder

This is a folder. Autoware's dynamic lanelet2 map loading pipeline needs this folder to find generated map-tiles.
It contains all the generated lanelet2 maps.

### lanelet2_map_metadata.yaml

This metadata file holds the origin points of all the generated lanelet2 map files inside the `lanelet2_map.osm`
folder. Origin point of each lanelet2 map is the coordinates of the left bottom vertice of the corresponding
square created with `mgrs_grid` and `grid_edge_size` parameters.

### config.json Files

Those files contain the coordinates of the vertices of the created squares. With those coordinates, **Osmium Tool**
runs an **extract** operation and divides the input lanelet2_map.osm file.

### output_layers.gpkg

This file contains the geographical visualization for generated data. This is not used in Autoware or somewhere else.
It is generating only for debugging the output files. [QGIS](https://qgis.org/en/site/) can be used for opening this
file. You need to see the visualizations of generated grids, filtered grids and input lanelet2 map.
<p align='center'>
<img src="docs/img_ytu_layers.png" alt="img_ytu_layers" width="60%"/>
</p>
<p align='center'>
<img src="docs/img_ytu_extended_layers_full.png" alt="img_ytu_extended_layers_full" width="57%"/>
<img src="docs/img_ytu_extended_layers.png" alt="img_ytu_extended_layers" width="40%"/>
</p>

## Installation

Additional to `colcon build`, you have to follow individual installation steps for the tools that are used in this
project.

### Poetry:

```bash
pip install poetry
```

### Osmium Tool

https://github.com/osmcode/osmium-tool?tab=readme-ov-file#building

```bash
cd <path-to-libraries>
git clone https://github.com/osmcode/osmium-tool.git
cd osmium-tool
mkdir build
cd build
cmake ..
ccmake . ## optional: change CMake settings if needed
make
```

### autoware_lanalet2_divider Python Dependencies

```bash
cd <path-to-autoware_tools/map/autoware_lanalet2_divider>
pip install -r requirements.txt
```

## Running

Before running the tool, you should check the `config/lanelet2_divider.param.yaml` file. You can change the default
parameters from this file.

```bash
ros2 run autoware_lanelet2_divider lanelet2_divider --ros-args --params-file install/autoware_lanelet2_divider/share/autoware_lanelet2_divider/lanelet2_divider.param.yaml
```

## Example Data
### Yildiz Technical University Original Lanelet2 Map
This is an original lanelet2 map file that contains stop lines, speed bumps or other regulatory elements:
https://drive.google.com/drive/folders/1VFN0zidAHzIuQCnznVaFzefqqdRS_X5l?usp=drive_link

<p align='center'>
<img src="docs/img_ytu_original.png" alt="img_ytu_original" width="60%"/>
</p>

### Yildiz Technical University Extended Lanelet2 Map (Synthetic)
This is the extended version of the original lanelet2 map file. We extended it to 80 kilometers by hand.
Still it contains all the regulatory elements:
https://drive.google.com/drive/folders/1CRBYp19_NXzHXxL9JkO_ffbhGARoRaAV?usp=drive_link

<p align='center'>
<img src="docs/img_ytu_extended.png" alt="img_ytu_extended"/>
</p>

## Params

| Param | Description |
|--------------------|---------------------------------------------------------|
| mgrs_grid | The 100 kilometer MGRS grid that the lanelet2 map is in |
| grid_edge_size | Wanted edge length in meters for map-tiles to generate |
| input_lanelet2_map | Full path of the lanelet2_map to divide |
| output_folder | Full path of the output folder to fill |
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import importlib.metadata as importlib_metadata

try:
# This will read version from pyproject.toml
__version__ = importlib_metadata.version(__package__ or __name__)
except importlib_metadata.PackageNotFoundError:
__version__ = "development"

from .autoware_lanelet2_divider import AutowareLanlet2Divider

Check warning on line 9 in map/autoware_lanelet2_divider/autoware_lanelet2_divider/__init__.py

View workflow job for this annotation

GitHub Actions / spell-check-partial

Unknown word (Lanlet)
import autoware_lanelet2_divider.osmium_tool.osmium_tool as osmium_tool
import autoware_lanelet2_divider.xml_tool.xml_tool as xml_tool
import autoware_lanelet2_divider.data_preperation.data_preperation as data_preparation

Check warning on line 12 in map/autoware_lanelet2_divider/autoware_lanelet2_divider/__init__.py

View workflow job for this annotation

GitHub Actions / spell-check-partial

Misspelled word (preperation) Suggestions: (preparation*)

Check warning on line 12 in map/autoware_lanelet2_divider/autoware_lanelet2_divider/__init__.py

View workflow job for this annotation

GitHub Actions / spell-check-partial

Misspelled word (preperation) Suggestions: (preparation*)
from autoware_lanelet2_divider.debug import Debug, DebugMessageType
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import rclpy
from rclpy.node import Node

import autoware_lanelet2_divider.osmium_tool.osmium_tool as osmium_tool
import autoware_lanelet2_divider.xml_tool.xml_tool as xml_tool
import autoware_lanelet2_divider.data_preperation.data_preperation as data_preparation

Check warning on line 6 in map/autoware_lanelet2_divider/autoware_lanelet2_divider/autoware_lanelet2_divider.py

View workflow job for this annotation

GitHub Actions / spell-check-partial

Misspelled word (preperation) Suggestions: (preparation*)

Check warning on line 6 in map/autoware_lanelet2_divider/autoware_lanelet2_divider/autoware_lanelet2_divider.py

View workflow job for this annotation

GitHub Actions / spell-check-partial

Misspelled word (preperation) Suggestions: (preparation*)
from autoware_lanelet2_divider.debug import Debug, DebugMessageType

import os

class AutowareLanlet2Divider(Node):

Check warning on line 11 in map/autoware_lanelet2_divider/autoware_lanelet2_divider/autoware_lanelet2_divider.py

View workflow job for this annotation

GitHub Actions / spell-check-partial

Unknown word (Lanlet)
def __init__(self):
super().__init__('autoware_lanelet2_divider')
Debug.log('Autoware Lanelet2 Divider Node has been started.', DebugMessageType.INFO)

self.declare_params()

self.input_lanelet2_map_path = self.get_parameter('input_lanelet2_map_path').get_parameter_value().string_value
self.output_folder_path = self.get_parameter('output_folder_path').get_parameter_value().string_value
self.mgrs_grid = self.get_parameter('mgrs_grid').get_parameter_value().string_value
self.grid_edge_size = self.get_parameter('grid_edge_size').get_parameter_value().integer_value

Debug.log('Input Lanelet2 Map Path: %s' % self.input_lanelet2_map_path, DebugMessageType.INFO)
Debug.log('Output Folder Path: %s' % self.output_folder_path, DebugMessageType.INFO)
Debug.log('MGRS Grid: %s' % self.mgrs_grid, DebugMessageType.INFO)
Debug.log('Grid Edge Size: %d' % self.grid_edge_size, DebugMessageType.INFO)

# Complete if missing "version" element in lanelet2_map.osm
xml_tool.complete_missing_version_tag(self.input_lanelet2_map_path)

# Create config file to extract osm file
config_files = data_preparation.data_preparation(self.mgrs_grid, self.grid_edge_size, self.input_lanelet2_map_path, self.output_folder_path)
# Extract osm file
for config_file_path in config_files:
is_extracted = osmium_tool.extract_osm_file(self.input_lanelet2_map_path, config_file_path,
os.path.join(self.output_folder_path, "lanelet2_map.osm"))
if not is_extracted:
Debug.log("Failed to extract osm file.\n", DebugMessageType.ERROR)
rclpy.shutdown()

# Complete missing elements in osm file
xml_tool.complete_missing_elements(self.input_lanelet2_map_path, os.path.join(self.output_folder_path, "lanelet2_map.osm"))

Debug.log('Autoware Lanelet2 Divider Node has been finished.', DebugMessageType.SUCCESS)
exit(0)

def declare_params(self) -> None:
self.declare_parameter('input_lanelet2_map_path', '')
self.declare_parameter('output_folder_path', '')
self.declare_parameter('mgrs_grid', '')
self.declare_parameter('grid_edge_size', 100)

def main(args=None):
rclpy.init(args=args)
autoware_lanelet2_divider = AutowareLanlet2Divider()

Check warning on line 55 in map/autoware_lanelet2_divider/autoware_lanelet2_divider/autoware_lanelet2_divider.py

View workflow job for this annotation

GitHub Actions / spell-check-partial

Unknown word (Lanlet)
rclpy.spin(autoware_lanelet2_divider)
autoware_lanelet2_divider.destroy_node()
rclpy.shutdown()

if __name__ == '__main__':
main()
Loading

0 comments on commit 3cbbf6e

Please sign in to comment.