Skip to main content

Plane segmentation with RANSAC-LP+ for Open3D point clouds

Project description

ransaclpplus

In this repository you can find the code related to the RANSACLPPLUS algorithm.

Table of Contents

Installation

Install the CPU-portable package from PyPI:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install ransaclpplus

For repository development:

git clone https://github.com/jmartinezot/lp4-plus.git
cd lp4-plus
python -m pip install -e .

PyPI installations use CPU execution by default. To enable native CUDA on a machine with the NVIDIA CUDA toolkit and CMake:

ransaclpplus-build-cuda --cuda-architectures "61;75;86;89;90"

See the installation guide for complete installation, CUDA, devcontainer, and troubleshooting instructions.

Docker

Build and run the CPU image:

docker build -f docker/Dockerfile.cpu -t ransaclpplus:cpu .
docker run --rm -it ransaclpplus:cpu

Build and run the native CUDA image:

docker build -f docker/Dockerfile.cuda -t ransaclpplus:cuda .
docker run --rm -it --gpus=all ransaclpplus:cuda

See the Docker guide for architecture selection, dataset mounts, and Open3D display notes.

Publishing

Package releases are published to PyPI from GitHub Releases using trusted publishing. See the PyPI release guide for the one-time PyPI setup, local validation commands, and release procedure.

Basic usage

An example of use:

import ransaclpplus
import open3d as o3d

office_dataset = o3d.data.OfficePointClouds()
office_filename = office_dataset.paths[0]

ransaclpplus_iterations = 200
threshold = 0.02
seed = 42
percentage_chosen_lines = 0.2
percentage_chosen_planes = 0.05

pcd = o3d.io.read_point_cloud(office_filename)
plane_model, inliers = ransaclpplus.segment_plane(pcd, distance_threshold=threshold, num_iterations=ransaclpplus_iterations, 
                                                percentage_chosen_lines = percentage_chosen_lines,
                                                percentage_chosen_planes = percentage_chosen_planes, seed = seed)
number_inliers = len(inliers)
inlier_cloud = pcd.select_by_index(inliers)
inlier_cloud.paint_uniform_color([1, 0, 0])
o3d.visualization.draw_geometries([pcd, inlier_cloud], window_name="RANSACLPPLUS Inliers:  " + str(number_inliers))

You can use native C++ CUDA-accelerated line fitting by setting use_cuda=True:

plane_model, inliers = ransaclpplus.segment_plane(pcd, distance_threshold=threshold, num_iterations=ransaclpplus_iterations, 
                                                percentage_chosen_lines = percentage_chosen_lines, use_cuda = True,
                                                percentage_chosen_planes = percentage_chosen_planes, seed = seed)

Adaptive line selection (optional) can replace fixed percentage_chosen_lines:

plane_model, inliers = ransaclpplus.segment_plane(
    pcd,
    distance_threshold=threshold,
    num_iterations=ransaclpplus_iterations,
    percentage_chosen_lines=0.2,
    percentage_chosen_planes=percentage_chosen_planes,
    line_selection_mode="adaptive_poisson_mixture",
    adaptive_tau=0.5,
    adaptive_em_max_iter=100,
    adaptive_em_tol=1e-6,
    adaptive_min_lines=2,
    adaptive_allow_empty=False,
    seed=seed,
)

Compatibility-filtered pairing (optional) can be enabled for pair generation:

plane_model, inliers = ransaclpplus.segment_plane(
    pcd,
    distance_threshold=threshold,
    num_iterations=ransaclpplus_iterations,
    percentage_chosen_lines=0.2,
    percentage_chosen_planes=percentage_chosen_planes,
    line_selection_mode="adaptive_poisson_mixture",
    adaptive_tau=0.5,
    pairing_filter_enabled=True,
    pairing_min_angle_deg=10.0,
    pairing_max_angle_deg=170.0,
    pairing_max_centroid_distance=0.6,
    seed=seed,
)

Repository Structure

