Patchwork segments the ground out of 3D LiDAR clouds in ROS
SOTA fast and robust ground segmentation using 3D point cloud (accepted in RA-L'21 w/ IROS'21)
At a glance
- What is it?
- Patchwork is a ground segmentation method for 3D LiDAR point clouds, published in RA-L and IROS and packaged as a ROS 2 node, with a concentric zone scheme and a ground likelihood estimator. The README also warns that the TBB build runs at twice the paper's rate, so comparisons against published numbers need care.
- Who is it for?
- Adopt Patchwork when your LiDAR pipeline needs a fast, well published ground segmentation stage on ROS 2 Jazzy, and when you are prepared to tune `elevation_thresholds` and the sensor height for your rig. Do not adopt it expecting to reproduce the paper's benchmark numbers from this repository, because the TBB build runs at 100 Hz against the paper's 50 Hz and the README sends you to a separate benchmark repository for a fair comparison.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 155 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A ground segmentation node for 3D LiDAR
Patchwork is described as state of the art, fast ground segmentation using 3D point cloud, and it was accepted in RA-L 21 with IROS 21. The paper title in the citation gives the mechanism away: Patchwork, Concentric Zone-based Region-wise Ground Segmentation with Ground Likelihood Estimation Using a 3D LiDAR Sensor.
So there are two ideas in the name. The region-wise part divides the sensor's surroundings into concentric zones and decides per zone whether points are ground, which is what lets the method handle a sloped or uneven surface rather than assuming a single plane. The ground likelihood estimation part scores how confident the decision is, which is what lets a downstream planner distinguish a confident ground point from an ambiguous one near the edge of a kerb.
The README also says the project is an overall updated version of R-GPF of ERASOR, with the ERASOR code and paper linked, so the lineage is a public one rather than a new implementation from nothing.
In software terms it is a C++ package built for ROS, MIT licensed, with the topic tags covering lidar, ROS, ground estimation and autonomous driving. The releases are v0.2, labelled ROS1 for archiving, from 2025-05-03, and v0.1 from 2024-07-28, which the release title describes as a refactor of the codes for clean codes and better out-of-distribution behaviour. The last push was on 2026-05-21.
The TBB note changes how you read the benchmarks
The first substantive thing in the README is a warning, and it is worth taking seriously. It says that on 18 August 2024 the author started employing TBB, so its FPS is increased from 50 Hz to 100 Hz, and that if you want to use the paper version of Patchwork for SOTA comparison purposes, you should use the linked ground segmentation benchmark code instead.
That is a fast and honest admission. The published numbers in the paper were produced by a build running at 50 Hz, and the code in this repository now runs at 100 Hz, so a latency or throughput comparison against the paper is not like for like. The fix is not to distrust the method but to benchmark against the same code, and the README points at the right repository for that.
The same note appears in the repository description, where the performance claim sits next to the conference line. Those are claims about the method, and the TBB note is where the project qualifies them.
Building it with colcon
The prerequisite installation is a colcon build from a workspace:
mkdir -p ~/colcon/src
cd ~/colcon/src
git clone https://github.com/LimHyungTae/patchwork.git
cd ..
colcon build --packages-up-to patchwork --cmake-args -DCMAKE_BUILD_TYPE=ReleaseThe `--packages-up-to patchwork` form builds the package and everything it depends on, and the release build type is passed through as a CMake argument rather than as a colcon flag, which is the detail that trips people up when they first try it.
The tested environment is stated plainly: the code is tested successfully at Linux 24.04 LTS and ROS 2 Jazzy. A ROS Noetic version exists and is not in this branch, since the README points to the v0.2 release for it and the v0.2 release title says ROS1 for archiving. In other words, the ROS 1 path is a frozen artefact and the ROS 2 path is the maintained one.
The repository layout is a standard ROS package, with `src/`, `include/`, `launch/`, `config/`, `msg/`, `rviz/`, `3rdparty/`, a `CMakeLists.txt` and a `package.xml`, plus a `.clang-format` and a `.pre-commit-config.yaml` for the C++ style and the commit hooks.
Offline evaluation on SemanticKITTI
The offline path is aimed at reproducing the paper's evaluation, and it needs the SemanticKITTI odometry dataset. The README says to download it, and notes that the labels are needed too since the evaluation code is opened as well.
The directory layout matters, because the launch file takes a sequence directory:
data_path (e.g. 00, 01, ..., or 10)
_____velodyne
|___000000.bin
|___000001.bin
|___000002.bin
|...
_____labels
|___000000.label
|___000001.label
|___000002.label
|...
_____...And the launch invocation is:
ros2 launch patchwork evaluate.launch.yaml evaluate_semantickitti:=true dataset_path:=<YOUR_TARGET_SEQUENCE_DIR>"
e.g.,
ros2 launch patchwork evaluate.launch.yaml evaluate_semantickitti:=true dataset_path:="/home/hyungtae_lim/semkitti/dataset/sequences/04"There is also a convenience for the labels themselves. A December 2024 news entry says `include/label_generator` was added to make the `.label` file following the SemanticKITTI format, thanks to code snippets from two named contributors, and that those `.label` files can be used directly in the 3DUIS benchmark.
That last point is the useful one for a user who does not want to run SemanticKITTI at all. Generating the label format locally means you can produce ground truth compatible with an existing benchmark from your own data, which is how you would evaluate the method on your own robot.
Online segmentation takes a topic and a sensor type
The online path is the one you would put on a vehicle, and the launch file takes two arguments:
ros2 launch patchwork run_patchwork.launch.yaml scan_topic:=<YOUR_TOPIC_NAME> sensor_type:=<YOUR_SENSOR_TYPE>
e.g.,
ros2 launch patchwork run_patchwork.launch.yaml scan_topic:="/acl_jackal2/lidar_points" sensor_type:="velodyne16"The topic is your point cloud source and the sensor type selects the configuration for that lidar, with `velodyne16` in the example. Since the parameters decide how zones are cut and how the height is judged, the README is explicit that you should read the wiki section on setting the parameters of Patchwork in your own environment, and the section title marks it as important.
That is the whole operational surface of the package, and it is a small one: a topic, a sensor type, and a set of parameters that the wiki explains. For a research component that plugs in front of a perception stack, that is a reasonable amount of configuration, and the wiki link is where the real work of adapting it to a different sensor lives.
Height estimation is the part you will have to tune
The news entries record the changes that affect behaviour, and the most important one is about the height of the sensor.
The entry dated 22 May 2022 says the meaning of `elevation_thresholds` was changed to increase usability, with the new meaning explained in the wiki, and that a novel height estimator called All-Terrain Automatic heighT estimator, or ATAT, was added within the patchwork code, which auto-calibrates the sensor height using the ground points in the vicinity of the vehicle or mobile robot. The README points at the function `consensus_set_based_height_estimation()`.
The mechanism is sensible. A zone-based ground detector needs to know roughly how high the sensor sits above the ground, because that height is what turns a distance measurement into an elevation judgement. Estimating it from the nearby ground points removes a manual calibration step, which matters when the vehicle pitches, when it drives on a slope, or when the same code runs on a robot with a different mount.
The trade-off is that an automatic estimate is only as good as the ground points near the vehicle, and on a surface where those points are themselves ambiguous the estimate and the segmentation can be wrong together. The `elevation_thresholds` parameters remain the override for that case, which is why the wiki section on parameters is the one the README keeps pointing at.
Python users have a separate route
There is a second repository worth knowing about, and the README's news entries point to it. The entry dated 22 July 2025 says that a pybinding and a more advanced version are now available on Patchwork++, as a preprocessing step for deep learning users, so that Python users can also use the ground segmentation.
That is a sensible division. This repository is the C++ ROS package, which is what a robot needs, and Patchwork++ is the library route for a team whose ground segmentation is one stage of a training or inference pipeline written in Python.
The other news entries are smaller but relevant to a user. The entry dated 13 July 2023 says the examples and codes were extensively revised to reflect issue 12, which reads like a usability pass over the launch files and the sample code. And the December 2024 entry added the label generator described earlier.
The current release list is short, with v0.2 for ROS 1 archiving and v0.1 for the refactor, and there is no release newer than 2025 in the list even though the last push was in May 2026, so the main branch is where the live work is and the tags are not a good way to track it.
Editorial conclusion
Adopt Patchwork when your LiDAR pipeline needs a fast, well published ground segmentation stage on ROS 2 Jazzy, and when you are prepared to tune `elevation_thresholds` and the sensor height for your rig. Do not adopt it expecting to reproduce the paper's benchmark numbers from this repository, because the TBB build runs at 100 Hz against the paper's 50 Hz and the README sends you to a separate benchmark repository for a fair comparison. Verify first that your sensor type appears in the supported list, that the launch parameters in the wiki match your environment, that your distribution matches the tested one, Linux 24.04 with ROS 2 Jazzy, and that the `consensus_set_based_height_estimation()` path is what you want rather than a fixed sensor height.
Frequently asked questions
What is Patchwork and what problem does it solve?
Patchwork is a fast ground segmentation method for 3D LiDAR point clouds, published as Concentric Zone-based Region-wise Ground Segmentation with Ground Likelihood Estimation Using a 3D LiDAR Sensor in RA-L 2021 with IROS 2021. It is a C++ package built for ROS and is MIT licensed.
How do I build Patchwork?
Create a colcon workspace, clone the repository into `~/colcon/src`, and run `colcon build --packages-up-to patchwork --cmake-args -DCMAKE_BUILD_TYPE=Release`. The tested environment is Linux 24.04 LTS with ROS 2 Jazzy, and the ROS Noetic version is in the v0.2 release.
How do I run Patchwork on a live LiDAR topic?
Run `ros2 launch patchwork run_patchwork.launch.yaml` with a `scan_topic` and a `sensor_type` argument, for example with the topic `/acl_jackal2/lidar_points` and the sensor type `velodyne16`. The README directs you to the project wiki for setting the parameters in your own environment.
Why does Patchwork run faster than the numbers in its paper?
The README explains that since 18 August 2024 the author has employed TBB, which raised the rate from 50 Hz to 100 Hz. For a fair SOTA comparison the README points to a separate ground segmentation benchmark code, since the build in this repository is no longer the one that produced the published numbers.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/limhyungtae-patchwork)Was this useful?