Skip to content

Commit 5b2884f

Browse files
committed
feat(python): run dufomap in python now!
updates: * main.py script to run. * poster for dufomap. * Dockerfile usage.
1 parent fe24fbb commit 5b2884f

File tree

3 files changed

+85
-3
lines changed

3 files changed

+85
-3
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,5 @@ docs/html/*
5858
# coverage report
5959
coverage_report/*
6060
.coverage/
61+
62+
*.pcd

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
</p>
44

55
[![arXiv](https://img.shields.io/badge/arXiv-2403.01449-b31b1b?logo=arxiv&logoColor=white)](https://arxiv.org/abs/2403.01449)
6-
[![page](https://img.shields.io/badge/Web-Page-green)](https://KTH-RPL.github.io/dufomap) [video coming soon] [poster coming soon]. Accepted by RA-L'24.
6+
[![page](https://img.shields.io/badge/Project-Page-green)](https://KTH-RPL.github.io/dufomap) [![poster](https://img.shields.io/badge/RAL2024|Poster-6495ed?style=flat&logo=Shotcut&logoColor=wihte)](https://mit-spark.github.io/Longterm-Perception-WS/assets/proceedings/DUFOMap/poster.pdf) [video coming soon]
77

88
Quick Demo: Run with the **same parameter setting** without tuning for different sensor (e.g 16, 32, 64, and 128 channel LiDAR and Livox-series mid360), the following shows the data collected from:
99

@@ -12,20 +12,26 @@ Quick Demo: Run with the **same parameter setting** without tuning for different
1212
| ![](assets/imgs/dufomap_leica.gif) | ![](assets/imgs/doals_train_128.gif) | ![](assets/imgs/two_floor_mid360.gif) |
1313
<!-- | ------- | ------- | ------- | -->
1414

15+
🚀 2024-11-20: Update dufomap Python API from [SeFlow](https://github.com/KTH-RPL/SeFlow) try it now! `pip install dufomap` and run `python main.py --data_dir data/00` to get the cleaned map directly. Support all >=Python 3.8 in Windows and Linux. Please extract your own data to unified format first follow [this wiki page](https://kth-rpl.github.io/DynamicMap_Benchmark/data/creation/#custom-data).
16+
1517
## 0. Setup
1618

1719
```bash
1820
sudo apt update && sudo apt install gcc-10 g++-10
1921
sudo apt install libtbb-dev liblz4-dev
2022
```
2123

22-
Dockerfile will be soon available.
2324

2425
Clone quickly and init submodules:
2526
```bash
2627
git clone --recursive -b main --single-branch https://github.com/KTH-RPL/dufomap.git
2728
```
2829

30+
Or you can directly build docker image through our [Dockerfile](Dockerfile):
31+
```bash
32+
docker build -t dufomap .
33+
```
34+
2935
## 1. Build & Run
3036

3137
Build:
@@ -34,7 +40,7 @@ Build:
3440
cmake -B build -D CMAKE_CXX_COMPILER=g++-10 && cmake --build build
3541
```
3642

37-
Prepare Data: Teaser data (KITTI 00: 384.4Mb) can be downloaded via follow commands, more data detail can be found in the [dataset section](https://github.com/KTH-RPL/DynamicMap_Benchmark?tab=readme-ov-file#dataset--scripts) or format your own dataset follow [custom dataset section](https://github.com/KTH-RPL/DynamicMap_Benchmark/blob/master/scripts/README.md#custom-dataset).
43+
Prepare Data: Teaser data (KITTI 00: 384.4Mb) can be downloaded via follow commands, more data detail can be found in the [dataset section](https://kth-rpl.github.io/DynamicMap_Benchmark/data) or format your own dataset follow [custom dataset section](https://kth-rpl.github.io/DynamicMap_Benchmark/data/creation/#custom-data).
3844

3945
```bash
4046
wget https://zenodo.org/records/8160051/files/00.zip -p data

main.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""
2+
# Created: 2024-11-20 13:11
3+
# Copyright (C) 2024-now, RPL, KTH Royal Institute of Technology
4+
# Author: Qingwen Zhang (https://kin-zhang.github.io/)
5+
#
6+
# This file is part of DUFOMap (https://github.com/KTH-RPL/dufomap) and
7+
# DynamicMap Benchmark (https://github.com/KTH-RPL/DynamicMap_Benchmark) projects.
8+
# If you find this repo helpful, please cite the respective publication as
9+
# listed on the above website.
10+
11+
# Description: Output Cleaned Map through Python API.
12+
"""
13+
from pathlib import Path
14+
import os, fire, time
15+
import numpy as np
16+
from tqdm import tqdm
17+
18+
from dufomap import dufomap
19+
from dufomap.utils import pcdpy3
20+
def inv_pose_matrix(pose):
21+
inv_pose = np.eye(4)
22+
inv_pose[:3, :3] = pose[:3, :3].T
23+
inv_pose[:3, 3] = -pose[:3, :3].T.dot(pose[:3, 3])
24+
return inv_pose
25+
class DynamicMapData:
26+
def __init__(self, directory):
27+
self.scene_id = directory.split("/")[-1]
28+
self.directory = Path(directory) / "pcd"
29+
self.pcd_files = [os.path.join(self.directory, f) for f in sorted(os.listdir(self.directory)) if f.endswith('.pcd')]
30+
31+
def __len__(self):
32+
return len(self.pcd_files)
33+
34+
def __getitem__(self, index_):
35+
res_dict = {
36+
'scene_id': self.scene_id,
37+
'timestamp': self.pcd_files[index_].split("/")[-1].split(".")[0],
38+
}
39+
pcd_ = pcdpy3.PointCloud.from_path(self.pcd_files[index_])
40+
pc0 = pcd_.np_data[:,:3]
41+
res_dict['pc'] = pc0.astype(np.float32)
42+
res_dict['pose'] = list(pcd_.viewpoint)
43+
return res_dict
44+
45+
def main_vis(
46+
data_dir: str = "/home/kin/data/00",
47+
):
48+
dataset = DynamicMapData(data_dir)
49+
50+
# STEP 0: initialize
51+
mydufo = dufomap(0.1, 0.2, 2, num_threads=12) # resolution, d_s, d_p same with paper.
52+
cloud_acc = np.zeros((0, 3), dtype=np.float32)
53+
for data_id in (pbar := tqdm(range(0, len(dataset)),ncols=100)):
54+
data = dataset[data_id]
55+
now_scene_id = data['scene_id']
56+
pbar.set_description(f"id: {data_id}, scene_id: {now_scene_id}, timestamp: {data['timestamp']}")
57+
58+
# STEP 1: integrate point cloud into dufomap
59+
mydufo.run(data['pc'], data['pose'], cloud_transform = False) # since pc already in world frame
60+
cloud_acc = np.concatenate((cloud_acc, data['pc']), axis=0)
61+
62+
# STEP 2: propagate
63+
mydufo.oncePropagateCluster(if_propagate=True, if_cluster=False)
64+
# STEP 3: Map results
65+
mydufo.outputMap(cloud_acc, voxel_map=False)
66+
# NOTE(Qingwen): You can also save voxeled map directly based on the resolution we set before:
67+
# mydufo.outputMap(cloud_acc, voxel_map=True)
68+
69+
mydufo.printDetailTiming()
70+
71+
if __name__ == "__main__":
72+
start_time = time.time()
73+
fire.Fire(main_vis)
74+
print(f"Time used: {time.time() - start_time:.2f} s")

0 commit comments

Comments
 (0)