Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(autoware_lanelet2_divider): add lanelet2 divider tool #130

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3cbbf6e
feat: add lanelet2 divider tool
StepTurtle Oct 4, 2024
99ec770
style(pre-commit): autofix
pre-commit-ci[bot] Oct 4, 2024
cc7ffbf
fix: wrong maintainer format
StepTurtle Oct 28, 2024
03005a9
fix: add missing output directory check
StepTurtle Oct 28, 2024
a537e1e
chore: add args to osmium tool
StepTurtle Oct 28, 2024
56f3dc5
chore: remove unnecessary else
StepTurtle Oct 28, 2024
926788f
refactor: extract_osm_file function
StepTurtle Oct 30, 2024
c89bc27
docs: add doxygen-style comments
StepTurtle Oct 30, 2024
f1fc2de
chore: remove redundant else
StepTurtle Oct 30, 2024
c5971df
refactor: missing version fuction
StepTurtle Oct 30, 2024
d74b05a
refactor: loops in complete_missing_elements function
StepTurtle Oct 30, 2024
b714afc
refactor: data_preparation function
StepTurtle Oct 30, 2024
bc46f7f
refactor: print functions with Debug
StepTurtle Oct 30, 2024
262b9d6
fix: spelling errors
StepTurtle Oct 30, 2024
6af5e19
style(pre-commit): autofix
pre-commit-ci[bot] Oct 30, 2024
5ae8394
fix: pre-commit.ci
StepTurtle Oct 30, 2024
3cbcf70
style(pre-commit): autofix
pre-commit-ci[bot] Oct 30, 2024
574564a
chore: create temp osm
StepTurtle Nov 21, 2024
bbb88cb
chore: update version function
StepTurtle Nov 21, 2024
ae49921
style(pre-commit): autofix
pre-commit-ci[bot] Nov 21, 2024
3383834
fix: spell check
StepTurtle Nov 21, 2024
4389d6b
Merge branch 'feat/add_lanelet2_divider' of github.com:StepTurtle/aut…
StepTurtle Nov 21, 2024
0d0ccea
style(pre-commit): autofix
pre-commit-ci[bot] Nov 21, 2024
27e4fe1
fix: spell check
StepTurtle Nov 21, 2024
d6975ae
style(pre-commit): autofix
pre-commit-ci[bot] Nov 21, 2024
40e4076
fix: spell check
StepTurtle Nov 21, 2024
4ed7577
Merge branch 'main' into feat/add_lanelet2_divider
YamatoAndo Nov 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions map/autoware_lanelet2_divider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# autoware_lanalet2_divider

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

Working principal of this tool is sequentially:

- 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 vertex 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 vertex 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,7 @@
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"
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import os

import autoware_lanelet2_divider.data_preperation.data_preperation as data_preparation

Check warning on line 3 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 3 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
from autoware_lanelet2_divider.debug import DebugMessageType
import autoware_lanelet2_divider.osmium_tool.osmium_tool as osmium_tool
import autoware_lanelet2_divider.xml_tool.xml_tool as xml_tool
import rclpy
from rclpy.node import Node


class AutowareLanlet2Divider(Node):

Check warning on line 12 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)
StepTurtle marked this conversation as resolved.
Show resolved Hide resolved

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 75 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
Loading