diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml index a8ad707..d38d30c 100644 --- a/.github/workflows/cpp.yml +++ b/.github/workflows/cpp.yml @@ -13,14 +13,11 @@ jobs: cpp_api: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [ubuntu-24.04, ubuntu-22.04, windows-2022] # TODO(hlim): Support Mac macos-14, macos-15] + os: [ubuntu-24.04, ubuntu-22.04, windows-2022, macos-14] steps: - - uses: actions/checkout@v3 - - name: Setup cmake - uses: jwlawson/actions-setup-cmake@v1.13 - with: - cmake-version: "3.25.x" + - uses: actions/checkout@v4 - name: Configure CMake run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ${{github.workspace}}/cpp/ - name: Build @@ -38,7 +35,7 @@ jobs: os: [ubuntu-24.04, ubuntu-22.04] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Cache dependencies uses: actions/cache@v4 with: diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 0058454..21c49f6 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -11,8 +11,8 @@ jobs: name: Pre-commit checks runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: "3.10" - - uses: pre-commit/action@v3.0.0 + - uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index e4807b6..943650c 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -14,30 +14,32 @@ jobs: name: Build source distribution runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build sdist run: pipx run build --sdist ${{github.workspace}}/python/ - name: Move sdist to dist run: mkdir -p dist && mv ${{github.workspace}}/python/dist/*.tar.gz dist/ - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: + name: sdist path: dist/*.tar.gz cibuildwheel: name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [ubuntu-22.04, windows-2022] # TODO(hlim): Support Mac, macos-14] + os: [ubuntu-22.04, windows-2022, macos-14] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build test wheels (only PRs) if: github.event_name != 'release' - uses: pypa/cibuildwheel@v2.16.5 + uses: pypa/cibuildwheel@v2.21.3 env: # build 1 build per platform just to make sure we can do it later when releasing CIBW_BUILD: "cp310-*" with: @@ -45,12 +47,13 @@ jobs: - name: Build all wheels if: github.event_name == 'release' - uses: pypa/cibuildwheel@v2.16.5 + uses: pypa/cibuildwheel@v2.21.3 with: package-dir: ${{github.workspace}}/python/ - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: + name: wheels-${{ matrix.os }} path: ./wheelhouse/*.whl pypi: @@ -58,10 +61,11 @@ jobs: needs: [cibuildwheel, build_sdist] runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: - name: artifact path: dist + pattern: "{sdist,wheels-*}" + merge-multiple: true - uses: pypa/gh-action-pypi-publish@release/v1 with: diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 5cc1f86..a661e8e 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -9,21 +9,20 @@ jobs: python_package: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [ubuntu-24.04, ubuntu-22.04, windows-2022] # TODO(hlim): Support Mac macos-14, macos-15] + os: [ubuntu-24.04, ubuntu-22.04, windows-2022, macos-14] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python3 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 - name: Install dependencies run: | python -m pip install --upgrade pip - name: Build pip package run: | - python -m pip install --verbose ./python/ - # TODO(hlim) Set unit test - # - name: Run unittests - # run: | - # python -m pip install --verbose './python[test]' - # pytest -rA --verbose ./python/ + python -m pip install --verbose './python[test]' + - name: Run unittests + run: | + pytest -rA --verbose ./python/ diff --git a/.github/workflows/ros.yml b/.github/workflows/ros.yml index 678cf47..e23e2ac 100644 --- a/.github/workflows/ros.yml +++ b/.github/workflows/ros.yml @@ -14,11 +14,7 @@ jobs: release: [humble, jazzy] container: osrf/ros:${{ matrix.release }}-desktop steps: - - name: Setup cmake - uses: jwlawson/actions-setup-cmake@v1.13 - with: - cmake-version: "3.25.x" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run colcon run: source /opt/ros/${{ matrix.release }}/setup.bash && colcon build --event-handlers console_direct+ shell: bash diff --git a/Makefile b/Makefile index 96c05a7..8ed1c9e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,14 @@ +UNAME_S := $(shell uname -s 2>/dev/null || echo Unknown) +ifeq ($(UNAME_S),Darwin) + NPROC := $(shell sysctl -n hw.ncpu 2>/dev/null || echo 4) +else + NPROC := $(shell nproc --all 2>/dev/null || echo 4) +endif + +.PHONY: pyinstall pyinstall_with_demo cppinstall cppinstall_with_demo + pyinstall: @python3 -m pip install --upgrade pip - @pip install numpy @pip install --verbose ./python/ pyinstall_with_demo: pyinstall @@ -8,8 +16,8 @@ pyinstall_with_demo: pyinstall cppinstall: @cmake -Bcpp/build cpp/ - @cmake --build cpp/build -j$(nproc --all) + @cmake --build cpp/build -j$(NPROC) cppinstall_with_demo: @cmake -Bcpp/build cpp/ -DINCLUDE_CPP_EXAMPLES=ON - @cmake --build cpp/build -j$(nproc --all) + @cmake --build cpp/build -j$(NPROC) diff --git a/README.md b/README.md index 76fc484..4065c2a 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,20 @@ > What we need are just minimal dependencies. +**Ubuntu / Debian:** + ```commandline sudo apt-get install g++ build-essential libeigen3-dev python3-pip python3-dev cmake -y ``` +**macOS** (Apple Silicon or Intel): + +```commandline +brew install cmake +``` + +Eigen is fetched automatically by CMake, so no extra system package is required on macOS. The build works with the bundled AppleClang toolchain. + ## :gear: How to build & Run @@ -124,7 +134,8 @@ In addition, you can also check the paper of our baseline, Patchwork. ([arXiv][p ## :triangular_flag_on_post: Tested Environment -- Ubuntu ~~18.04 and~~ 20.04 and 22.04 +- Ubuntu ~~18.04 and~~ 20.04, 22.04, and 24.04 +- macOS 14+ (Apple Silicon) - CMake 3.25.1 (>=3.20, min. Required to install Open3D) - In `scripts/install_open3d.bash`, the installation of the higher version of CMake is already implemented. - Open3D ~~0.15.2~~ 0.18.0 diff --git a/cpp/cmake/pybind11.cmake b/cpp/cmake/pybind11.cmake deleted file mode 100644 index c24911d..0000000 --- a/cpp/cmake/pybind11.cmake +++ /dev/null @@ -1,13 +0,0 @@ -include(FetchContent) - -FetchContent_Declare( - pybind11 - GIT_REPOSITORY https://github.com/pybind/pybind11 - GIT_TAG v2.2.3 -) - -FetchContent_GetProperties(pybind11) -if(NOT pybind11_POPULATED) - FetchContent_Populate(pybind11) - add_subdirectory(${pybind11_SOURCE_DIR} ${pybind11_BINARY_DIR} EXCLUDE_FROM_ALL) -endif() diff --git a/python/pyproject.toml b/python/pyproject.toml index 764d7ac..b9fd219 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -15,6 +15,9 @@ dependencies = [ demo = [ "open3d-cpu>=0.17" ] +test = [ + "pytest" +] [tool.scikit-build] -cmake.args = ["-DINCLUDE_PYTHON_WRAPPER=true"] +cmake.version = ">=3.18,<4" diff --git a/python/tests/test_smoke.py b/python/tests/test_smoke.py new file mode 100644 index 0000000..3769ee3 --- /dev/null +++ b/python/tests/test_smoke.py @@ -0,0 +1,30 @@ +import os + +import numpy as np +import pypatchworkpp + +DATA_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "data") + + +def _read_bin(path): + return np.fromfile(path, dtype=np.float32).reshape(-1, 4) + + +def test_module_imports_and_exposes_api(): + assert hasattr(pypatchworkpp, "Parameters") + assert hasattr(pypatchworkpp, "patchworkpp") + + +def test_estimate_ground_partitions_all_points(): + params = pypatchworkpp.Parameters() + pp = pypatchworkpp.patchworkpp(params) + + scan = _read_bin(os.path.join(DATA_DIR, "000000.bin")) + pp.estimateGround(scan) + + ground = pp.getGround() + nonground = pp.getNonground() + + assert ground.shape[0] > 0 + assert nonground.shape[0] > 0 + assert ground.shape[0] + nonground.shape[0] <= scan.shape[0]