Experiment artifacts are organized with a canonical snapshot and a separate exploratory area:

  • Canonical fixed-vs-adaptive Open3D experiment:
    • results/open3d_fixed_vs_adaptive_alpha/
  • Canonical pairing-ablation snapshots:
    • results/open3d_pairing_ablation_06/
    • results/open3d_pairing_ablation_pairing_max_centroid_20/
    • results/open3d_pairing_ablation_pairing_max_centroid_30/
  • Exploratory sweeps and follow-up tuning runs:
    • results/exploratory/
  • S3DIS validation outputs:
    • results/s3dis_pilot_validation/
    • results/s3dis_validation/

Experiment code and run guide:

  • Script: experiments/run_open3d_fixed_vs_adaptive_alpha.py
  • Script (pairing ablation): experiments/run_open3d_pairing_ablation.py
  • Script (angle-only ablation): experiments/run_open3d_angle_only_ablation.py
  • Script (pairing-ablation post-analysis): experiments/analyze_pairing_ablation_results.py
  • Script (S3DIS pilot validation): experiments/run_s3dis_pilot_validation.py
  • Script (S3DIS full validation): experiments/run_s3dis_validation.py
  • Helper (S3DIS dataset discovery): experiments/s3dis_dataset.py
  • Usage guide: experiments/README_open3d_fixed_vs_adaptive_alpha.md
  • Usage guide (angle-only ablation): experiments/README_open3d_angle_only_ablation.md
  • Reproducibility overview: docs/reproducibility.md

Reproducible Experiments

The canonical Open3D fixed-vs-adaptive-alpha snapshot is preserved in:

  • results/open3d_fixed_vs_adaptive_alpha/

This directory includes:

  • configuration (experiment_config.json)
  • environment and git metadata (environment.json)
  • exact dataset file manifest (dataset_files.txt)
  • raw run-level outputs (raw_runs.csv)
  • aggregated outputs (aggregated_per_file.csv, aggregated_global.csv)

Canonical pairing-ablation snapshots are stored separately by pairing_max_centroid_distance:

  • results/open3d_pairing_ablation_06/
  • results/open3d_pairing_ablation_pairing_max_centroid_20/
  • results/open3d_pairing_ablation_pairing_max_centroid_30/

