Repository navigation
feat(core): drop PCL + Boost; release travel-seg 1.1.0 with cibuildwheel (Linux + macOS + Windows) - #29
Merged
Conversation
…0 with cibuildwheel matrix (Linux + macOS + Windows)
Plan A from the wheel-matrix discussion: rather than fighting per-platform
PCL installs (vcpkg PCL on Windows alone is a 30-min wheel build), strip
PCL + Boost out of the algorithm core. The core only ever borrowed a tiny
slice of PCL — type wrappers, plus a single algorithm call to
`pcl::computeMeanAndCovarianceMatrix`. Replacing those is a contained
change.
What's in cpp/travel/core now:
* New `travel/types.hpp` ships self-contained replacements:
- `travel::PCLHeader` (POD), `travel::PointCloud<T>` (vector-with-header
container with the PCL-shaped API surface we actually call: size,
empty, clear, reserve, resize, push_back, emplace_back, operator[],
at, begin/end, operator+= and `using Ptr = std::shared_ptr<...>`).
- `travel::PointXYZ`, `travel::PointXYZI` (POD).
- Global `PointXYZILID` retained but with the `PCL_ADD_POINT4D` macro
replaced by an equivalent anonymous union, and the
`POINT_CLOUD_REGISTER_POINT_STRUCT` macro dropped (we never used the
PCL runtime field registry, only the field layout).
- `travel::computeMeanAndCovarianceMatrix` ports PCL's accumulator
pattern bit-for-bit: same Eigen 1x9 row-major storage, same single-
pass formulation, same float order, same coeffRef indices.
* `tgs.hpp` / `aos.hpp` / `save_labels.hpp` / `kitti_loader.hpp` now
refer to `travel::PointCloud<...>` and `travel::computeMeanAndCovarianceMatrix`
instead of the `pcl::` versions.
* `aos.hpp` switched its two `boost::optional<int>` cluster-size members
to C++17 `std::optional<int>`, dropping the `<boost/optional.hpp>`
include.
* `kitti_loader.hpp` switched from `boost::filesystem` + `boost::format`
to `<filesystem>` + `snprintf`. Same behaviour, no boost dependency.
* `cpp/travel/CMakeLists.txt` now only does `find_package(Eigen3)`. PCL,
Boost, and the MPI workaround for VTK 9.1 are gone. Project version
bumped to 1.1.0.
* `cpp/travel/cmake/travelConfig.cmake` likewise only emits
`find_dependency(Eigen3)`.
* `cpp/examples/CMakeLists.txt` and `cpp/tests/CMakeLists.txt` drop
PCL + MPI find_package; both link only `travel::travel_core`.
* `cpp/examples/src/run_travel_kitti.cpp` swapped `pcl::io::savePCDFileBinary`
output for plain Nx4/Nx5 float32 .bin writers — KITTI velodyne shape,
no PCL dependency.
* `cpp/tests/regression_kitti.cpp` updated to use `travel::PointCloud<>`.
* `.github/workflows/ci.yml`'s cpp-examples job now checks for `.bin`
outputs instead of `.pcd`.
What stays the same:
* The ROS 2 wrapper (ros/) keeps PCL — it still needs `pcl::fromROSMsg`
/ `pcl::toROSMsg` for ROS message conversion. The boundary in
`ros/src/travel_node.cpp` now converts pcl::PointCloud<pcl::PointXYZ>
-> travel::PointCloud<PointXYZILID> on input, and the publish path
copies travel::PointCloud<PointXYZILID> back out into
pcl::PointXYZI / pcl::PointXYZL clouds for `pcl::toROSMsg`. PCL stays
as a *ros wrapper* dependency, not a core dependency.
* The Python package (python/) is unchanged in behaviour. The pybind
module just refers to `travel::PointCloud<PointXYZILID>` instead of
`pcl::PointCloud<PointXYZILID>`.
travel-seg version bumps to 1.1.0 across pyproject.toml,
travel_seg/__init__.py, and the pybind `__version__` attribute.
`.github/workflows/release.yml` is rewritten to a cibuildwheel matrix:
* sdist on ubuntu-22.04
* wheels on ubuntu-22.04 (manylinux_2_17 x86_64), macos-14
(arm64 + x86_64), windows-2022 (win_amd64)
* CIBW_BEFORE_ALL_LINUX="yum install -y eigen3-devel"
* CIBW_BEFORE_ALL_MACOS="brew install eigen"
* CIBW_BEFORE_ALL_WINDOWS="vcpkg install eigen3:x64-windows" with
CMAKE_PREFIX_PATH set so cmake finds it.
* CIBW_SKIP="pp* *-musllinux_*" — CPython only, manylinux only.
* Trusted-Publisher PyPI upload only when run from a git tag (v*).
Verification (CLAUDE.md "never break the pipeline" rule):
* cpp/tests/regression_kitti against cpp/tests/data/kitti00_000000_gold.bin
-> REGRESSION PASS, bit-identical (374008 bytes) on:
- macOS arm64 + Apple Silicon Homebrew clang + Eigen 3.4.0
- Ubuntu 24.04 + GCC 13.3 + libeigen3-dev (linux/arm64 docker)
i.e. the algorithm output on KITTI sequence 00 frame 0 with seed=42
is byte-for-byte the same as the gold dump captured pre-PCL-removal.
* python/tests/ -> 7/7 pass on macOS arm64 (full editable rebuild).
Initial cibuildwheel run on PR #29 surfaced one issue per platform: * Linux: manylinux2014 (CentOS 7) yum repos do not have eigen3-devel. CIBW_BEFORE_ALL_LINUX="yum install -y eigen3-devel" failed with "No package eigen3-devel available". * macOS x86_64: cp38 default deployment target is 10.9; std::thread / std::shared_ptr require 10.13+ in libc++. The build failed with "'operator delete' is unavailable: introduced in macOS 10.12". * Windows: aos.hpp used the bare type `uint` (POSIX-only typedef from sys/types.h). MSVC errored at the AOSNode/Point member declarations with "syntax error: '='". Fixes: * aos.hpp: replace every bare `uint` with `std::uint32_t` (5 sites: AOSNode::start/end, Point::idx, two locals in labelPointcloud). Add <cstdint> include. Header reordering of the include block while there. * cpp/travel/CMakeLists.txt: Eigen find_package now falls back to FetchContent-fetching Eigen 3.4.0 from upstream GitLab when the system doesn't have it. KITTI regression bit-identical against the gold dump verified with the FetchContent path on macOS arm64 (`-DCMAKE_DISABLE_FIND_PACKAGE_Eigen3=ON`). This removes the need for per-platform yum/brew/vcpkg setup in cibuildwheel — every wheel build just runs `cmake -S cpp/travel ...` and the FetchContent path fires when needed. * .github/workflows/release.yml: - Drop CIBW_BEFORE_ALL_LINUX / _MACOS / _WINDOWS now that Eigen is handled via FetchContent. Wheels build straight from the source tree; no system package install on the cibuildwheel container. - Add CIBW_ENVIRONMENT_MACOS="MACOSX_DEPLOYMENT_TARGET=10.13" so libc++ std::thread / std::shared_ptr resolve on the cp38 x86_64 cross-build. - Skip 32-bit Linux (manylinux_i686) and Windows (win32) to keep the matrix tight; users on those niches can still build from sdist. CIBW_SKIP grew to "pp* *-manylinux_i686 *-musllinux_* *-win32".
Second wheel-matrix run got Linux + macOS to green and revealed the next Windows issue: tgs.hpp and aos.hpp use bare M_PI in 9 places, but MSVC's <cmath> does not define M_PI by default — it is a POSIX / GNU extension. The Windows wheel build failed with 9 instances of "error C2065: 'M_PI': undeclared identifier". Define M_PI once in travel/types.hpp (which every other core header transitively includes) under an `#ifndef` guard. POSIX / GNU compilers that already define it via <cmath> are unaffected. The numeric value is the long double form used by glibc, truncated to double when assigned.
Third wheel-matrix run got Linux + macOS green again, Windows still failing — this time on `ssize_t` redefinition. MSVC does not provide a top-level `ssize_t`; it gets defined transitively by some Python / pybind11 headers, and our binding then redeclared it. Cascading parse errors followed. Use the qualified `py::ssize_t` (pybind11's portable alias) at all three usage sites in numpyToCloud. POSIX / Linux toolchains where bare `ssize_t` was already in scope keep working — `py::ssize_t` is just a typedef there too.
LimHyungTae
added a commit
that referenced
this pull request
May 10, 2026
…badges
* Title: "TRAVEL for RA-L'22 w/ IROS Option" -> "TRAVEL: Traversable
Ground and Above-Ground Object Segmentation". The award subtitle
("Best Paper Award winner from RA-L 2022") stays as <h3>.
* New badge rows, modeled on KISS-Matcher:
- Row 1 (identity): C++, Python, ROS2-Humble|Jazzy, Ubuntu, macOS,
Windows. The Windows badge reflects v1.1.0 prebuilt-wheel support
(cibuildwheel matrix landed in #29).
- Row 2 (existing media/paper): unchanged YouTube×2, RA-L, arXiv.
- Row 3 (status): GitHub Actions CI workflow badge + PyPI version
badge for travel-seg.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Plan A from the wheel-matrix discussion: rather than fight per-platform PCL installs (vcpkg PCL alone makes a Windows wheel build ~30 min), strip PCL + Boost out of the algorithm core. The core only borrowed a tiny slice of PCL — type wrappers, plus a single algorithm call to `pcl::computeMeanAndCovarianceMatrix`. Replacing those is contained.
Why
Goal: `pip install travel-seg` on macOS arm64 / Linux x86_64 / Windows x86_64 all picks up a prebuilt wheel for CPython 3.8–3.13. Patchwork++ already does this; it's possible because that project only depends on Eigen. After this PR, travel-seg is in the same bucket.
What changed in the core
Why this is safe under the "never break the pipeline" rule
The fix preserves byte-for-byte output. `computeMeanAndCovarianceMatrix` was the one real PCL algorithm call; the port keeps the exact float-arithmetic order PCL used.
```
$ ./build/tests/regression_kitti kitti00_000000.bin /tmp/run.bin cpp/tests/data/kitti00_000000_gold.bin
REGRESSION PASS: bit-identical to cpp/tests/data/kitti00_000000_gold.bin (374008 bytes)
```
Verified bit-identical on:
Python: `pytest python/tests/` -> 7/7 passed on macOS arm64.
ROS wrapper
`ros/` keeps PCL — it still needs `pcl::fromROSMsg` / `pcl::toROSMsg` for ROS message conversion. The boundary in `ros/src/travel_node.cpp` now converts `pcl::PointCloudpcl::PointXYZ` → `travel::PointCloud` on input, and copies the algorithm output back out into `pcl::PointXYZI` / `pcl::PointXYZL` clouds for the publish path. PCL stays a ros wrapper dependency, not a core dependency.
Wheel matrix
`.github/workflows/release.yml` rewritten to a cibuildwheel matrix:
Test plan