Skip to content

Commit 4713502

Browse files
committed
fix(memcpy): need ascontiguousarray before memcpy. So add init file to do so.
* add more data in README * support python=3.13 also * rename default branch to main. * update HiMo link where I develop this package from this project. * same api still to align previous fn etc.
1 parent 9d5d228 commit 4713502

File tree

13 files changed

+157
-112
lines changed

13 files changed

+157
-112
lines changed

.github/workflows/Pip.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
pull_request:
66
push:
77
branches:
8-
- master
8+
- main
99
release:
1010
types:
1111
- published

.github/workflows/Wheels.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
pull_request:
66
push:
77
branches:
8-
- master
8+
- main
99
release:
1010
types:
1111
- published

README.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ linefit
55
[![Python Versions](https://img.shields.io/pypi/pyversions/linefit)](https://pypi.org/project/linefit/)
66
[![Download Stats](https://img.shields.io/pypi/dm/linefit)](https://pypistats.org/packages/linefit)
77

8-
linefit is a ground segmentation algorithm for 3D point clouds. This repo we setup a python binding for the original C++ code and push to pypi for easy installation through `pip install linefit`.
8+
linefit is a ground segmentation algorithm for 3D point clouds.
9+
This repo we setup a python binding for the original C++ code and push to pypi for easy installation through `pip install linefit`.
910

1011
Author: C++ code from [Lorenz Wellhausen](https://github.com/lorenwel), python package from [Qingwen Zhang](https://kin-zhang.github.io/).
1112

@@ -15,6 +16,7 @@ Available in: <a href="https://github.com/Kin-Zhang/linefit"><img src="https://i
1516

1617
<!-- -->
1718
📜 Change Log:
19+
- 2025-04-18: Add `__init__.py` to the package with `ascontiguousarray` to avoid unexpected point error reading, add package to the latest python (3.13) also. Rename the default branch to `main`.
1820
- 2024-07-03: Speed up nanobind `np.array` <-> `std::vector<Eigen:: Vector3d>` conversion and also `NOMINSIZE` in make. Speed difference: 0.1s -> 0.01s. Based on [discussion here](https://github.com/wjakob/nanobind/discussions/426).
1921
- 2024-02-15: Initial version.
2022

@@ -26,9 +28,8 @@ Option A: Install from pypi `pip install linefit`
2628

2729
Option B: Clone this repo and run following to build:
2830
```bash
29-
cmake -B build && cmake --build build
30-
pip install .
31-
python3 -c 'import linefit; print("success")'
31+
pip install git+https://github.com/Kin-Zhang/linefit
32+
python3 -c 'import linefit; print("linefit ground seg lib import success")'
3233
```
3334

3435
Dependencies for demo:
@@ -106,6 +107,17 @@ The original methods are described in the following paper:
106107
}
107108
```
108109

110+
This Python package is developed during HiMo project, please consider to cite our paper if this python package is helpful for your research:
111+
112+
```
113+
@article{zhang2025himo,
114+
title={HiMo: High-Speed Objects Motion Compensation in Point Cloud},
115+
author={Zhang, Qingwen and Khoche, Ajinkya and Yang, Yi and Ling, Li and Sina, Sharif Mansouri and Andersson, Olov and Jensfelt, Patric},
116+
year={2025},
117+
journal={arXiv preprint arXiv:2503.00803},
118+
}
119+
```
120+
109121
More python binding examples can be found in our other project:
110122
- [dufomap](https://github.com/KTH-RPL/dufomap): a dynamic awareness mapping framework. Remove dynamic points in a raw map.
111123
- [dztimer](https://github.com/KTH-RPL/dztimer): a breakout timer for python code.

assets/README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@ Assets
33

44
## Data
55

6+
7+
8+
### PCD/npy Format
69
The data is generated by [DynamicMap Benchmark](https://github.com/KTH-RPL/DynamicMap_Benchmark).
710

8-
Detail code could be find in [scripts/py/data](https://github.com/KTH-RPL/DynamicMap_Benchmark/blob/master/scripts/py/data).
9-
Although the original is save to pcd. While, adding `np.save` to save the data as `.npy` file.
11+
Detail code could be found in [scripts/py/data](https://github.com/KTH-RPL/DynamicMap_Benchmark/blob/master/scripts/py/data).
12+
Although the original is saved to pcd. While, adding `np.save` to save the data as `.npy` file.
13+
14+
15+
### H5 Format
16+
The sequence data can be generated by [OpenSceneFlow](https://github.com/KTH-RPL/OpenSceneFlow). Check more detail on [here](https://github.com/KTH-RPL/OpenSceneFlow/blob/main/dataprocess/README.md#process).

assets/config/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ Popular Dataset config
88
Here is what I mean, all visualization here are provided by [DeFlow vis scripts](https://github.com/KTH-RPL/DeFlow/blob/main/tests/scene_flow.py):
99
![](../docs/sensor_pos.png)
1010

11+
`${#lidar}x ${#channel} lidar` mean how many lidar and how many channel lidar in the dataset.
12+
1113
- [x] KITTI: 1x 64 lidar
1214
- [x] Nuscenes: 1x 32 lidar
1315
- [x] Argoverse 2: 2x 32 lidar
16+
- [x] [Zod](https://zod.zenseact.com/): 128 lidar + 2x 16 lidar
1417
- [ ] [Semi-indoor](https://github.com/KTH-RPL/DynamicMap_Benchmark?tab=readme-ov-file#dataset--scripts): 1x 16 lidar
15-
- [ ] Waymo: custom lidar.
16-
- [ ] [Zod](https://zod.zenseact.com/): 128 lidar + 2x 16 lidar
18+
- [ ] Waymo: 1x custom 64 lidar.
19+
- [ ] [Scania](https://kin-zhang.github.io/HiMo): 6/10x 32 lidar.
20+
- [ ] [TruckScene](https://github.com/TUMFTM/truckscenes-devkit): 1x 128 lidar.
1721
... More on the way

assets/config/zod.toml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
[important]
3+
height = 2.1 # sensor height. 雷达传感器高度,主要是+offset
4+
5+
# 整个雷点点云以自己为中心 分为多少个segment,每个segment又分成多少个bin
6+
[segments]
7+
r_min = 0.1 # minimum point distance. 感兴趣的区域
8+
r_max = 100 # maximum point distance.
9+
n_segments = 360 # number of radial segments.
10+
n_bins = 160 # number of radial bins.
11+
12+
13+
[ground]
14+
# 直线的 slope 斜率,一个seg里拟合的线斜率
15+
min_slope = 0.0 # minimum slope of a ground line. [T_m_small]
16+
max_slope = 0.1 # maximum slope of a ground line. [T_m]
17+
# 如果拟合点超过这个 long threshold,判断其 height 变化是否超过 max_long_height
18+
long_threshold = 2.0 # Distance at which points are considered far from each other. [T_d_prev]
19+
max_long_height = 0.2 # maximum height change to previous point in long line. [T_b]
20+
# 如果没有超过 long threshold,判断现在拟合的点与fitline高度变化是否超过 max_start_height
21+
max_start_height = 0.2 # Maximum heigh of starting line to be labelled ground.
22+
# 最大的拟合误差,超过这个误差的点不会被加入 line 拟合
23+
max_fit_error = 0.1 # maximum error of a point during line fit. [T_RMSE: will sqaure inside code.]
24+
25+
# 判断是否是地面点的时候,需要满足的条件:
26+
max_dist_to_line = 0.2 # maximum vertical distance of point to line to be considered ground. [T_d_ground]
27+
line_search_angle = 2.0 # How far to search for a line in angular direction [rad].
28+
29+
[general]
30+
n_threads = 8 # number of threads for parallel processing.
31+
verbose = false # if you don't want to see every output, set this to false.

example.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
else:
2828
groundseg = ground_seg(config_path)
2929
label = np.array(groundseg.run(pc_data[:,:3]))
30-
print(f"point cloud shape: {pc_data[:, :3].shape}, label shape: {label.shape}, ground points: {np.sum(label)}, time: {time.time() - start_time:.3f} s")
30+
print(f"point cloud shape: {pc_data[:, :3].shape}, label shape: {label.shape}, ground points: {np.sum(label)}, process time: {(time.time() - start_time)*1000:.3f} ms")
3131

3232
from python.utils.o3d_view import MyVisualizer
3333
import open3d as o3d

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
44

55
[project]
66
name = "linefit"
7-
version = "1.0.1"
7+
version = "1.1.0"
88
description = "linefit ground segmentation algorithm Python bindings"
99
readme = "README.md"
1010
requires-python = ">=3.8"
@@ -19,6 +19,7 @@ classifiers = [
1919
"Programming Language :: Python :: 3.10",
2020
"Programming Language :: Python :: 3.11",
2121
"Programming Language :: Python :: 3.12",
22+
"Programming Language :: Python :: 3.13",
2223
]
2324

2425
[project.urls]
@@ -33,7 +34,7 @@ minimum-version = "0.4"
3334
build-dir = "build/{wheel_tag}"
3435

3536
# Build stable ABI wheels for CPython 3.12+
36-
wheel.py-api = "cp312"
37+
wheel.py-api = "cp313"
3738

3839

3940
[tool.cibuildwheel]

python/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
nanobind_add_module(linefit MODULE NOMINSIZE linefit_ext.cpp)
2-
target_link_libraries(linefit PRIVATE gm_lib)
3-
install(TARGETS linefit LIBRARY DESTINATION .)
1+
nanobind_add_module(linefit_bind MODULE NOMINSIZE linefit_ext.cpp)
2+
target_link_libraries(linefit_bind PRIVATE gm_lib)
3+
install(TARGETS linefit_bind LIBRARY DESTINATION .)

python/linefit/__init__.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'''
2+
# @date: 2025-04-18 18:29
3+
# @author: Qingwen Zhang (https://kin-zhang.github.io/)
4+
# Copyright (C) 2025-now, RPL, KTH Royal Institute of Technology
5+
#
6+
# This file is part of HiMo (https://kin-zhang.github.io/HiMo).
7+
# If you find this repo helpful, please cite the respective publication as
8+
# listed on the above website.
9+
'''
10+
11+
__version__ = "1.1.0"
12+
13+
import numpy as np
14+
import linefit_bind
15+
16+
class ground_seg:
17+
def __init__(self, config_path=None):
18+
"""
19+
config_path (str): path to the config file, if None, use default parameters
20+
"""
21+
if config_path is None:
22+
self.linefit_fn = linefit_bind.ground_seg()
23+
else:
24+
self.linefit_fn = linefit_bind.ground_seg(config_path)
25+
26+
def run(self, points):
27+
"""
28+
Parameters
29+
----------
30+
points (np.ndarray): point cloud data, shape (N, 3), 3 for x, y, z
31+
"""
32+
points = np.ascontiguousarray(points.astype(np.float32))
33+
labels = np.array(self.linefit_fn.run(points[:, :3])).astype(np.uint8)
34+
return labels

0 commit comments

Comments
 (0)