For each snapshot, derived post-analysis artifacts are generated in-place:

  • analysis/*.csv and analysis/*.md summaries
  • plots/*.png paper-oriented figures (runtime-vs-inliers, boxplots, pair-filter and rejection breakdowns, per-scene deltas)

Exploratory tuning runs remain intentionally separated in results/exploratory/ and are not the primary paper snapshots.

Pairing-ablation post-analysis command (single snapshot):

python experiments/analyze_pairing_ablation_results.py \
  --results-dir results/open3d_pairing_ablation_06 \
  --plot-format png \
  --title-suffix "(pairing_max_centroid_distance=0.6)"

Manual multi-snapshot analysis sequence:

python experiments/analyze_pairing_ablation_results.py --results-dir results/open3d_pairing_ablation_06 --plot-format png --title-suffix "(pairing_max_centroid_distance=0.6)"
python experiments/analyze_pairing_ablation_results.py --results-dir results/open3d_pairing_ablation_pairing_max_centroid_20 --plot-format png --title-suffix "(pairing_max_centroid_distance=2.0)"
python experiments/analyze_pairing_ablation_results.py --results-dir results/open3d_pairing_ablation_pairing_max_centroid_30 --plot-format png --title-suffix "(pairing_max_centroid_distance=3.0)"

Completed follow-up snapshot:

  • results/open3d_angle_only_ablation/

Angle-only rerun command:

python experiments/run_open3d_angle_only_ablation.py \
  --output-dir results/open3d_angle_only_ablation \
  --num-runs 10 \
  --n-line-iterations 250 \
  --threshold 0.03 \
  --beta 0.05 \
  --fixed-alpha 0.2 \
  --adaptive-tau 0.5 \
  --pairing-min-angle-deg 10 \
  --pairing-max-angle-deg 170 \
  --pairing-max-centroid-distance 3.0 \
  --use-cuda

S3DIS validation workflow:

  • S3DIS is expected to be mounted read-only at /datasets/S3DIS.
  • If S3DIS_DATA_ROOT is set, the S3DIS scripts use it by default; otherwise they fall back to /datasets/S3DIS.
  • Run the pilot first on Area_1, review outputs, then launch the full validation later if approved.
  • Search is performed on a reduced point set for efficiency:
    • optional voxelized cloud
    • optional deterministic search subset from that voxelized cloud
  • Final support is re-evaluated on the full raw point cloud for reviewer-facing reporting.
  • For S3DIS validation, the top-level reported final support metric is intended to be the raw-cloud support.

S3DIS pilot command:

python experiments/run_s3dis_pilot_validation.py \
  --output-dir results/s3dis_pilot_validation \
  --num-runs 10 \
  --n-line-iterations 250 \
  --threshold 0.03 \
  --beta 0.05 \
  --fixed-alpha 0.2 \
  --adaptive-tau 0.5 \
  --pairing-min-angle-deg 10 \
  --pairing-max-angle-deg 170 \
  --voxel-size 0.02 \
  --search-subset-size 30000 \
  --search-subset-seed 0 \
  --use-cuda

S3DIS full validation command:

python experiments/run_s3dis_validation.py \
  --output-dir results/s3dis_validation \
  --num-runs 10 \
  --n-line-iterations 250 \
  --threshold 0.03 \
  --beta 0.05 \
  --fixed-alpha 0.2 \
  --adaptive-tau 0.5 \
  --pairing-min-angle-deg 10 \
  --pairing-max-angle-deg 170 \
  --voxel-size 0.02 \
  --search-subset-size 30000 \
  --search-subset-seed 0 \
  --use-cuda

S3DIS post-analysis command:

python experiments/analyze_pairing_ablation_results.py \
  --results-dir results/s3dis_pilot_validation \
  --plot-format png \
  --title-suffix "(S3DIS pilot validation)"

Key conservative findings from the canonical snapshot:

  • Adaptive alpha has higher mean best-plane inliers than fixed alpha (128071.33 vs 127446.12).
  • Adaptive alpha has higher mean runtime than fixed alpha (260.54 ms vs 232.97 ms).
  • Per-file mean inlier comparison: adaptive better on 103/110, equal on 3/110, worse on 4/110.
  • Per-file mean runtime comparison: adaptive slower on 105/110, faster on 5/110.

All values above are derived from:

  • results/open3d_fixed_vs_adaptive_alpha/aggregated_global.csv
  • results/open3d_fixed_vs_adaptive_alpha/per_file_win_loss_summary.csv

Method

RANSAC-LP4 is a plane-detection method that reduces expensive full point-to-plane evaluations while keeping robustness to outliers.

Instead of sampling planes directly from three points, it first samples lines (two-point hypotheses), then constructs plane candidates from pairs of promising lines.

The method has three stages:

  1. Candidate line generation: sample n lines, score each line by inlier count with threshold t, keep N_l = floor(alpha * n) best lines.
  2. Candidate plane generation from line pairs: generate all unique pairs of retained lines, fit one plane per pair, rank by local fit quality (SSE), keep N_pi = floor(beta * N_lambda) where N_lambda = N_l * (N_l - 1) / 2.
  3. Final plane evaluation: evaluate only retained candidate planes on the full point cloud and select the plane with highest inlier support.

Parameters:

  • Shared with classical RANSAC: n, t
  • Specific to RANSAC-LP4: alpha, beta

Adaptive line-selection option:

  • Fixed mode (line_selection_mode="fixed_alpha"): keeps the top alpha fraction by line support.
  • Adaptive mode (line_selection_mode="adaptive_poisson_mixture"): fits a 2-component Poisson mixture to line supports and keeps lines with posterior P(good | support) >= tau.
  • tau controls strictness: higher tau keeps fewer lines.
  • The effective retained fraction is alpha_adapt = kept_lines / n.
  • Adaptive mode exposes rho_hat = sqrt(w), where w is the estimated mixture weight of the “good-line” component.

Limitations:

  • The adaptive selector assumes line supports are reasonably modeled by a 2-component Poisson mixture.
  • If supports are nearly constant or EM is unstable, the implementation falls back to deterministic top-support retention with minimum-line safeguards.

Repository implementation notes:

  • Planes from two lines are fit with a four-point least-squares (SVD) fit.
  • Step-2 quality uses four-point SSE.
  • Final scoring uses standard inlier counting against threshold t.

Current Research Status

Completed:

  • baseline LP4 implementation
  • adaptive alpha line selection
  • reproducible Open3D fixed-vs-adaptive canonical experiment

Interpretation from completed evidence:

  • Adaptive alpha improves best-plane quality in most files.
  • Adaptive alpha usually increases runtime, consistent with keeping more lines and therefore increasing line-pair combinations.

Current pairing focus:

  • compatibility-filtered pairing with angle and support-centroid distance gates
  • four-way Open3D ablation:
    • fixed alpha
    • adaptive alpha
    • fixed alpha + compatibility-filtered pairing
    • adaptive alpha + compatibility-filtered pairing
  • completed angle-gate isolation ablation:
    • adaptive_alpha
    • adaptive_alpha_cf_pairing_angle_only
    • adaptive_alpha_cf_pairing_angle_plus_distance (pairing_max_centroid_distance=3.0)

Prepared artifacts:

  • script: experiments/run_open3d_pairing_ablation.py
  • script: experiments/run_open3d_angle_only_ablation.py
  • script: experiments/analyze_pairing_ablation_results.py
  • canonical snapshot folders:
    • results/open3d_pairing_ablation_06/
    • results/open3d_pairing_ablation_pairing_max_centroid_20/
    • results/open3d_pairing_ablation_pairing_max_centroid_30/
  • method note: docs/open3d_pairing_ablation.md
  • research report: docs/research_report.md

Next validation target:

  • minimal S3DIS validation with:
    • fixed_alpha
    • adaptive_alpha
    • adaptive_alpha_cf_pairing_angle_only
  • pilot-first execution on Area_1
  • full-dataset execution only after pilot review

CUDA backend

The project uses a native C++ CUDA shared library for CUDA execution. Numba is not required.

Native backend coverage includes:

  • single plane inlier counting
  • batched plane inlier counting
  • single line inlier counting
  • plane inlier index collection

Runtime behavior:

  • ransaclpplus.ransaccuda preserves the existing Python helper names while routing all CUDA work through ransaclpplus.nativecuda.
  • use_cuda=True requires the native shared library. A clear runtime error is raised when it is unavailable.

Building the native CUDA backend

Build from ransaclpplus/native/cuda:

cmake -S . -B build
cmake --build build -j

The Python loader checks:

  • RANSACLPPLUS_CUDA_LIB (if set)
  • ransaclpplus/native/cuda/build/libransaclpplus_cuda.so (Linux)
  • ransaclpplus/native/cuda/build/libransaclpplus_cuda.dylib (macOS)
  • ransaclpplus/native/cuda/build/Release/ransaclpplus_cuda.dll (Windows)

Quick verification:

python -c "from ransaclpplus.nativecuda import native_backend_available; print(native_backend_available())"

CUDA benchmark

Benchmark native CUDA kernels and persistent-context cache behavior with:

python -m ransaclpplus.benchmark_cuda_backends --points 200000 --planes 64 --warmup 2 --repetitions 10

Optional JSON output:

python -m ransaclpplus.benchmark_cuda_backends --json-out benchmark_results.json

Historical migration measurements comparing native CUDA with the former Numba backend are preserved in:

  • docs/reports/cuda_vs_numba_report.md
  • docs/reports/cuda_numba_analysis.json
  • docs/reports/cuda_numba_analysis_after_async_pinned.json (latest optimized baseline)
  • docs/reports/cuda_numba_analysis_after_plane_cache.json (latest plane-cache run)
  • docs/reports/cuda_optimization_comparison.md (cross-version comparison)
  • docs/reports/optimization_backups/ (source snapshots by optimization stage)

Backup and artifact policy:

  • Keep historical benchmark JSON files; append new versioned artifacts instead of overwriting old ones.
  • Keep snapshot copies of changed optimization source files in docs/reports/optimization_backups/ before major tuning changes.
  • Prefer explicit version/date suffixes in artifact names for reproducible cross-version comparisons.

Historical optimized baseline summary (native over former Numba backend, plane-cache run):

  • Small (4096 points, 12 planes): plane 15.42x, line 14.83x, batched 32.42x
  • Medium (50000 points, 32 planes): plane 16.19x, line 15.39x, batched 7.29x
  • Large (200000 points, 64 planes): plane 9.68x, line 10.22x, batched 2.27x

If the package is installed with scripts, the equivalent command is:

ransaclpplus-benchmark-cuda --points 200000 --planes 64

Campaigns

The repository now includes paper-oriented LP4 campaign families for Open3D and S3DIS. The broader campaign roots remain reusable for reruns, and the compact minimum paper-oriented subset has already been executed in versioned result roots.

Reusable campaign roots:

  • results/open3d_core_robustness/
  • results/s3dis_core_robustness/
  • results/open3d_adaptive_tau_sweep/
  • results/s3dis_adaptive_tau_sweep/
  • results/open3d_budget_sweep/
  • results/s3dis_budget_sweep/
  • results/s3dis_preprocessing_stability/
  • results/open3d_vs_open3d_ransac/
  • results/s3dis_vs_open3d_ransac/
  • results/open3d_vs_open3d_ransac_lo/
  • results/s3dis_vs_open3d_ransac_lo/

Campaign entrypoints:

  • experiments/run_open3d_core_robustness.py
  • experiments/run_s3dis_core_robustness.py
  • experiments/run_open3d_adaptive_tau_sweep.py
  • experiments/run_s3dis_adaptive_tau_sweep.py
  • experiments/run_open3d_budget_sweep.py
  • experiments/run_s3dis_budget_sweep.py
  • experiments/run_s3dis_preprocessing_stability.py
  • experiments/run_open3d_vs_open3d_ransac.py
  • experiments/run_s3dis_vs_open3d_ransac.py
  • experiments/run_open3d_vs_open3d_ransac_lo.py
  • experiments/run_s3dis_vs_open3d_ransac_lo.py

Unified post-analysis entrypoint:

  • experiments/lp4_campaign_analysis.py

Primary metrics:

  • Open3D: best_plane_inliers / best_plane_inlier_ratio
  • S3DIS: raw-cloud final support via best_plane_inliers_raw, also mapped to top-level best_plane_inliers

External baseline policy:

  • Plain external baseline: Open3D segment_plane
  • LO-style external baseline: Open3D segment_plane plus local inlier refit rounds
  • open3d_segment_plane_lo is a local-optimization proxy baseline, not a formal true LO-RANSAC implementation
  • Hypothesis generation runs on the designated search-stage point set
  • Final support is evaluated with the same final metric convention as the corresponding LP4 campaign
  • For S3DIS, raw-cloud final support remains the primary reported metric
  • Baseline parameters are written explicitly to experiment_config.json and raw_runs.csv

Manual run commands:

python experiments/run_open3d_core_robustness.py --output-dir results/open3d_core_robustness --num-runs 30 --n-line-iterations 250 --threshold 0.03 --beta 0.05 --fixed-alpha 0.2 --adaptive-tau 0.5 --pairing-min-angle-deg 10 --pairing-max-angle-deg 170 --use-cuda
python experiments/run_s3dis_core_robustness.py --output-dir results/s3dis_core_robustness --num-runs 30 --n-line-iterations 250 --threshold 0.03 --beta 0.05 --fixed-alpha 0.2 --adaptive-tau 0.5 --pairing-min-angle-deg 10 --pairing-max-angle-deg 170 --voxel-size 0.02 --search-subset-size 30000 --search-subset-seed 0 --use-cuda
python experiments/run_open3d_adaptive_tau_sweep.py --output-dir results/open3d_adaptive_tau_sweep --num-runs 10 --n-line-iterations 250 --threshold 0.03 --beta 0.05 --fixed-alpha 0.2 --pairing-min-angle-deg 10 --pairing-max-angle-deg 170 --use-cuda
python experiments/run_s3dis_adaptive_tau_sweep.py --output-dir results/s3dis_adaptive_tau_sweep --num-runs 10 --n-line-iterations 250 --threshold 0.03 --beta 0.05 --fixed-alpha 0.2 --pairing-min-angle-deg 10 --pairing-max-angle-deg 170 --voxel-size 0.02 --search-subset-size 30000 --search-subset-seed 0 --use-cuda
python experiments/run_open3d_budget_sweep.py --output-dir results/open3d_budget_sweep --num-runs 10 --threshold 0.03 --beta 0.05 --fixed-alpha 0.2 --adaptive-tau 0.5 --pairing-min-angle-deg 10 --pairing-max-angle-deg 170 --use-cuda
python experiments/run_s3dis_budget_sweep.py --output-dir results/s3dis_budget_sweep --num-runs 10 --threshold 0.03 --beta 0.05 --fixed-alpha 0.2 --adaptive-tau 0.5 --pairing-min-angle-deg 10 --pairing-max-angle-deg 170 --voxel-size 0.02 --search-subset-size 30000 --search-subset-seed 0 --use-cuda
python experiments/run_s3dis_preprocessing_stability.py --output-dir results/s3dis_preprocessing_stability --num-runs 10 --n-line-iterations 250 --threshold 0.03 --beta 0.05 --fixed-alpha 0.2 --adaptive-tau 0.5 --pairing-min-angle-deg 10 --pairing-max-angle-deg 170 --voxel-size 0.02 --search-subset-size 30000 --search-subset-seed 0 --use-cuda

External-baseline run commands:

python experiments/run_open3d_vs_open3d_ransac.py --output-dir results/open3d_vs_open3d_ransac --num-runs 10 --n-line-iterations 250 --threshold 0.03 --beta 0.05 --fixed-alpha 0.2 --adaptive-tau 0.5 --pairing-min-angle-deg 10 --pairing-max-angle-deg 170 --baseline-ransac-n 3 --baseline-lo-refit-max-rounds 2 --use-cuda
python experiments/run_s3dis_vs_open3d_ransac.py --output-dir results/s3dis_vs_open3d_ransac --num-runs 10 --n-line-iterations 250 --threshold 0.03 --beta 0.05 --fixed-alpha 0.2 --adaptive-tau 0.5 --pairing-min-angle-deg 10 --pairing-max-angle-deg 170 --voxel-size 0.02 --search-subset-size 30000 --search-subset-seed 0 --baseline-ransac-n 3 --baseline-lo-refit-max-rounds 2 --use-cuda
python experiments/run_open3d_vs_open3d_ransac_lo.py --output-dir results/open3d_vs_open3d_ransac_lo --num-runs 10 --n-line-iterations 250 --threshold 0.03 --beta 0.05 --fixed-alpha 0.2 --adaptive-tau 0.5 --pairing-min-angle-deg 10 --pairing-max-angle-deg 170 --baseline-ransac-n 3 --baseline-lo-refit-max-rounds 2 --use-cuda
python experiments/run_s3dis_vs_open3d_ransac_lo.py --output-dir results/s3dis_vs_open3d_ransac_lo --num-runs 10 --n-line-iterations 250 --threshold 0.03 --beta 0.05 --fixed-alpha 0.2 --adaptive-tau 0.5 --pairing-min-angle-deg 10 --pairing-max-angle-deg 170 --voxel-size 0.02 --search-subset-size 30000 --search-subset-seed 0 --baseline-ransac-n 3 --baseline-lo-refit-max-rounds 2 --use-cuda

Analysis commands:

python experiments/lp4_campaign_analysis.py --results-dir results/open3d_core_robustness --plot-format png
python experiments/lp4_campaign_analysis.py --results-dir results/s3dis_core_robustness --plot-format png
python experiments/lp4_campaign_analysis.py --results-dir results/open3d_adaptive_tau_sweep --plot-format png
python experiments/lp4_campaign_analysis.py --results-dir results/s3dis_adaptive_tau_sweep --plot-format png
python experiments/lp4_campaign_analysis.py --results-dir results/open3d_budget_sweep --plot-format png
python experiments/lp4_campaign_analysis.py --results-dir results/s3dis_budget_sweep --plot-format png
python experiments/lp4_campaign_analysis.py --results-dir results/s3dis_preprocessing_stability --plot-format png
python experiments/lp4_campaign_analysis.py --results-dir results/open3d_vs_open3d_ransac --plot-format png
python experiments/lp4_campaign_analysis.py --results-dir results/s3dis_vs_open3d_ransac --plot-format png
python experiments/lp4_campaign_analysis.py --results-dir results/open3d_vs_open3d_ransac_lo --plot-format png
python experiments/lp4_campaign_analysis.py --results-dir results/s3dis_vs_open3d_ransac_lo --plot-format png

Command-printer helpers:

  • scripts/print_open3d_core_commands.sh
  • scripts/print_s3dis_core_commands.sh
  • scripts/print_sweep_commands.sh

Executed minimum paper-oriented result roots:

  • results/synthetic_lp4_benchmark_paper_minimum_20260313/
  • results/open3d_budget_sweep_paper_minimum_20260313/
  • results/open3d_lp4_proposal_lo_paper_minimum_20260313/

Documentation with Sphinx

This repository includes a Sphinx configuration under docs/ for the package reference and the main project guides.

Install documentation dependencies:

pip install -e ".[docs]"

Build HTML docs:

make -C docs html

The generated site will be available at docs/_build/html/index.html. It includes:

  • repository overview and navigation page
  • API reference for the package modules
  • method overview
  • research report
  • reproducibility guide
  • benchmark and report pages under docs/reports/

The repository also includes Read the Docs deployment configuration. See the Read the Docs deployment guide for the one-time project import and build settings.

Documentation expectations for ongoing development:

  • new public functionality should be documented with Sphinx-compatible docstrings
  • new user-visible workflows or features should be reflected in the relevant page under docs/

Tests

The repository uses pytest for automated tests.

Run the full suite:

pytest -q

Run a focused test file:

pytest -q tests/test_ransaclpplus_api.py

Current baseline status in this environment:

  • broad suite: 91 passed, 5 skipped

Testing expectations for ongoing development:

  • behavior changes should include updated or new automated tests
  • new public additions and user-visible workflows should ship with both tests and Sphinx documentation in the same change

Visual Step-by-Step Test (Open3D)

A manual visual test is available at tests/test_ransaclpplus_visual_steps.py. It opens Open3D windows for:

  • Step 1: sampled lines retained after line scoring
  • Step 2: candidate planes generated from retained line pairs
  • Step 3: final inliers of the best-scoring plane

Run it with:

RANSACLPPLUS_VISUAL_TEST=1 pytest -m visual -s

Or use the helper script:

./scripts/run_visual_test.sh

Close each Open3D window to continue to the next stage.

If you run inside the devcontainer, X11 forwarding must be enabled on your host.

Run The Devcontainer From CLI (JSON-Equivalent)

The .devcontainer/devcontainer.json configuration can be reproduced from the command line with the following commands.

Exact devcontainer.json parity (including features) via Dev Container CLI:

devcontainer up --workspace-folder .

Plain Docker workflow approximating the build, run, and post-create settings:

Build the image from the same Dockerfile/context:

docker build -f .devcontainer/Dockerfile -t ransaclpplus-dev .

Run the container with the same GPU, env vars, X11, and workspace mount behavior:

REPOSITORY_ROOT="$(pwd)"
WORKSPACE_NAME="$(basename "${REPOSITORY_ROOT}")"
HOST_S3DIS_DATA_ROOT="${S3DIS_DATA_ROOT:-${HOME}/S3DIS/Stanford3dDataset_v1.2}"

docker run --rm -it \
  --gpus=all \
  --user vscode \
  --env DISPLAY="${DISPLAY}" \
  --env NVIDIA_VISIBLE_DEVICES=all \
  --env NVIDIA_DRIVER_CAPABILITIES=compute,utility \
  --env QT_X11_NO_MITSHM=1 \
  --env RANSACLPPLUS_CUDA_ARCH=61 \
  --env OPEN3D_DATA_ROOT=/home/vscode/open3d_data \
  --env S3DIS_DATA_ROOT=/datasets/S3DIS \
  --volume /tmp/.X11-unix:/tmp/.X11-unix:rw \
  --mount "type=bind,source=${REPOSITORY_ROOT},target=/workspaces/${WORKSPACE_NAME}" \
  --mount "type=bind,source=${HOST_S3DIS_DATA_ROOT},target=/datasets/S3DIS,readonly" \
  --workdir "/workspaces/${WORKSPACE_NAME}" \
  --name ransaclpplus-dev \
  ransaclpplus-dev \
  bash

Run the same post-create setup command defined in devcontainer.json:

docker exec -u vscode -it ransaclpplus-dev bash -lc \
  'pip install -e . && cmake -S ransaclpplus/native/cuda -B ransaclpplus/native/cuda/build -DCMAKE_CUDA_ARCHITECTURES=${RANSACLPPLUS_CUDA_ARCH} && cmake --build ransaclpplus/native/cuda/build -j'

Notes:

  • Run the plain Docker commands from the repository root. Set S3DIS_DATA_ROOT on the host when the dataset is not stored at the default path shown above.
  • The plain Docker workflow mirrors the core runArgs, containerEnv, workspaceMount, workspaceFolder, remoteUser, and postCreateCommand settings. Only the Dev Container CLI command applies features and provides exact devcontainer.json behavior.
  • For Open3D windows from inside the container, host X11 access is required (for example, xhost +local:docker on Linux before running, and revert later with xhost -local:docker).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ransaclpplus-0.1.0.tar.gz (71.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ransaclpplus-0.1.0-py3-none-any.whl (71.2 kB view details)

Uploaded Python 3

File details

Details for the file ransaclpplus-0.1.0.tar.gz.

File metadata

  • Download URL: ransaclpplus-0.1.0.tar.gz
  • Upload date:
  • Size: 71.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ransaclpplus-0.1.0.tar.gz
Algorithm Hash digest
SHA256 bcf07d3bd844cef27a84a19ef19b31f9f230ae30b7eaa0a58345aca6c68cf6ab
MD5 0d5496b9d37960223b540e867e86a5fc
BLAKE2b-256 506f751a5feb08d26b97f00fd5685dda9ebd55f292298a48d4c4ab7f8ee66f3a

See more details on using hashes here.

Provenance

The following attestation bundles were made for ransaclpplus-0.1.0.tar.gz:

Publisher: publish-pypi.yml on jmartinezot/lp4-plus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ransaclpplus-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ransaclpplus-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 71.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ransaclpplus-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e40bc35c673c43c64e69b475b75a7c8d097f4eca892ae322ec472b9b671b6d9e
MD5 3d9cd20b914ed0a48798ada907f7ab32
BLAKE2b-256 bf8288c90b2a3ffd64001747fb8a717b79044a176c254fa029f1d73661c96e3f

See more details on using hashes here.

Provenance

The following attestation bundles were made for ransaclpplus-0.1.0-py3-none-any.whl:

Publisher: publish-pypi.yml on jmartinezot/lp4-plus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page