From cd3e7dbd3f873efc4684055b247a0ff124b1d401 Mon Sep 17 00:00:00 2001 From: Hyungtae Lim Date: Thu, 21 May 2026 17:28:19 +0900 Subject: [PATCH 1/4] docs(readme): show Patchwork++ as the ROS 2 default + advertise eval harness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ROS 2 section: - Make explicit that `ros2 launch patchworkpp patchworkpp.launch.py` alone runs Patchwork++; only `algorithm:=patchwork` opts into the classic algorithm. The launch file's LaunchConfiguration default is already "patchworkpp" (ros/launch/patchworkpp.launch.py:20), so this is a doc fix, not a behavioural change. What's-in-this-repo: - Add a bullet for python/examples/evaluate_semantickitti.py and note that the two algorithms use different SemanticKITTI evaluation protocols (Patchwork paper counts low-z vegetation as ground; Patchwork++ paper Sec. IV.A excludes vegetation entirely because the SemanticKITTI `vegetation` label mixes spurious leaves / branches with low ground cover). Point at USAGE.md §1 and §4 for the protocol switch and per-sequence numbers. Docs-only; no version bump. --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 40c5140..1aee773 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ - C++ source code of Patchwork++ ([patchworkpp][sourcecodelink]) - Python binding of Patchwork++ using pybind11 ([python_wrapper][wraplink]) - Examples codes of [C++][cppexamplelink], [Python][pyexamplelink], and [ROS2][rosexamplelink] :thumbsup: +- A transparent, reproducible **SemanticKITTI evaluation harness** for both Patchwork and Patchwork++ ([`python/examples/evaluate_semantickitti.py`][evallink]). The two algorithms use **different evaluation protocols** — the original Patchwork paper counts low-z vegetation as ground while the Patchwork++ paper excludes vegetation entirely (Sec. IV.A), because the SemanticKITTI `vegetation` label mixes spurious leaves/branches with low ground cover and a single ground/non-ground choice is impractical. The script supports both protocols via `--eval_protocol {patchwork, patchworkpp}` and reproduces each paper's Table I within ±0.2 F1; see [`USAGE.md`][usagelink] §1 and §4 for the full reasoning and per-sequence numbers. > If you are familiar with ROS1, you can also visit [here][roslink] and try executing ROS1-based Patchwork++! @@ -135,9 +136,13 @@ pp_default = p.patchworkpp(p.Parameters()) # Patchwork++ pp_classic = p.patchwork(p.PatchworkParams()) # Patchwork (classic) ``` -**ROS2:** +**ROS2:** Patchwork++ is the default; pass `algorithm:=patchwork` to switch to the classic Patchwork. ```bash +# Default — runs Patchwork++ +ros2 launch patchworkpp patchworkpp.launch.py + +# Override to the classic Patchwork ros2 launch patchworkpp patchworkpp.launch.py algorithm:=patchwork ``` @@ -193,6 +198,7 @@ ______________________________________________________________________ [arxivlink]: https://arxiv.org/abs/2207.11919 [cppexamplelink]: https://github.com/url-kaist/patchwork-plusplus/tree/master/cpp +[evallink]: python/examples/evaluate_semantickitti.py [htlink]: https://github.com/LimHyungTae [patchworkarxivlink]: https://arxiv.org/abs/2108.05560 [patchworkieeelink]: https://ieeexplore.ieee.org/document/9466396 @@ -203,4 +209,5 @@ ______________________________________________________________________ [roslink]: https://github.com/url-kaist/patchwork-plusplus-ros [sjlink]: https://github.com/seungjae24 [sourcecodelink]: https://github.com/url-kaist/patchwork-plusplus/tree/master/cpp/patchworkpp +[usagelink]: USAGE.md [wraplink]: https://github.com/url-kaist/patchwork-plusplus/tree/master/python/patchworkpp From 6b85ae47e0990730a9ca90b4b621d888d874cb49 Mon Sep 17 00:00:00 2001 From: Hyungtae Lim Date: Thu, 21 May 2026 17:32:53 +0900 Subject: [PATCH 2/4] docs(readme): pip-first Python install, demote make pyinstall to a contributors note pypatchworkpp ships on PyPI since v1.3.0; the pip banner is already at the top of the README, but the Python install section was still making `make pyinstall` the headline command. Switch the order: - Lead with `pip install pypatchworkpp` and `pip install 'pypatchworkpp[demo]'` (the `[demo]` extra is defined in python/pyproject.toml and pulls open3d). - Keep `make pyinstall` / `make pyinstall_with_demo` in a collapsed
block labelled "Build from source (contributors / unreleased main)" so the source-build path is still discoverable without competing with the pip path for new users. Docs-only; same PR as the ROS 2 default clarification + eval-harness bullet. --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1aee773..e8493d9 100644 --- a/README.md +++ b/README.md @@ -69,23 +69,23 @@ Eigen is fetched automatically by CMake, so no extra system package is required ### Python -**Pure installation** +The released library is on PyPI: ```commandline -make pyinstall +pip install pypatchworkpp # core library +pip install 'pypatchworkpp[demo]' # + Open3D for the visual demos ``` -Then, you can use Patchwork++ by `import pypatchworkpp`, which is super simple! - -**Installation to run demo** +Then `import pypatchworkpp` in your script — see the [Python examples][pyexamplelink]. -Only Open3D (> 0.17.0) is additionally installed for visualization purposes. +
Build from source (contributors / unreleased main) ```commandline -make pyinstall_with_demo +make pyinstall # equivalent to `pip install ./python/` +make pyinstall_with_demo # also installs Open3D >= 0.17.0 ``` -How to run Python demos is explained [here][pyexamplelink]. +
### C++ From b47d26864aed95421b6cdd26e10bf620b5930c02 Mon Sep 17 00:00:00 2001 From: Hyungtae Lim Date: Thu, 21 May 2026 17:38:44 +0900 Subject: [PATCH 3/4] =?UTF-8?q?docs:=20move=20vegetation-protocol=20ration?= =?UTF-8?q?ale=20out=20of=20README=20into=20USAGE.md=20=C2=A71?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The README "What's in this repo" bullet was carrying a 4-line wall of text about why Patchwork and Patchwork++ disagree on the vegetation class. Shrink it to a single sentence + link to USAGE.md §1, and put the full rationale (low ground cover vs. overhead foliage, why the two papers chose different resolutions) where it belongs. --- README.md | 2 +- USAGE.md | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e8493d9..d9dd2df 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ - C++ source code of Patchwork++ ([patchworkpp][sourcecodelink]) - Python binding of Patchwork++ using pybind11 ([python_wrapper][wraplink]) - Examples codes of [C++][cppexamplelink], [Python][pyexamplelink], and [ROS2][rosexamplelink] :thumbsup: -- A transparent, reproducible **SemanticKITTI evaluation harness** for both Patchwork and Patchwork++ ([`python/examples/evaluate_semantickitti.py`][evallink]). The two algorithms use **different evaluation protocols** — the original Patchwork paper counts low-z vegetation as ground while the Patchwork++ paper excludes vegetation entirely (Sec. IV.A), because the SemanticKITTI `vegetation` label mixes spurious leaves/branches with low ground cover and a single ground/non-ground choice is impractical. The script supports both protocols via `--eval_protocol {patchwork, patchworkpp}` and reproduces each paper's Table I within ±0.2 F1; see [`USAGE.md`][usagelink] §1 and §4 for the full reasoning and per-sequence numbers. +- A reproducible **SemanticKITTI evaluation harness** for both Patchwork and Patchwork++ ([`python/examples/evaluate_semantickitti.py`][evallink]). The two algorithms use **different evaluation protocols** (Patchwork paper vs Patchwork++ paper Sec. IV.A) — see [`USAGE.md`][usagelink] §1 for why and §4 for per-sequence numbers. > If you are familiar with ROS1, you can also visit [here][roslink] and try executing ROS1-based Patchwork++! diff --git a/USAGE.md b/USAGE.md index da092c0..a43194e 100644 --- a/USAGE.md +++ b/USAGE.md @@ -14,6 +14,15 @@ ______________________________________________________________________ The Patchwork and Patchwork++ papers use **different** ground-truth definitions on SemanticKITTI. The eval driver `python/examples/evaluate_semantickitti.py` supports both via `--eval_protocol {patchwork, patchworkpp}`. +### Why the two papers disagree + +The disagreement is concentrated on one class: **`vegetation` (label 70)**. SemanticKITTI's `vegetation` label conflates two visually similar but physically very different things — low ground cover (grass, terrain weeds, leaves on flat ground) and overhead foliage / branches / hedge tops. The first is essentially ground; the second is not. + +- The **original Patchwork paper** picked a height-based proxy: `vegetation` points with `z < −1.30 m` w.r.t. the sensor frame count as ground, anything above does not. Simple, but it mislabels overhead foliage in low-mounted sensors and ground vegetation on hills. +- The **Patchwork++ paper** (Sec. IV.A) treats this as fundamentally unresolvable from labels alone and **excludes** `vegetation` from the evaluation entirely: *"the points labeled as vegetation are not evaluated as ground nor non-ground points exceptionally because it is impractical to regard the vegetation as a single ground or non-ground class"*. The points are still fed to the algorithm — only the scoring drops them. + +Either choice is defensible; they just yield different numbers on the same predictions. Always use the protocol that matches the paper you're comparing against. + ### A. `--eval_protocol patchwork` (original Patchwork repo protocol) - **Ground GT** = `{ROAD (40), PARKING (44), SIDEWALK (48), OTHER_GROUND (49), LANE_MARKING (60), VEGETATION (70, only if z < −1.30 m), TERRAIN (72)}` From acb374cab7fd739f9488dd074acdce6cde2cc2d1 Mon Sep 17 00:00:00 2001 From: Hyungtae Lim Date: Thu, 21 May 2026 17:44:36 +0900 Subject: [PATCH 4/4] Finally update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d9dd2df..ce69be7 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ - C++ source code of Patchwork++ ([patchworkpp][sourcecodelink]) - Python binding of Patchwork++ using pybind11 ([python_wrapper][wraplink]) - Examples codes of [C++][cppexamplelink], [Python][pyexamplelink], and [ROS2][rosexamplelink] :thumbsup: -- A reproducible **SemanticKITTI evaluation harness** for both Patchwork and Patchwork++ ([`python/examples/evaluate_semantickitti.py`][evallink]). The two algorithms use **different evaluation protocols** (Patchwork paper vs Patchwork++ paper Sec. IV.A) — see [`USAGE.md`][usagelink] §1 for why and §4 for per-sequence numbers. +- Full suppor of a reproducible **SemanticKITTI evaluation harness** for both Patchwork and Patchwork++ ([`python/examples/evaluate_semantickitti.py`][evallink]). In the papers of Patchwork and Patchwork++, we use **different evaluation protocols** — see [`USAGE.md`][usagelink] §1 for why and §4 for per-sequence numbers. > If you are familiar with ROS1, you can also visit [here][roslink] and try executing ROS1-based Patchwork++!